c8bb8f
diff -up dhcp-4.2.4b1/server/bootp.c.unicast dhcp-4.2.4b1/server/bootp.c
c8bb8f
--- dhcp-4.2.4b1/server/bootp.c.unicast	2012-04-10 23:27:06.000000000 +0200
c8bb8f
+++ dhcp-4.2.4b1/server/bootp.c	2012-04-16 17:28:42.095919022 +0200
c8bb8f
@@ -59,6 +59,7 @@ void bootp (packet)
c8bb8f
 	char msgbuf [1024];
c8bb8f
 	int ignorep;
c8bb8f
 	int peer_has_leases = 0;
c8bb8f
+	int norelay = 0;
c8bb8f
 
c8bb8f
 	if (packet -> raw -> op != BOOTREQUEST)
c8bb8f
 		return;
c8bb8f
@@ -74,7 +75,7 @@ void bootp (packet)
c8bb8f
 		 ? inet_ntoa (packet -> raw -> giaddr)
c8bb8f
 		 : packet -> interface -> name);
c8bb8f
 
c8bb8f
-	if (!locate_network (packet)) {
c8bb8f
+	if ((norelay = locate_network (packet)) == 0) {
c8bb8f
 		log_info ("%s: network unknown", msgbuf);
c8bb8f
 		return;
c8bb8f
 	}
c8bb8f
@@ -399,6 +400,15 @@ void bootp (packet)
c8bb8f
 
c8bb8f
 			goto out;
c8bb8f
 		}
c8bb8f
+	} else if (norelay == 2) {
c8bb8f
+		to.sin_addr = raw.ciaddr;
c8bb8f
+		to.sin_port = remote_port;
c8bb8f
+		if (fallback_interface) {
c8bb8f
+			result = send_packet (fallback_interface, NULL, &raw,
c8bb8f
+					      outgoing.packet_length, from,
c8bb8f
+					      &to, &hto);
c8bb8f
+			goto out;
c8bb8f
+		}
c8bb8f
 
c8bb8f
 	/* If it comes from a client that already knows its address
c8bb8f
 	   and is not requesting a broadcast response, and we can
c8bb8f
diff -up dhcp-4.2.4b1/server/dhcp.c.unicast dhcp-4.2.4b1/server/dhcp.c
c8bb8f
--- dhcp-4.2.4b1/server/dhcp.c.unicast	2012-03-09 12:28:12.000000000 +0100
c8bb8f
+++ dhcp-4.2.4b1/server/dhcp.c	2012-04-16 17:26:55.067418285 +0200
c8bb8f
@@ -4299,6 +4299,7 @@ int locate_network (packet)
c8bb8f
 	struct data_string data;
c8bb8f
 	struct subnet *subnet = (struct subnet *)0;
c8bb8f
 	struct option_cache *oc;
c8bb8f
+	int norelay = 0;
c8bb8f
 
c8bb8f
 	/* See if there's a Relay Agent Link Selection Option, or a
c8bb8f
 	 * Subnet Selection Option.  The Link-Select and Subnet-Select
c8bb8f
@@ -4314,12 +4315,24 @@ int locate_network (packet)
c8bb8f
 	   from the interface, if there is one.   If not, fail. */
c8bb8f
 	if (!oc && !packet -> raw -> giaddr.s_addr) {
c8bb8f
 		if (packet -> interface -> shared_network) {
c8bb8f
-			shared_network_reference
c8bb8f
-				(&packet -> shared_network,
c8bb8f
-				 packet -> interface -> shared_network, MDL);
c8bb8f
-			return 1;
c8bb8f
+			struct in_addr any_addr;
c8bb8f
+			any_addr.s_addr = INADDR_ANY;
c8bb8f
+
c8bb8f
+			if (!packet -> packet_type && memcmp(&packet -> raw -> ciaddr, &any_addr, 4)) {
c8bb8f
+				struct iaddr cip;
c8bb8f
+				memcpy(cip.iabuf, &packet -> raw -> ciaddr, 4);
c8bb8f
+				cip.len = 4;
c8bb8f
+				if (!find_grouped_subnet(&subnet, packet->interface->shared_network, cip, MDL))
c8bb8f
+					norelay = 2;
c8bb8f
+			}
c8bb8f
+
c8bb8f
+			if (!norelay) {
c8bb8f
+				shared_network_reference(&packet -> shared_network, packet -> interface -> shared_network, MDL);
c8bb8f
+				return 1;
c8bb8f
+			}
c8bb8f
+		} else {
c8bb8f
+			return 0;
c8bb8f
 		}
c8bb8f
-		return 0;
c8bb8f
 	}
c8bb8f
 
c8bb8f
 	/* If there's an option indicating link connection, and it's valid,
c8bb8f
@@ -4342,7 +4355,10 @@ int locate_network (packet)
c8bb8f
 		data_string_forget (&data, MDL);
c8bb8f
 	} else {
c8bb8f
 		ia.len = 4;
c8bb8f
-		memcpy (ia.iabuf, &packet -> raw -> giaddr, 4);
c8bb8f
+		if (norelay)
c8bb8f
+			memcpy (ia.iabuf, &packet->raw->ciaddr, 4);
c8bb8f
+		else
c8bb8f
+			memcpy (ia.iabuf, &packet->raw->giaddr, 4);
c8bb8f
 	}
c8bb8f
 
c8bb8f
 	/* If we know the subnet on which the IP address lives, use it. */
c8bb8f
@@ -4350,7 +4366,10 @@ int locate_network (packet)
c8bb8f
 		shared_network_reference (&packet -> shared_network,
c8bb8f
 					  subnet -> shared_network, MDL);
c8bb8f
 		subnet_dereference (&subnet, MDL);
c8bb8f
-		return 1;
c8bb8f
+		if (norelay)
c8bb8f
+			return norelay;
c8bb8f
+		else
c8bb8f
+			return 1;
c8bb8f
 	}
c8bb8f
 
c8bb8f
 	/* Otherwise, fail. */