--- /dev/null
+diff -up dhcp-4.2.0/server/bootp.c.unicast dhcp-4.2.0/server/bootp.c
+--- dhcp-4.2.0/server/bootp.c.unicast 2009-11-20 02:49:03.000000000 +0100
++++ dhcp-4.2.0/server/bootp.c 2010-07-21 13:40:25.000000000 +0200
+@@ -58,6 +58,7 @@ void bootp (packet)
+ char msgbuf [1024];
+ int ignorep;
+ int peer_has_leases = 0;
++ int norelay = 0;
+
+ if (packet -> raw -> op != BOOTREQUEST)
+ return;
+@@ -73,7 +74,7 @@ void bootp (packet)
+ ? inet_ntoa (packet -> raw -> giaddr)
+ : packet -> interface -> name);
+
+- if (!locate_network (packet)) {
++ if ((norelay = locate_network (packet)) == 0) {
+ log_info ("%s: network unknown", msgbuf);
+ return;
+ }
+@@ -390,6 +391,13 @@ void bootp (packet)
+ from, &to, &hto);
+ goto out;
+ }
++ } else if (norelay == 2) {
++ to.sin_addr = raw.ciaddr;
++ to.sin_port = remote_port;
++ if (fallback_interface) {
++ result = send_packet (fallback_interface, (struct packet *)0, &raw, outgoing.packet_length, from, &to, &hto);
++ goto out;
++ }
+
+ /* If it comes from a client that already knows its address
+ and is not requesting a broadcast response, and we can
+diff -up dhcp-4.2.0/server/dhcp.c.unicast dhcp-4.2.0/server/dhcp.c
+--- dhcp-4.2.0/server/dhcp.c.unicast 2010-06-01 19:29:59.000000000 +0200
++++ dhcp-4.2.0/server/dhcp.c 2010-07-21 13:40:25.000000000 +0200
+@@ -4185,6 +4185,7 @@ int locate_network (packet)
+ struct data_string data;
+ struct subnet *subnet = (struct subnet *)0;
+ struct option_cache *oc;
++ int norelay = 0;
+
+ /* See if there's a Relay Agent Link Selection Option, or a
+ * Subnet Selection Option. The Link-Select and Subnet-Select
+@@ -4200,12 +4201,24 @@ int locate_network (packet)
+ from the interface, if there is one. If not, fail. */
+ if (!oc && !packet -> raw -> giaddr.s_addr) {
+ if (packet -> interface -> shared_network) {
+- shared_network_reference
+- (&packet -> shared_network,
+- packet -> interface -> shared_network, MDL);
+- return 1;
++ struct in_addr any_addr;
++ any_addr.s_addr = INADDR_ANY;
++
++ if (!packet -> packet_type && memcmp(&packet -> raw -> ciaddr, &any_addr, 4)) {
++ struct iaddr cip;
++ memcpy(cip.iabuf, &packet -> raw -> ciaddr, 4);
++ cip.len = 4;
++ if (!find_grouped_subnet(&subnet, packet->interface->shared_network, cip, MDL))
++ norelay = 2;
++ }
++
++ if (!norelay) {
++ shared_network_reference(&packet -> shared_network, packet -> interface -> shared_network, MDL);
++ return 1;
++ }
++ } else {
++ return 0;
+ }
+- return 0;
+ }
+
+ /* If there's an option indicating link connection, and it's valid,
+@@ -4228,7 +4241,10 @@ int locate_network (packet)
+ data_string_forget (&data, MDL);
+ } else {
+ ia.len = 4;
+- memcpy (ia.iabuf, &packet -> raw -> giaddr, 4);
++ if (norelay)
++ memcpy (ia.iabuf, &packet->raw->ciaddr, 4);
++ else
++ memcpy (ia.iabuf, &packet->raw->giaddr, 4);
+ }
+
+ /* If we know the subnet on which the IP address lives, use it. */
+@@ -4236,7 +4252,10 @@ int locate_network (packet)
+ shared_network_reference (&packet -> shared_network,
+ subnet -> shared_network, MDL);
+ subnet_dereference (&subnet, MDL);
+- return 1;
++ if (norelay)
++ return norelay;
++ else
++ return 1;
+ }
+
+ /* Otherwise, fail. */