diff options
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 { |