dhclient - Refuse leases for already configured subnets.
authorAntonio Huete Jimenez <tuxillo@quantumachine.net>
Thu, 7 Aug 2014 07:47:01 +0000 (09:47 +0200)
committerAntonio Huete Jimenez <tuxillo@quantumachine.net>
Sat, 9 Aug 2014 16:29:41 +0000 (18:29 +0200)
Taken-from: OpenBSD

sbin/dhclient/dhclient.c
sbin/dhclient/dhcpd.h
sbin/dhclient/dispatch.c

index 12a7677..9db5f4b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: src/sbin/dhclient/dhclient.c,v 1.155 2012/09/17 20:30:17 krw Exp $    */
+/*     $OpenBSD: src/sbin/dhclient/dhclient.c,v 1.156 2012/09/18 09:34:09 krw Exp $    */
 
 /*
  * Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -743,6 +743,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)
index 4c65a11..5a77e8d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: src/sbin/dhclient/dhcpd.h,v 1.80 2012/09/01 19:08:42 krw Exp $        */
+/*     $OpenBSD: src/sbin/dhclient/dhcpd.h,v 1.81 2012/09/18 09:34:09 krw Exp $        */
 
 /*
  * Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
@@ -253,6 +253,7 @@ void set_timeout_interval(time_t, void (*)(void));
 void cancel_timeout(void);
 int interface_status(char *);
 int interface_link_forceup(char *);
+int subnet_exists(struct client_lease *);
 
 /* tables.c */
 extern const struct option dhcp_options[256];
index a5e7622..27869eb 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: src/sbin/dhclient/dispatch.c,v 1.57 2012/09/17 12:10:46 krw Exp $     */
+/*     $OpenBSD: src/sbin/dhclient/dispatch.c,v 1.58 2012/09/18 09:34:09 krw Exp $     */
 
 /*
  * Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -312,3 +312,52 @@ cancel_timeout(void)
        timeout.when = 0;
        timeout.func = NULL;
 }
+
+int
+subnet_exists(struct client_lease *l)
+{
+       struct ifaddrs *ifap, *ifa;
+       in_addr_t mymask, myaddr, mynet, hismask, hisaddr, hisnet;
+
+       bcopy(l->options[DHO_SUBNET_MASK].data, &mymask, 4);
+       bcopy(l->address.iabuf, &myaddr, 4);
+       mynet = mymask & myaddr;
+
+       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;
+
+               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);
+}