+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.
# Should work for both GNU make and BSD make
-VERSION = 3.0.11
+VERSION = 3.0.12_pre1
CFLAGS ?= -O2 -pipe
$(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)
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
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. */
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;
}
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
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;
}
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;
} 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)
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;
logger (LOG_INFO, PACKAGE " " VERSION " starting");
if (dhcp_run (&options))
- exit (EXIT_FAILURE);
+ {
+ unlink (options.pidfile);
+ exit (EXIT_FAILURE);
+ }
exit (EXIT_SUCCESS);
}
}
}
+
+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__
if (! ifname)
return NULL;
+ memset (hwaddr, sizeof (hwaddr), 0);
+
#ifndef __linux__
if (getifaddrs (&ifap) != 0)
return NULL;
}
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);
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;
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;
#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;
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;
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
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));