changeset 45:c17863fc1b2d draft

Add static routes before any default routes as a router may require a host route in the static routes.
author Roy Marples <roy@marples.name>
date Thu, 28 Dec 2006 18:44:16 +0000
parents 5e34595a9e0f
children 23d8133bf061
files ChangeLog configure.c dhcp.c interface.c socket.c
diffstat 5 files changed, 103 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Dec 21 21:12:28 2006 +0000
+++ b/ChangeLog	Thu Dec 28 18:44:16 2006 +0000
@@ -1,3 +1,6 @@
+Add static routes before any default routes as a router may require a host
+route in the static routes.
+
 dhcpcd-3.0.8
 Fix arp checking.
 linux header asm/types.h doesn't work with c99 which is just wrong,
--- a/configure.c	Thu Dec 21 21:12:28 2006 +0000
+++ b/configure.c	Thu Dec 28 18:44:16 2006 +0000
@@ -426,7 +426,7 @@
 #ifdef __linux__
   /* On linux, we need to change the subnet route to have our metric. */
   if (iface->previous_address.s_addr != dhcp->address.s_addr
-      && options->metric > 0)
+      && options->metric > 0 && dhcp->netmask.s_addr != INADDR_BROADCAST)
     {
       struct in_addr td;
       struct in_addr tg;
--- a/dhcp.c	Thu Dec 21 21:12:28 2006 +0000
+++ b/dhcp.c	Thu Dec 28 18:44:16 2006 +0000
@@ -165,8 +165,8 @@
 	  *p++ = DHCP_CSR;
 	  /* RFC 3442 states classless static routes should be before routers
 	   * and static routes as classless static routes override them both */
+	  *p++ = DHCP_STATICROUTE;
 	  *p++ = DHCP_ROUTERS;
-	  *p++ = DHCP_STATICROUTE;
 	  *p++ = DHCP_HOSTNAME;
 	  *p++ = DHCP_DNSSEARCH;
 	  *p++ = DHCP_DNSDOMAIN;
--- a/interface.c	Thu Dec 21 21:12:28 2006 +0000
+++ b/interface.c	Thu Dec 28 18:44:16 2006 +0000
@@ -115,7 +115,7 @@
   for (p = ifap; p; p = p->ifa_next)
     {
       union
-        {
+	{
 	  struct sockaddr *sa;
 	  struct sockaddr_dl *sdl;
 	} us;
@@ -130,11 +130,11 @@
 	/*
 	   && us.sdl->sdl_type != IFT_ISO88025))
 	   */
-	  {
-	    logger (LOG_ERR, "interface is not Ethernet");
-	    freeifaddrs (ifap);
-	    return NULL;
-	  }
+	{
+	  logger (LOG_ERR, "interface is not Ethernet");
+	  freeifaddrs (ifap);
+	  return NULL;
+	}
 
       memcpy (hwaddr, us.sdl->sdl_data + us.sdl->sdl_nlen, ETHER_ADDR_LEN);
       family = us.sdl->sdl_type;
@@ -278,13 +278,19 @@
 		     int change, int del)
 {
   int s;
-  char *destd;
+  char *dstd;
   char *gend;
   struct rtm
     {
       struct rt_msghdr hdr;
       struct sockaddr_in destination;
-      struct sockaddr_in gateway;
+      union
+	{
+	  struct sockaddr sa;
+	  struct sockaddr_in sin;
+	  struct sockaddr_dl sdl;
+	  struct sockaddr_storage sss; /* added to avoid memory overrun */
+	} gateway;
       struct sockaddr_in netmask;
     } rtm;
   static int seq;
@@ -295,13 +301,22 @@
   /* Do something with metric to satisfy compiler warnings */
   metric = 0;
 
-  destd = strdup (inet_ntoa (destination));
+  dstd = strdup (inet_ntoa (destination));
   gend = strdup (inet_ntoa (netmask));
-  logger (LOG_INFO, "%s route to %s (%s) via %s",
-	  change ? "changing" : del ? "removing" : "adding",
-	  destd, gend, inet_ntoa(gateway));
-  if (destd)
-    free (destd);
+  if (gateway.s_addr == destination.s_addr)
+    logger (LOG_INFO, "%s route to %s (%s)",
+	    change ? "changing" : del ? "removing" : "adding",
+	    dstd, gend);
+  else if (destination.s_addr == INADDR_ANY && netmask.s_addr == INADDR_ANY)
+    logger (LOG_INFO, "%s default route via %s",
+	    change ? "changing" : del ? "removing" : "adding",
+	    inet_ntoa (gateway));
+  else
+    logger (LOG_INFO, "%s route to %s (%s) via %s",
+	    change ? "changing" : del ? "removing" : "adding",
+	    dstd, gend, inet_ntoa (gateway));
+  if (dstd)
+    free (dstd);
   if (gend)
     free (gend);
 
@@ -317,9 +332,11 @@
   rtm.hdr.rtm_seq = ++seq;
   rtm.hdr.rtm_type = change ? RTM_CHANGE : del ? RTM_DELETE : RTM_ADD;
 
-  rtm.hdr.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
-  if (netmask.s_addr == 0xffffffff)
+  rtm.hdr.rtm_flags = RTF_UP | RTF_STATIC;
+  if (netmask.s_addr == INADDR_BROADCAST) 
     rtm.hdr.rtm_flags |= RTF_HOST;
+  else
+    rtm.hdr.rtm_flags |= RTF_GATEWAY;
 
   rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
 
@@ -329,7 +346,40 @@
   memcpy (&_var.sin_addr, &_addr, sizeof (struct in_addr));
 
   ADDADDR (rtm.destination, destination);
-  ADDADDR (rtm.gateway, gateway);
+  if (netmask.s_addr == INADDR_BROADCAST)
+    {
+      struct ifaddrs *ifap, *ifa;
+      union
+	{
+	  struct sockaddr *sa;
+	  struct sockaddr_dl *sdl;
+	} us;
+
+      if (getifaddrs (&ifap))
+	{
+	  logger (LOG_ERR, "getifaddrs: %s", strerror (errno));
+	  return -1;
+	}
+
+      for (ifa = ifap; ifa; ifa = ifa->ifa_next)
+	{
+	  if (ifa->ifa_addr->sa_family != AF_LINK)
+	    continue;
+
+	  if (strcmp (ifname, ifa->ifa_name))
+	    continue;
+
+	  us.sa = ifa->ifa_addr;
+	  memcpy (&rtm.gateway.sdl, us.sdl, us.sdl->sdl_len);
+	  break;
+	}
+      freeifaddrs (ifap);
+    }
+  else
+    {
+      ADDADDR (rtm.gateway.sin, gateway);
+    }
+
   ADDADDR (rtm.netmask, netmask);
 
 #undef ADDADDR
@@ -369,10 +419,10 @@
   static unsigned int seq;
   char buffer[16384];
   union
-  {
-    char *buffer;
-    struct nlmsghdr *nlm;
-  } h;
+    {
+      char *buffer;
+      struct nlmsghdr *nlm;
+    } h;
 
   if ((s = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) 
     {
@@ -504,7 +554,7 @@
 }
 
 #define NLMSG_TAIL(nmsg) \
-  ((struct rtattr *) (((ptrdiff_t) (nmsg)) + NLMSG_ALIGN ((nmsg)->nlmsg_len)))
+ ((struct rtattr *) (((ptrdiff_t) (nmsg)) + NLMSG_ALIGN ((nmsg)->nlmsg_len)))
 
 static int add_attr_l(struct nlmsghdr *n, unsigned int maxlen, int type,
 		      const void *data, int alen)
@@ -532,7 +582,7 @@
 {
   int len = RTA_LENGTH (sizeof (uint32_t));
   struct rtattr *rta;
-  
+
   if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
     {
       logger (LOG_ERR, "add_attr32: message exceeded bound of %d\n", maxlen);
@@ -610,9 +660,18 @@
 
   dstd = strdup (inet_ntoa (destination));
   gend = strdup (inet_ntoa (netmask));
-  logger (LOG_INFO, "%s route to %s (%s) via %s, metric %d",
-	  change ? "changing" : del ? "removing" : "adding",
-	  dstd, gend, inet_ntoa (gateway), metric);
+  if (gateway.s_addr == destination.s_addr)
+    logger (LOG_INFO, "%s route to %s (%s) metric %d",
+	    change ? "changing" : del ? "removing" : "adding",
+	    dstd, gend, metric);
+  else if (destination.s_addr == INADDR_ANY && netmask.s_addr == INADDR_ANY)
+    logger (LOG_INFO, "%s default route via %s metric %d",
+	    change ? "changing" : del ? "removing" : "adding",
+	    inet_ntoa (gateway), metric);
+  else
+    logger (LOG_INFO, "%s route to %s (%s) via %s metric %d",
+	    change ? "changing" : del ? "removing" : "adding",
+	    dstd, gend, inet_ntoa (gateway), metric);
   if (dstd)
     free (dstd);
   if (gend)
@@ -636,7 +695,8 @@
     {
       nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
       nlm.rt.rtm_protocol = RTPROT_BOOT;
-      if (gateway.s_addr == 0)
+      if (gateway.s_addr == INADDR_ANY ||
+	  netmask.s_addr == INADDR_BROADCAST)
 	nlm.rt.rtm_scope = RT_SCOPE_LINK;
       else
 	nlm.rt.rtm_scope = RT_SCOPE_UNIVERSE;
@@ -652,7 +712,7 @@
 
   add_attr_l (&nlm.hdr, sizeof (nlm), RTA_DST, &destination.s_addr,
 	      sizeof (destination.s_addr));
-  if (gateway.s_addr != 0)
+  if (gateway.s_addr != INADDR_ANY && gateway.s_addr != destination.s_addr)
     add_attr_l (&nlm.hdr, sizeof (nlm), RTA_GATEWAY, &gateway.s_addr,
 		sizeof (gateway.s_addr));
 
@@ -684,7 +744,7 @@
 int del_address (const char *ifname, struct in_addr address)
 {
   struct in_addr t;
-  
+
   logger (LOG_INFO, "deleting IP address %s", inet_ntoa (address));
 
   memset (&t, 0, sizeof (t));
@@ -724,7 +784,7 @@
   for (p = ifap; p; p = p->ifa_next)
     {
       union
-        {
+	{
 	  struct sockaddr *sa;
 	  struct sockaddr_in *sin;
 	} us;
--- a/socket.c	Thu Dec 21 21:12:28 2006 +0000
+++ b/socket.c	Thu Dec 28 18:44:16 2006 +0000
@@ -112,7 +112,7 @@
   ip->ip_len = udp->uh_ulen;
   udp->uh_sum = checksum ((unsigned char *) packet,
 			  sizeof (struct udp_dhcp_packet));
-  
+
   ip->ip_v = IPVERSION;
   ip->ip_hl = 5;
   ip->ip_id = 0;
@@ -180,7 +180,7 @@
 }
 
 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) \
-|| defined(__APPLE__)
+ || defined(__APPLE__)
 /* Credit where credit is due :)
    The below BPF filter is taken from ISC DHCP */
 
@@ -373,7 +373,7 @@
     {
       int len = -1;
       union
-        {
+	{
 	  unsigned char *buffer;
 	  struct ether_header *hw;
 	} hdr;
@@ -398,7 +398,7 @@
 	  if (valid_dhcp_packet (payload) >= 0)
 	    {
 	      union
-	        {
+		{
 		  unsigned char *buffer;
 		  struct udp_dhcp_packet *packet;
 		} pay;
@@ -411,7 +411,7 @@
 
       /* Update the buffer_pos pointer */
       bpf.buffer +=
-      BPF_WORDALIGN (bpf.packet->bh_hdrlen + bpf.packet->bh_caplen);
+       BPF_WORDALIGN (bpf.packet->bh_hdrlen + bpf.packet->bh_caplen);
       if (bpf.buffer - buffer <  *buffer_len)
 	*buffer_pos = bpf.buffer - buffer;
       else
@@ -508,10 +508,10 @@
 {
   long bytes;
   union
-  {
+    {
       unsigned char *buffer;
       struct udp_dhcp_packet *packet;
-  } pay;
+    } pay;
 
   /* We don't use the given buffer, but we need to rewind the position */
   *buffer_pos = 0;
@@ -563,7 +563,7 @@
     return -1;
 
   memcpy(data, &pay.packet->dhcp,
-  bytes - (sizeof (pay.packet->ip) + sizeof (pay.packet->udp)));
+	 bytes - (sizeof (pay.packet->ip) + sizeof (pay.packet->udp)));
 
   return bytes - (sizeof (pay.packet->ip) + sizeof (pay.packet->udp));
 }