summaryrefslogtreecommitdiff
path: root/usr.sbin/dhcp
diff options
context:
space:
mode:
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 {