9858513
--- dhcp-3.0.5/server/bootp.c.unicast	2005-05-18 15:54:17.000000000 -0400
9858513
+++ dhcp-3.0.5/server/bootp.c	2007-03-30 16:16:00.000000000 -0400
9858513
@@ -62,6 +62,7 @@
9858513
 	char msgbuf [1024];
9858513
 	int ignorep;
9858513
 	int peer_has_leases = 0;
9858513
+	int norelay = 0;
9858513
 
9858513
 	if (packet -> raw -> op != BOOTREQUEST)
9858513
 		return;
9858513
@@ -77,7 +78,7 @@
9858513
 		 ? inet_ntoa (packet -> raw -> giaddr)
9858513
 		 : packet -> interface -> name);
9858513
 
9858513
-	if (!locate_network (packet)) {
9858513
+	if ((norelay = locate_network (packet)) == 0) {
9858513
 		log_info ("%s: network unknown", msgbuf);
9858513
 		return;
9858513
 	}
9858513
@@ -357,6 +358,13 @@
9858513
 					      from, &to, &hto);
9858513
 			goto out;
9858513
 		}
9858513
+	} else if (norelay == 2) {
9858513
+		to.sin_addr = raw.ciaddr;
9858513
+		to.sin_port = remote_port;
9858513
+		if (fallback_interface) {
9858513
+			result = send_packet (fallback_interface, (struct packet *)0, &raw, outgoing.packet_length, from, &to, &hto);
9858513
+			goto out;
9858513
+		}
9858513
 
9858513
 	/* If it comes from a client that already knows its address
9858513
 	   and is not requesting a broadcast response, and we can
9858513
--- dhcp-3.0.5/server/dhcp.c.unicast	2007-03-30 16:13:36.000000000 -0400
9858513
+++ dhcp-3.0.5/server/dhcp.c	2007-03-30 16:19:35.000000000 -0400
9858513
@@ -3817,6 +3817,7 @@
9858513
 	struct data_string data;
9858513
 	struct subnet *subnet = (struct subnet *)0;
9858513
 	struct option_cache *oc;
9858513
+	int norelay = 0;
9858513
 
9858513
 	/* See if there's a subnet selection option. */
9858513
 	oc = lookup_option (&dhcp_universe, packet -> options,
9858513
@@ -3826,12 +3827,24 @@
9858513
 	   from the interface, if there is one.   If not, fail. */
9858513
 	if (!oc && !packet -> raw -> giaddr.s_addr) {
9858513
 		if (packet -> interface -> shared_network) {
9858513
-			shared_network_reference
9858513
-				(&packet -> shared_network,
9858513
-				 packet -> interface -> shared_network, MDL);
9858513
-			return 1;
9858513
+			struct in_addr any_addr;
9858513
+			any_addr.s_addr = INADDR_ANY;
9858513
+
9858513
+			if (!packet -> packet_type && memcmp(&packet -> raw -> ciaddr, &any_addr, 4)) {
9858513
+				struct iaddr cip;
9858513
+				memcpy(cip.iabuf, &packet -> raw -> ciaddr, 4);
9858513
+				cip.len = 4;
9858513
+				if (!find_grouped_subnet(&subnet, packet->interface->shared_network, cip, MDL))
9858513
+					norelay = 2;
9858513
+			}
9858513
+
9858513
+			if (!norelay) {
9858513
+				shared_network_reference(&packet -> shared_network, packet -> interface -> shared_network, MDL);
9858513
+				return 1;
9858513
+			}
9858513
+		} else {
9858513
+			return 0;
9858513
 		}
9858513
-		return 0;
9858513
 	}
9858513
 
9858513
 	/* If there's an SSO, and it's valid, use it to figure out the
9858513
@@ -3853,7 +3866,10 @@
9858513
 		data_string_forget (&data, MDL);
9858513
 	} else {
9858513
 		ia.len = 4;
9858513
-		memcpy (ia.iabuf, &packet -> raw -> giaddr, 4);
9858513
+		if (norelay)
9858513
+			memcpy (ia.iabuf, &packet->raw->ciaddr, 4);
9858513
+		else
9858513
+			memcpy (ia.iabuf, &packet->raw->giaddr, 4);
9858513
 	}
9858513
 
9858513
 	/* If we know the subnet on which the IP address lives, use it. */
9858513
@@ -3861,7 +3877,10 @@
9858513
 		shared_network_reference (&packet -> shared_network,
9858513
 					  subnet -> shared_network, MDL);
9858513
 		subnet_dereference (&subnet, MDL);
9858513
-		return 1;
9858513
+		if (norelay)
9858513
+			return norelay;
9858513
+		else
9858513
+			return 1;
9858513
 	}
9858513
 
9858513
 	/* Otherwise, fail. */