diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2004-01-11 03:25:31 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2004-01-11 03:25:31 +0000 |
commit | 4ae424f26819cda58dd24753bf580e87d2f0e018 (patch) | |
tree | cdca95fca1d7ff37fc2d5b699898caf0cff2db75 /usr.sbin/dhcp | |
parent | dae50989c25c246202480f7c5f81d021f3f2c056 (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.c | 1 | ||||
-rw-r--r-- | usr.sbin/dhcp/dhclient/dhclient.c | 105 | ||||
-rw-r--r-- | usr.sbin/dhcp/includes/dhcpd.h | 1 |
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 { |