changeset 58:8120e49daefd draft

Add DHCP over FireWire 1394 (RFC 2855) and InfiniBand (RFC 4390) support.
author Roy Marples <roy@marples.name>
date Mon, 12 Feb 2007 16:12:50 +0000
parents e2185cab548d
children 047729b6641a
files ChangeLog Makefile arp.c configure.c dhcp.c dhcp.h dhcpcd.c interface.c interface.h socket.c
diffstat 10 files changed, 103 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Feb 08 09:40:22 2007 +0000
+++ b/ChangeLog	Mon Feb 12 16:12:50 2007 +0000
@@ -1,3 +1,6 @@
+Add DHCP over FireWire 1394 (RFC 2855) and InfiniBand (RFC 4390) support.
+We should add support for DUIDs (RFC4361) as well.
+
 dhcpcd-3.0.11
 Don't try to send messages when we infinite leasetime and the interface
 fd is closed.
--- a/Makefile	Thu Feb 08 09:40:22 2007 +0000
+++ b/Makefile	Mon Feb 12 16:12:50 2007 +0000
@@ -1,6 +1,6 @@
 # Should work for both GNU make and BSD make
 
-VERSION = 3.0.11
+VERSION = 3.0.12_pre1
 
 CFLAGS ?= -O2 -pipe
 
@@ -59,7 +59,7 @@
 	$(INSTALL) -m 0755 $(MAN8_TARGETS) $(MANDIR)/man8
 
 clean:
-	rm -f $(TARGET) $(dhcpcd_H) *.o *~ *.core
+	rm -f $(TARGET) $(dhcpcd_H) *.o *~ *.core *.bz2
 
 dist:
 	$(INSTALL) -m 0755 -d /tmp/dhcpcd-$(VERSION)
--- a/arp.c	Thu Feb 08 09:40:22 2007 +0000
+++ b/arp.c	Mon Feb 12 16:12:50 2007 +0000
@@ -78,12 +78,12 @@
 
   memset (arp.buffer, 0, sizeof (arp.buffer));
 
-  arp.ah.ar_hrd = htons (ARPHRD_ETHER);
+  arp.ah.ar_hrd = htons (iface->family);
   arp.ah.ar_pro = htons (ETHERTYPE_IP);
-  arp.ah.ar_hln = ETHER_ADDR_LEN;
+  arp.ah.ar_hln = iface->hwlen;
   arp.ah.ar_pln = sizeof (struct in_addr);
   arp.ah.ar_op = htons (ARPOP_REQUEST);
-  memcpy (ar_sha (&arp.ah), &iface->ethernet_address, arp.ah.ar_hln);
+  memcpy (ar_sha (&arp.ah), &iface->hwaddr, arp.ah.ar_hln);
   memcpy (ar_tpa (&arp.ah), &address, arp.ah.ar_pln);
 
   logger (LOG_INFO, "checking %s is available on attached networks", inet_ntoa
@@ -139,8 +139,7 @@
 	    break;
 
 	  /* Only these types are recognised */
-	  if (reply.hdr.ar_op != htons(ARPOP_REPLY)
-	      || reply.hdr.ar_hrd != htons (ARPHRD_ETHER))
+	  if (reply.hdr.ar_op != htons(ARPOP_REPLY))
 	    continue;
 
 	  /* Protocol must be IP. */
--- a/configure.c	Thu Feb 08 09:40:22 2007 +0000
+++ b/configure.c	Mon Feb 12 16:12:50 2007 +0000
@@ -411,8 +411,8 @@
   if (options->clientid[0])
     fprintf (f, "CLIENTID='%s'\n", cleanmetas (options->clientid));
   else
-    fprintf (f, "CLIENTID='%s'\n", ether_ntoa (&iface->ethernet_address));
-  fprintf (f, "DHCPCHADDR='%s'\n", ether_ntoa (&iface->ethernet_address));
+    fprintf (f, "CLIENTID='%s'\n", hwaddr_ntoa (iface->hwaddr, iface->hwlen));
+  fprintf (f, "DHCPCHADDR='%s'\n", hwaddr_ntoa (iface->hwaddr, iface->hwlen));
   fclose (f);
   return 0;
 }
--- a/dhcp.c	Thu Feb 08 09:40:22 2007 +0000
+++ b/dhcp.c	Mon Feb 12 16:12:50 2007 +0000
@@ -72,13 +72,6 @@
   if (!iface || !options || !dhcp)
     return -1;
 
-  if (type == DHCP_RELEASE || type == DHCP_INFORM ||
-      (type == DHCP_REQUEST &&
-       iface->previous_address.s_addr == dhcp->address.s_addr))
-    from.s_addr = dhcp->address.s_addr;
-  else
-    from.s_addr = 0;
-
   if (type == DHCP_RELEASE)
     to.s_addr = dhcp->serveraddress.s_addr;
   else
@@ -86,23 +79,41 @@
 
   memset (&message, 0, sizeof (dhcpmessage_t));
 
+  if (iface->previous_address.s_addr != 0
+      && (type == DHCP_INFORM || type == DHCP_RELEASE
+	  || (type == DHCP_REQUEST
+	      && iface->previous_address.s_addr == dhcp->address.s_addr)))
+    {
+      message.ciaddr = iface->previous_address.s_addr;
+      from.s_addr = iface->previous_address.s_addr;
+    }
+
   message.op = DHCP_BOOTREQUEST;
-  message.hwtype = ARPHRD_ETHER;
-  message.hwlen = ETHER_ADDR_LEN;
+  message.hwtype = iface->family;
+  switch (iface->family)
+    {
+    case ARPHRD_ETHER:
+    case ARPHRD_IEEE802:
+      message.hwlen = ETHER_ADDR_LEN;
+      memcpy (&message.chaddr, &iface->hwaddr, ETHER_ADDR_LEN);
+      break;
+    case ARPHRD_IEEE1394:
+    case ARPHRD_INFINIBAND:
+      if (message.ciaddr == 0)
+	message.flags = htons (BROADCAST_FLAG);
+      message.hwlen = 0;
+      break;
+    default:
+      logger (LOG_ERR, "dhcp: unknown hardware type %d", iface->family);
+    }
+
   if (up < 0 || up > UINT16_MAX)
     message.secs = htons ((short) UINT16_MAX);
   else
     message.secs = htons (up);
   message.xid = xid;
-  memcpy (&message.hwaddr, &iface->ethernet_address, ETHER_ADDR_LEN);
   message.cookie = htonl (MAGIC_COOKIE);
 
-  if (iface->previous_address.s_addr != 0
-      && (type == DHCP_INFORM || type == DHCP_RELEASE
-	  || (type == DHCP_REQUEST
-	      && iface->previous_address.s_addr == dhcp->address.s_addr)))
-    message.ciaddr = iface->previous_address.s_addr;
-
   *p++ = DHCP_MESSAGETYPE; 
   *p++ = 1;
   *p++ = type;
@@ -239,10 +250,10 @@
     }
   else
     {
-      *p++ = ETHER_ADDR_LEN + 1;
-      *p++ = ARPHRD_ETHER;
-      memcpy (p, &iface->ethernet_address, ETHER_ADDR_LEN);
-      p += ETHER_ADDR_LEN;
+      *p++ = iface->hwlen + 1;
+      *p++ = iface->family;
+      memcpy (p, &iface->hwaddr, iface->hwlen);
+      p += iface->hwlen;
     }
 
   *p++ = DHCP_END;
--- a/dhcp.h	Thu Feb 08 09:40:22 2007 +0000
+++ b/dhcp.h	Mon Feb 12 16:12:50 2007 +0000
@@ -152,13 +152,13 @@
 } dhcp_t;
 
 /* Sizes for DHCP options */
-#define HWADDR_LEN		16
+#define DHCP_CHADDR_LEN		16
 #define SERVERNAME_LEN		64
 #define BOOTFILE_LEN		128
 #define DHCP_UDP_LEN		(20 + 8)
 #define DHCP_BASE_LEN		(4 + 4 + 2 + 2 + 4 + 4 + 4 + 4 + 4)
 #define DHCP_RESERVE_LEN	(4 + 4 + 4 + 4 + 2)
-#define DHCP_FIXED_LEN		(DHCP_BASE_LEN + HWADDR_LEN + \
+#define DHCP_FIXED_LEN		(DHCP_BASE_LEN + DHCP_CHADDR_LEN + \
 				+ SERVERNAME_LEN + BOOTFILE_LEN)
 #define DHCP_OPTION_LEN		(MTU_MAX - DHCP_FIXED_LEN - DHCP_UDP_LEN \
 				 - DHCP_RESERVE_LEN)
@@ -177,7 +177,7 @@
   int32_t yiaddr;			/* 'your' client IP address */
   int32_t siaddr;			/* should be zero in client's messages */
   int32_t giaddr;			/* should be zero in client's messages */
-  unsigned char hwaddr[HWADDR_LEN];	/* client's hardware address */
+  unsigned char chaddr[DHCP_CHADDR_LEN];	/* client's hardware address */
   char servername[SERVERNAME_LEN];	/* server host name, null terminated string */
   char bootfile[BOOTFILE_LEN];		/* boot file name, null terminated string */
   uint32_t cookie;
--- a/dhcpcd.c	Thu Feb 08 09:40:22 2007 +0000
+++ b/dhcpcd.c	Mon Feb 12 16:12:50 2007 +0000
@@ -387,7 +387,10 @@
 
   logger (LOG_INFO, PACKAGE " " VERSION " starting");
   if (dhcp_run (&options))
-    exit (EXIT_FAILURE);
+    {
+      unlink (options.pidfile);
+      exit (EXIT_FAILURE);
+    }
 
   exit (EXIT_SUCCESS);
 }
--- a/interface.c	Thu Feb 08 09:40:22 2007 +0000
+++ b/interface.c	Mon Feb 12 16:12:50 2007 +0000
@@ -91,13 +91,31 @@
     }
 }
 
+
+char *hwaddr_ntoa (const unsigned char *hwaddr, int hwlen)
+{
+  static char buffer[128];
+  char *p = buffer;
+  int i;
+
+  for (i = 0; i < hwlen && i < 125; i++)
+    {
+      if (i > 0)
+	p += sprintf (p, ":");
+      p += sprintf (p, "%.2x", hwaddr[i]);
+    }
+
+  return (buffer);
+}
+
 interface_t *read_interface (const char *ifname, int metric)
 {
 
   int s;
   struct ifreq ifr;
   interface_t *iface;
-  unsigned char hwaddr[ETHER_ADDR_LEN];
+  unsigned char hwaddr[16];
+  int hwlen = 0;
   sa_family_t family;
 
 #ifndef __linux__
@@ -108,6 +126,8 @@
   if (! ifname)
     return NULL;
 
+  memset (hwaddr, sizeof (hwaddr), 0);
+
 #ifndef __linux__
   if (getifaddrs (&ifap) != 0)
     return NULL;
@@ -137,7 +157,8 @@
 	}
 
       memcpy (hwaddr, us.sdl->sdl_data + us.sdl->sdl_nlen, ETHER_ADDR_LEN);
-      family = us.sdl->sdl_type;
+      family = ARPHRD_ETHER;
+      hwlen = ETHER_ADDR_LEN;
       break;
     }
   freeifaddrs (ifap);
@@ -166,14 +187,23 @@
       close (s);
       return NULL;
     }
-  if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER &&
-      ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE802_TR)
+  switch (ifr.ifr_hwaddr.sa_family)
     {
-      logger (LOG_ERR, "interface is not Ethernet or Token Ring");
+    case ARPHRD_ETHER:
+    case ARPHRD_IEEE802:
+      hwlen = ETHER_ADDR_LEN;
+      break;
+    case ARPHRD_IEEE1394:
+      hwlen = EUI64_ADDR_LEN;
+    case ARPHRD_INFINIBAND:
+      hwlen = INFINIBAND_ADDR_LEN;
+      break;
+    default:
+      logger (LOG_ERR, "interface is not Ethernet, FireWire, InfiniBand or Token Ring");
       close (s);
       return NULL;
     }
-  memcpy (hwaddr, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
+  memcpy (hwaddr, ifr.ifr_hwaddr.sa_data, hwlen);
   family = ifr.ifr_hwaddr.sa_family;
 #else
   ifr.ifr_metric = metric;
@@ -206,13 +236,14 @@
   memset (iface, 0, sizeof (interface_t));
   strncpy (iface->name, ifname, IF_NAMESIZE);
   snprintf (iface->infofile, PATH_MAX, INFOFILE, ifname);
-  memcpy (&iface->ethernet_address, hwaddr, ETHER_ADDR_LEN);
+  memcpy (&iface->hwaddr, hwaddr, hwlen);
+  iface->hwlen = hwlen;
 
   iface->family = family;
   iface->arpable = ! (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK));
 
-  logger (LOG_INFO, "ethernet address = %s",
-	  ether_ntoa (&iface->ethernet_address));
+  logger (LOG_INFO, "hardware address = %s",
+	  hwaddr_ntoa (iface->hwaddr, iface->hwlen));
 
   /* 0 is a valid fd, so init to -1 */
   iface->fd = -1;
--- a/interface.h	Thu Feb 08 09:40:22 2007 +0000
+++ b/interface.h	Mon Feb 12 16:12:50 2007 +0000
@@ -31,6 +31,14 @@
 #include <limits.h>
 #include <stdbool.h>
 
+#define EUI64_ADDR_LEN			8
+#define INFINIBAND_ADDR_LEN		20
+
+/* The BSD's don't define this yet */
+#ifndef ARPHRD_INFINIBAND
+#  define ARPHRD_INFINIBAND		27
+#endif
+
 typedef struct route_t
 {
   struct in_addr destination; 
@@ -48,8 +56,9 @@
 typedef struct interface_t
 {
   char name[IF_NAMESIZE];
-  struct ether_addr ethernet_address;
   sa_family_t family;
+  unsigned char hwaddr[20];
+  int hwlen;
   bool arpable;
 
   int fd;
@@ -82,4 +91,7 @@
 		  struct in_addr netmask, struct in_addr gateway, int metric);
 int del_route (const char *ifname, struct in_addr destination,
 	       struct in_addr netmask, struct in_addr gateway, int metric);
+
+char *hwaddr_ntoa (const unsigned char *hwaddr, int hwlen);
+
 #endif
--- a/socket.c	Thu Feb 08 09:40:22 2007 +0000
+++ b/socket.c	Mon Feb 12 16:12:50 2007 +0000
@@ -317,7 +317,7 @@
   int retval = -1;
   struct iovec iov[2];
 
-  if (iface->family == IFT_ETHER)
+  if (iface->family == ARPHRD_ETHER)
     {
       struct ether_header hw;
       memset (&hw, 0, sizeof (struct ether_header));