summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2009-01-26 22:32:42 +0000
committerRoy Marples <roy@marples.name>2009-01-26 22:32:42 +0000
commit16687a3be1f8c1e6d55cdd691e947e5760eef30c (patch)
tree81ecc57612e06ddcc51dd29a6473ec5aea736f44
parent495c0a77ac4caba2360004b64a1f563d682ac7ee (diff)
downloaddhcpcd-16687a3be1f8c1e6d55cdd691e947e5760eef30c.tar.xz
We need to ensure that manual route deletions are deleted from our internal routing table also. Partial fix for #159.
-rw-r--r--configure.c28
-rw-r--r--configure.h3
-rw-r--r--if-bsd.c32
3 files changed, 63 insertions, 0 deletions
diff --git a/configure.c b/configure.c
index 3b4b2124..96d8d886 100644
--- a/configure.c
+++ b/configure.c
@@ -62,6 +62,7 @@
static struct rt *routes;
+
static int
exec_script(char *const *argv, char *const *env)
{
@@ -388,6 +389,33 @@ desc_route(const char *cmd, const struct rt *rt, const char *ifname)
addr, inet_ntocidr(rt->net), inet_ntoa(rt->gate));
}
+/* If something other than dhcpcd removes a route,
+ * we need to remove it from our internal table. */
+int
+route_deleted(const struct in_addr *dst,
+ const struct in_addr *net,
+ const struct in_addr *gate)
+{
+ struct rt rt, *f, *l;
+
+ rt.dest.s_addr = dst->s_addr;
+ rt.net.s_addr = net->s_addr;
+ rt.gate.s_addr = gate->s_addr;
+ rt.iface = NULL;
+ rt.next = NULL;
+
+ f = find_route(routes, &rt, &l, NULL);
+ if (f == NULL)
+ return 0;
+ desc_route("removing", f, f->iface->name);
+ if (l)
+ l->next = f->next;
+ else
+ routes = f->next;
+ free(f);
+ return 1;
+}
+
static int
n_route(struct rt *rt, const struct interface *iface)
{
diff --git a/configure.h b/configure.h
index 5ee4ab8a..5d0124de 100644
--- a/configure.h
+++ b/configure.h
@@ -33,5 +33,8 @@
int send_interface(int, const struct interface *);
int run_script(const struct interface *);
int configure(struct interface *);
+int route_deleted(const struct in_addr *,
+ const struct in_addr *,
+ const struct in_addr *);
#endif
diff --git a/if-bsd.c b/if-bsd.c
index cc671ee2..46a87aca 100644
--- a/if-bsd.c
+++ b/if-bsd.c
@@ -51,10 +51,14 @@
#include "config.h"
#include "common.h"
+#include "configure.h"
#include "dhcp.h"
#include "if-options.h"
#include "net.h"
+#define ROUNDUP(a) \
+ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+
/* Darwin doesn't define this for some very odd reason */
#ifndef SA_SIZE
# define SA_SIZE(sa) \
@@ -312,6 +316,9 @@ manage_link(int fd,
struct rt_msghdr *rtm;
struct if_announcemsghdr *ifa;
struct if_msghdr *ifm;
+ struct in_addr dst, net, gate;
+ struct sockaddr *sa;
+ struct sockaddr_in *sin;
for (;;) {
bytes = read(fd, buffer, BUFFER_LEN);
@@ -343,6 +350,31 @@ manage_link(int fd,
if (if_indextoname(ifm->ifm_index, ifname))
if_carrier(ifname);
break;
+ case RTM_DELETE:
+ if (!(rtm->rtm_addrs & RTA_DST) ||
+ !(rtm->rtm_addrs & RTA_GATEWAY) ||
+ !(rtm->rtm_addrs & RTA_NETMASK))
+ break;
+ if (rtm->rtm_pid == getpid())
+ break;
+ sa = (struct sockaddr *)(rtm + 1);
+ if (sa->sa_family != AF_INET)
+ break;
+ sin = (struct sockaddr_in *)sa;
+ memcpy(&dst.s_addr, &sin->sin_addr.s_addr,
+ sizeof(dst.s_addr));
+ sa = (struct sockaddr *)
+ (ROUNDUP(sa->sa_len) + (char *)sa);
+ sin = (struct sockaddr_in *)sa;
+ memcpy(&gate.s_addr, &sin->sin_addr.s_addr,
+ sizeof(gate.s_addr));
+ sa = (struct sockaddr *)
+ (ROUNDUP(sa->sa_len) + (char *)sa);
+ sin = (struct sockaddr_in *)sa;
+ memcpy(&net.s_addr, &sin->sin_addr.s_addr,
+ sizeof(net.s_addr));
+ route_deleted(&dst, &net, &gate);
+ break;
}
}
}