Subject: | support unicast BOOTP in dhcpd |
Date: | Thu, 08 Jan 2009 10:04:15 -1000 |
To: | dhcp-bugs@isc.org |
From: | David Cantrell <dcantrell@redhat.com> |
The attached patch is against the dhcp HEAD revision as of now. It adds
support for unicast BOOTP which is at least necessary for IBM pSeries
systems. We include this patch in the dhcp package included in RHEL and
Fedora and the server still works for all users.
I would like to see this added to the upstream sources.
Thanks,
--
David Cantrell <dcantrell@redhat.com>
Red Hat / Honolulu, HI
? ChangeLog
Index: server/bootp.c
===================================================================
RCS file: /var/snapdf/DHCP/server/bootp.c,v
retrieving revision 1.83
diff -u -p -r1.83 bootp.c
--- server/bootp.c 20 Aug 2008 23:07:19 -0000 1.83
+++ server/bootp.c 8 Jan 2009 20:01:57 -0000
@@ -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
Index: server/dhcp.c
===================================================================
RCS file: /var/snapdf/DHCP/server/dhcp.c,v
retrieving revision 1.238
diff -u -p -r1.238 dhcp.c
--- server/dhcp.c 3 Nov 2008 18:13:58 -0000 1.238
+++ server/dhcp.c 8 Jan 2009 20:01:57 -0000
@@ -4111,6 +4111,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
@@ -4126,12 +4127,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,
@@ -4154,7 +4167,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. */
@@ -4162,7 +4178,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. */