As many of you know, I've been fascinated for some time by Scott's Network
Principles [1].
Several weeks ago, I outlined in a lightly-circulated patch how one might hack
up libc's getaddrinfo() implementation to do the DNS resolution work described
in Scott's paper.

Here is a second copy of that patch, which I have improved to the point where I
am willing to recommend it for further testing, adaptation, and exploration.

(This new version uses libcrypt's MD5 implementation in favor of pulling in
chunks of libtomcrypt and it includes the minimum knowledge of "gaih_service"
structs necessary to work with ssh, wget, etc.)

To build it, grab your distro's libc6 packaging, apply the patch to
sysdeps/posix/getaddrinfo.c, and make sure that you define "crypt-in-libc = yes" in an appropriate configuration file. Then build normally. Some tests for
getaddrinfo() will fail but you should wind up with a fully functional
libc.so.6 which you may install or use via LD_PRELOAD like so:

  # calculate an address for "sonipes"
  LD_PRELOAD=/path/to/libc.so.6 python -c 'import socket; print 
socket.getaddrinfo("sonipes", None)'

  # suppose we get fe80::b3da:e0e7:3bd7:278d%eth0

  # on sonipes:
  sudo ip addr add fe80::b3da:e0e7:3bd7:278d%eth0 dev eth0

  # elsewhere, on another computer on the same link as sonipes
  sudo env LD_PRELOAD=/path/to/libc.so.6 ping6 sonipes
  LD_PRELOAD=/path/to/libc.so.6 ssh sonipes
  (rsync, wget, nc6, ...)

Enjoy,

Michael

[1]: http://wiki.laptop.org/go/Network_principles

P.S. - Improvements are definitely welcome -- I found the code very satisfying
to use on a local wireless network.

  a) provide a cute one-liner for assigning appropriate addresses to interfaces
     based on the machine's desired hostnames

  b) check the code for endian-neutrality

  c) figure out how to fully build and package the result for easier testing

  d) rewrite as an NSS module?

  e) rewrite in an external DNS resolver?
diff -u eglibc-2.9/debian/changelog eglibc-2.9/debian/changelog
--- eglibc-2.9/debian/changelog
+++ eglibc-2.9/debian/changelog
@@ -1,3 +1,11 @@
+eglibc (2.9-13.1) unstable; urgency=low
+
+  * Non-maintainer upload.
+  * debian/rules.d/build.mk: build libcrypt into libc
+  * debian/patches/any/hack-up-getaddrinfo.diff: install getaddrinfo hack.
+
+ -- Michael Stone <mich...@laptop.org>  Sat, 04 Jul 2009 19:06:59 -0400
+
 eglibc (2.9-13) unstable; urgency=low
 
   * debian/debhelper.in/nscd.init: fix return code when querying status
diff -u eglibc-2.9/debian/rules.d/build.mk eglibc-2.9/debian/rules.d/build.mk
--- eglibc-2.9/debian/rules.d/build.mk
+++ eglibc-2.9/debian/rules.d/build.mk
@@ -52,6 +52,7 @@
 	rtlddir="$(call xx,rtlddir)" ; if test -n "$$rtlddir" ; then \
 		echo "rtlddir = $$rtlddir" >> $(DEB_BUILDDIR)/configparms ; \
 	fi
+	echo "crypt-in-libc = yes" >> $(DEB_BUILDDIR)/configparms
 
 	# Prevent autoconf from running unexpectedly by setting it to false.
 	# Also explicitly pass CC down - this is needed to get -m64 on
diff -u eglibc-2.9/debian/patches/series eglibc-2.9/debian/patches/series
--- eglibc-2.9/debian/patches/series
+++ eglibc-2.9/debian/patches/series
@@ -210,0 +211 @@
+any/hack-up-getaddrinfo.diff
only in patch2:
unchanged:
--- eglibc-2.9.orig/debian/patches/any/hack-up-getaddrinfo.diff
+++ eglibc-2.9/debian/patches/any/hack-up-getaddrinfo.diff
@@ -0,0 +1,111 @@
+From 55208c43bbd9ce5e21b7c9b77db6526e688ce612 Mon Sep 17 00:00:00 2001
+From: Michael Stone <mich...@laptop.org>
+Date: Thu, 11 Jun 2009 21:04:18 -0400
+Subject: [PATCH] Hack up getaddrinfo().
+
+---
+ sysdeps/posix/getaddrinfo.c |   74 ++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 74 insertions(+), 0 deletions(-)
+
+Index: eglibc-2.9/sysdeps/posix/getaddrinfo.c
+===================================================================
+--- eglibc-2.9.orig/sysdeps/posix/getaddrinfo.c	2009-07-04 19:14:10.000000000 -0400
++++ eglibc-2.9/sysdeps/posix/getaddrinfo.c	2009-07-05 13:52:29.000000000 -0400
+@@ -62,6 +62,7 @@
+ #include <nscd/nscd-client.h>
+ #include <nscd/nscd_proto.h>
+ #include <resolv/res_hconf.h>
++#include <crypt/md5.h>
+ 
+ #ifdef HAVE_LIBIDN
+ extern int __idna_to_ascii_lz (const char *input, char **output, int flags);
+@@ -251,6 +252,81 @@
+     }									      \
+  }
+ 
++static void
++hack_dns  (const char *name, const struct gaih_service *service,
++	   const struct addrinfo *req, struct addrinfo **pai,
++	   unsigned int *naddrs, int *ret)
++{
++  /* XXX: Service processing! <MS> */
++  if (name == NULL
++   || (service != NULL && service->num < 0)
++   || ( req->ai_family != AF_INET6
++     && req->ai_family != AF_UNSPEC))
++      return;
++
++  char buf[16];
++
++  __md5_buffer(name, strlen(name), buf);
++
++  struct ifaddrs *ifaddr, *ifa;
++
++  if (getifaddrs(&ifaddr) == -1)
++    return; /* Should we set *ret? <MS> */
++
++  unsigned int old_naddrs = *naddrs;
++
++  for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
++    {
++      if (ifa->ifa_addr->sa_family != AF_INET6)
++        continue;
++
++      struct sockaddr_in6* sa6 = (struct sockaddr_in6*)ifa->ifa_addr;
++
++      /* XXX: Should I copy all ipv6 addrs or just link-local ones? */
++      if ( ! IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr) )
++        continue;
++
++      struct addrinfo *ai;
++      ai = *pai = malloc (sizeof (struct addrinfo));
++      if (ai == NULL)
++      {
++        *ret = -EAI_MEMORY;
++        return;
++      }
++
++      ai->ai_flags = req->ai_flags;
++      ai->ai_family = AF_INET6;
++      ai->ai_socktype = req->ai_socktype;
++      ai->ai_protocol = req->ai_protocol;
++      ai->ai_addrlen = sizeof (struct sockaddr_in6);
++      ai->ai_canonname = NULL; /* Really? <MS> */
++      ai->ai_next = NULL;
++
++      ai->ai_addr = malloc (ai->ai_addrlen);
++      if (ai->ai_addr == NULL)
++      {
++        free(*pai);
++        ai = *pai = NULL;
++        *ret = -EAI_MEMORY;
++        return;
++      }
++
++      memcpy(ai->ai_addr, sa6, ai->ai_addrlen);
++
++      struct sockaddr_in6* sp6 = (struct sockaddr_in6*)ai->ai_addr;
++      /* XXX: Should I try to adjust based on prefix length? */
++      memcpy (sp6->sin6_addr.s6_addr+8, buf, 8);
++
++      if (service != NULL && service->num >= 0)
++        sp6->sin6_port = htons (service->num);
++
++      pai = &(ai->ai_next);
++      ++*naddrs;
++    }
++
++  if (old_naddrs != *naddrs)
++    *ret = 0;
++}
+ 
+ typedef enum nss_status (*nss_gethostbyname4_r)
+   (const char *name, struct gaih_addrtuple **pat,
+@@ -2156,6 +2232,7 @@
+       || hints->ai_family == AF_INET6)
+     {
+       last_i = gaih_inet (name, pservice, hints, end, &naddrs);
++      hack_dns(name, pservice, hints, end, &naddrs, &last_i);
+       if (last_i != 0)
+ 	{
+ 	  freeaddrinfo (p);
_______________________________________________
Devel mailing list
Devel@lists.laptop.org
http://lists.laptop.org/listinfo/devel

Reply via email to