summaryrefslogtreecommitdiff
path: root/usr.sbin/dhcp/dhclient
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/dhclient
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/dhclient')
-rw-r--r--usr.sbin/dhcp/dhclient/dhclient.c105
1 files changed, 105 insertions, 0 deletions
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