diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2012-09-18 09:34:10 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2012-09-18 09:34:10 +0000 |
commit | 3ca5cf3cbd3e1c182a2e36bcd033ef9bf7540b6d (patch) | |
tree | 232de3a9325ab13d2a0b13854640922de4f4b601 | |
parent | d969a0350bb560c21fa288513e0acdb96c341448 (diff) |
Don't accept leases that offer a subnet that is already configured
on an interface. Crude hammer that may be refined as needed.
Feedback from tedu@, beck@, sthen@ claudio@
-rw-r--r-- | sbin/dhclient/dhclient.c | 9 | ||||
-rw-r--r-- | sbin/dhclient/dhcpd.h | 3 | ||||
-rw-r--r-- | sbin/dhclient/dispatch.c | 58 |
3 files changed, 67 insertions, 3 deletions
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index 93298b2f729..95fb1144080 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dhclient.c,v 1.155 2012/09/17 20:30:17 krw Exp $ */ +/* $OpenBSD: dhclient.c,v 1.156 2012/09/18 09:34:09 krw Exp $ */ /* * Copyright 2004 Henning Brauer <henning@openbsd.org> @@ -758,6 +758,13 @@ dhcpoffer(struct iaddr client_addr, struct option_data *options) return; } + /* + * Reject offers whose subnet is already configured on another + * interface. + */ + if (subnet_exists(lease)) + return; + /* If this lease was acquired through a BOOTREPLY, record that fact. */ if (!options[DHO_DHCP_MESSAGE_TYPE].len) diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h index b899e0dc703..d0e7cabce62 100644 --- a/sbin/dhclient/dhcpd.h +++ b/sbin/dhclient/dhcpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dhcpd.h,v 1.80 2012/09/01 19:08:42 krw Exp $ */ +/* $OpenBSD: dhcpd.h,v 1.81 2012/09/18 09:34:09 krw Exp $ */ /* * Copyright (c) 2004 Henning Brauer <henning@openbsd.org> @@ -256,6 +256,7 @@ void cancel_timeout(void); int interface_status(char *); int interface_link_forceup(char *); int get_rdomain(char *); +int subnet_exists(struct client_lease *); /* tables.c */ extern const struct option dhcp_options[256]; diff --git a/sbin/dhclient/dispatch.c b/sbin/dhclient/dispatch.c index 863430d2b9e..d5662e3f805 100644 --- a/sbin/dhclient/dispatch.c +++ b/sbin/dhclient/dispatch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dispatch.c,v 1.57 2012/09/17 12:10:46 krw Exp $ */ +/* $OpenBSD: dispatch.c,v 1.58 2012/09/18 09:34:09 krw Exp $ */ /* * Copyright 2004 Henning Brauer <henning@openbsd.org> @@ -335,3 +335,59 @@ get_rdomain(char *name) close(s); return rv; } + +int +subnet_exists(struct client_lease *l) + { + struct ifaddrs *ifap, *ifa; + in_addr_t mymask, myaddr, mynet, hismask, hisaddr, hisnet; + int myrdomain, hisrdomain; + + bcopy(l->options[DHO_SUBNET_MASK].data, &mymask, 4); + bcopy(l->address.iabuf, &myaddr, 4); + mynet = mymask & myaddr; + + myrdomain = get_rdomain(ifi->name); + + if (getifaddrs(&ifap) != 0) + error("getifaddrs failed"); + + for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { + if (strcmp(ifi->name, ifa->ifa_name) == 0) + continue; + + if (ifa->ifa_addr->sa_family != AF_INET) + continue; + + hisrdomain = get_rdomain(ifi->name); + if (hisrdomain != myrdomain) + continue; + + hismask = ((struct sockaddr_in *)ifa->ifa_netmask)-> + sin_addr.s_addr; + hisaddr = ((struct sockaddr_in *)ifa->ifa_addr)-> + sin_addr.s_addr; + hisnet = hisaddr & hismask; + + if (hisnet == 0) + continue; + + /* Would his packets go out *my* interface? */ + if (mynet == (hisaddr & mymask)) { + note("interface %s already has the offered subnet!", + ifa->ifa_name); + return (1); + } + + /* Would my packets go out *his* interface? */ + if (hisnet == (myaddr & hismask)) { + note("interface %s already has the offered subnet!", + ifa->ifa_name); + return (1); + } + } + + freeifaddrs(ifap); + + return (0); + } |