summaryrefslogtreecommitdiff
path: root/usr.sbin/dhcp
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2004-01-11 03:25:31 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2004-01-11 03:25:31 +0000
commit4ae424f26819cda58dd24753bf580e87d2f0e018 (patch)
treecdca95fca1d7ff37fc2d5b699898caf0cff2db75 /usr.sbin/dhcp
parentdae50989c25c246202480f7c5f81d021f3f2c056 (diff)
listen to the routing socket. if anyone messes with our interface by
taking it down, or deleting or adding an address, then we attempt to cleanup and exit. ok vincent mcbride, wow from hin
Diffstat (limited to 'usr.sbin/dhcp')
-rw-r--r--usr.sbin/dhcp/common/dispatch.c1
-rw-r--r--usr.sbin/dhcp/dhclient/dhclient.c105
-rw-r--r--usr.sbin/dhcp/includes/dhcpd.h1
3 files changed, 107 insertions, 0 deletions
diff --git a/usr.sbin/dhcp/common/dispatch.c b/usr.sbin/dhcp/common/dispatch.c
index c830a5d6f34..d978223bc1b 100644
--- a/usr.sbin/dhcp/common/dispatch.c
+++ b/usr.sbin/dhcp/common/dispatch.c
@@ -139,6 +139,7 @@ void discover_interfaces (state)
if (ifa -> ifa_addr->sa_family == AF_LINK) {
struct sockaddr_dl *foo = ((struct sockaddr_dl *)
(ifa -> ifa_addr));
+ tmp -> index = foo->sdl_index;
tmp -> hw_address.hlen = foo -> sdl_alen;
tmp -> hw_address.htype = HTYPE_ETHER; /* XXX */
memcpy (tmp -> hw_address.haddr,
diff --git a/usr.sbin/dhcp/dhclient/dhclient.c b/usr.sbin/dhcp/dhclient/dhclient.c
index d5dd7f08d31..959bd444e00 100644
--- a/usr.sbin/dhcp/dhclient/dhclient.c
+++ b/usr.sbin/dhcp/dhclient/dhclient.c
@@ -117,6 +117,107 @@ static int res_hnok(const char *dn);
char *option_as_string (unsigned int code, unsigned char *data, int len);
+int routefd;
+
+struct interface_info *
+isours(u_int16_t index)
+{
+ struct interface_info *ip;
+
+ for(ip = interfaces; ip; ip = ip->next) {
+ if (index == ip->index)
+ return (ip);
+ }
+ return (NULL);
+}
+
+#define ROUNDUP(a) \
+ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
+
+int
+findproto(char *cp, int n)
+{
+ struct sockaddr *sa;
+ int i;
+
+ if (n == 0)
+ return -1;
+ for (i = 1; i; i <<= 1) {
+ if (i & n) {
+ sa = (struct sockaddr *)cp;
+ switch (i) {
+ case RTA_IFA:
+ case RTA_DST:
+ case RTA_GATEWAY:
+ case RTA_NETMASK:
+ if (sa->sa_family == AF_INET)
+ return AF_INET;
+ if (sa->sa_family == AF_INET6)
+ return AF_INET6;
+ break;
+ case RTA_IFP:
+ break;
+ }
+ ADVANCE(cp, sa);
+ }
+ }
+ return (-1);
+}
+
+void
+routehandler(struct protocol *p)
+{
+ char msg[2048];
+ struct rt_msghdr *rtm;
+ struct if_msghdr *ifm;
+ struct ifa_msghdr *ifam;
+ struct interface_info *ip;
+ ssize_t n;
+
+ n = read(routefd, &msg, sizeof msg);
+ rtm = (struct rt_msghdr *)msg;
+ if (n < sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen ||
+ rtm->rtm_version != RTM_VERSION)
+ return;
+
+ switch (rtm->rtm_type) {
+ case RTM_NEWADDR:
+ ifam = (struct ifa_msghdr *)rtm;
+ if ((ip = isours(ifam->ifam_index)) == NULL)
+ break;
+ if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
+ break;
+ /* goto die; */
+ break;
+ case RTM_DELADDR:
+ ifam = (struct ifa_msghdr *)rtm;
+ if ((ip = isours(ifam->ifam_index)) == 0)
+ break;
+ if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
+ break;
+ goto die;
+ break;
+ case RTM_IFINFO:
+ ifm = (struct if_msghdr *)rtm;
+ if ((ip = isours(ifm->ifm_index)) == 0)
+ break;
+ if ((rtm->rtm_flags & RTF_UP) == 0)
+ goto die;
+ break;
+ default:
+ break;
+ }
+ return;
+
+die:
+ script_init(ip, "FAIL", (struct string_list *)0);
+ if (ip->client->alias)
+ script_write_params(ip, "alias_", ip->client->alias);
+ script_go(ip);
+ exit(1);
+}
+
int main (argc, argv)
int argc;
char **argv;
@@ -262,6 +363,10 @@ int main (argc, argv)
}
}
+ routefd = socket(PF_ROUTE, SOCK_RAW, 0);
+ if (routefd != -1)
+ add_protocol("AF_ROUTE", routefd, routehandler, interfaces);
+
/* At this point, all the interfaces that the script thinks
are relevant should be running, so now we once again call
discover_interfaces(), and this time ask it to actually set
diff --git a/usr.sbin/dhcp/includes/dhcpd.h b/usr.sbin/dhcp/includes/dhcpd.h
index 16c1ec7382f..9936965615b 100644
--- a/usr.sbin/dhcp/includes/dhcpd.h
+++ b/usr.sbin/dhcp/includes/dhcpd.h
@@ -392,6 +392,7 @@ struct interface_info {
int noifmedia;
int errors;
int dead;
+ u_int16_t index;
};
struct hardware_link {