SHA256
1
0
forked from pool/dhcp
dhcp/0016-infiniband-support.patch

1086 lines
36 KiB
Diff
Raw Normal View History

For complete changelog, please read the RELNOTES file shipped along with this package or online at: - Replaced hostname patch with a dhcpv6 and fqdn aware variant: [- 0006-dhcp-4.2.5-dhclient-send-hostname-rml.patch, + 0006-dhcp-4.3.2-dhclient-send-hostname-or-fqdn.patch] - Adjusted patch numbers in the spec file: [- 0008-dhcp-4.1.1-P1-lpf-bind-msg-fix.patch, - 0010-dhcp-4.2.2-dhclient-option-checks.patch, - 0011-dhcp-4.2.6-close-on-exec.patch, - 0012-dhcp-4.2.2-quiet-dhclient.patch, - 0014-Fixed-linux-interface-discovery-using-getifaddrs.patch, - 0020-dhcp-4.2.x-chown-server-leases.bnc868253.patch, - 0024-dhcp-4.2.x-dhcpv6-decline-on-DAD-failure.872609.patch, + 0008-dhcp-4.2.2-dhclient-option-checks.patch, + 0009-dhcp-4.2.6-close-on-exec.patch, + 0010-dhcp-4.2.2-quiet-dhclient.patch, + 0011-Fixed-linux-interface-discovery-using-getifaddrs.patch, + 0012-dhcp-4.2.x-chown-server-leases.bnc868253.patch, + 0013-dhcp-4.2.x-dhcpv6-decline-on-DAD-failure.872609.patch] - Fixed to not pass DHCPv6 address lifetimes a positive (unsigned 32bit) integers to scripts and properly format timestamps as long to not break them on 64bit architectures (bsc#926159). [+ 0014-dhclient6-unsigned-lifetimes-for-script-bsc-926159.patch] - dhclient: expose next-server DHCPv4 option to script (bsc#928390) [+ 0015-Expose-next-server-DHCPv4-option-to-dhclient-script.patch] - Replaced infiniband support patch with fixed variant (bsc#910984): [- 0017-dhcp-4.2.6-lpf-ip-over-ib-support.patch, - 0018-dhcp-4.2.6-improved-xid.patch, + 0016-infiniband-support.patch] - Moved dhcp-devel package include files and static libraries OBS-URL: https://build.opensuse.org/package/show/network:dhcp/dhcp?expand=0&rev=154
2015-09-14 17:35:16 +02:00
References: bnc#870535,bsc#909189,bsc#910984
- Update to dhcp-4.3.3 (fate#319067) provinding many bug fixes, features and obsoletes several patches we were using before. For complete list of the changes, please read the RELNOTES file shipped along with the package or online: https://kb.isc.org/article/AA-01297/82/DHCP-4.3.3-Release-Notes.html - Removed obsolete patches included upstream now: [- 0007-dhcp-4.2.6-ldap-mt01.patch, - 0009-dhcp-4.2.6-xen-checksum.patch, - 0013-dhcp-4.2.3-P1-dhclient-log-pid.patch, - 0015-Ignore-SIGPIPE-to-not-die-in-socket-code.patch, - 0016-server-log-DHCPv6-addresses-assigned-to-clients.patch, - 0019-dhcp-4.2.x-ldap-debug-write.bnc835818.patch, - 0021-dhcp-4.2.4-P2-bnc878846-conf-to-ldap.patch, - 0022-dhcp-4.2.x-contrib-conf-to-ldap-reorder.886094.patch, - 0023-dhcp-4.2.x-ddns-tsig-hmac-sha-support.890731.patch, - 0025-dhcp-4.2.x-dhcpv6-retransmission-until-MRD.872609.patch, - 0026-dhcp-4.2.x-disable-unused-ddns-port-in-server.891655.patch] - Replaced hostname patch with a dhcpv6 and fqdn aware variant: [- 0006-dhcp-4.2.5-dhclient-send-hostname-rml.patch, + 0006-dhcp-4.3.2-dhclient-send-hostname-or-fqdn.patch] - Replaced infiniband support patch with fixed variant: [- 0017-dhcp-4.2.6-lpf-ip-over-ib-support.patch - 0018-dhcp-4.2.6-improved-xid.patch - 0027-dhcp-4.2.x-handle-ifa_addr-NULL.909189.patch, + 0030-infiniband-support.patch] - Merged/Adopted patches for the dhcp-4.3.3 sources: [* 0004-dhcp-4.1.1-tmpfile.patch, * 0011-dhcp-4.2.6-close-on-exec.patch, * 0020-dhcp-4.2.x-chown-server-leases.bnc868253.patch] OBS-URL: https://build.opensuse.org/package/show/network:dhcp/dhcp?expand=0&rev=151
2015-09-14 14:11:04 +02:00
From 92250da05c2e4e3f1f60d627b52fe3f4f14828d3 Mon Sep 17 00:00:00 2001
From: Marius Tomaschewski <mt@suse.de>
Date: Mon, 14 Sep 2015 13:42:34 +0200
Subject: [PATCH] infiniband-support
Squashed rework based on the following commits:
commit 8f5918fa4319fc8173ca6e75d6e2ab8c379e980d
Author: Marius Tomaschewski <mt@suse.de>
Date: Mon Sep 14 12:26:12 2015 +0200
For complete changelog, please read the RELNOTES file shipped along with this package or online at: - Replaced hostname patch with a dhcpv6 and fqdn aware variant: [- 0006-dhcp-4.2.5-dhclient-send-hostname-rml.patch, + 0006-dhcp-4.3.2-dhclient-send-hostname-or-fqdn.patch] - Adjusted patch numbers in the spec file: [- 0008-dhcp-4.1.1-P1-lpf-bind-msg-fix.patch, - 0010-dhcp-4.2.2-dhclient-option-checks.patch, - 0011-dhcp-4.2.6-close-on-exec.patch, - 0012-dhcp-4.2.2-quiet-dhclient.patch, - 0014-Fixed-linux-interface-discovery-using-getifaddrs.patch, - 0020-dhcp-4.2.x-chown-server-leases.bnc868253.patch, - 0024-dhcp-4.2.x-dhcpv6-decline-on-DAD-failure.872609.patch, + 0008-dhcp-4.2.2-dhclient-option-checks.patch, + 0009-dhcp-4.2.6-close-on-exec.patch, + 0010-dhcp-4.2.2-quiet-dhclient.patch, + 0011-Fixed-linux-interface-discovery-using-getifaddrs.patch, + 0012-dhcp-4.2.x-chown-server-leases.bnc868253.patch, + 0013-dhcp-4.2.x-dhcpv6-decline-on-DAD-failure.872609.patch] - Fixed to not pass DHCPv6 address lifetimes a positive (unsigned 32bit) integers to scripts and properly format timestamps as long to not break them on 64bit architectures (bsc#926159). [+ 0014-dhclient6-unsigned-lifetimes-for-script-bsc-926159.patch] - dhclient: expose next-server DHCPv4 option to script (bsc#928390) [+ 0015-Expose-next-server-DHCPv4-option-to-dhclient-script.patch] - Replaced infiniband support patch with fixed variant (bsc#910984): [- 0017-dhcp-4.2.6-lpf-ip-over-ib-support.patch, - 0018-dhcp-4.2.6-improved-xid.patch, + 0016-infiniband-support.patch] - Moved dhcp-devel package include files and static libraries OBS-URL: https://build.opensuse.org/package/show/network:dhcp/dhcp?expand=0&rev=154
2015-09-14 17:35:16 +02:00
dhcp 4.3.3 ip over ib support fixes (bsc#910984)
- Update to dhcp-4.3.3 (fate#319067) provinding many bug fixes, features and obsoletes several patches we were using before. For complete list of the changes, please read the RELNOTES file shipped along with the package or online: https://kb.isc.org/article/AA-01297/82/DHCP-4.3.3-Release-Notes.html - Removed obsolete patches included upstream now: [- 0007-dhcp-4.2.6-ldap-mt01.patch, - 0009-dhcp-4.2.6-xen-checksum.patch, - 0013-dhcp-4.2.3-P1-dhclient-log-pid.patch, - 0015-Ignore-SIGPIPE-to-not-die-in-socket-code.patch, - 0016-server-log-DHCPv6-addresses-assigned-to-clients.patch, - 0019-dhcp-4.2.x-ldap-debug-write.bnc835818.patch, - 0021-dhcp-4.2.4-P2-bnc878846-conf-to-ldap.patch, - 0022-dhcp-4.2.x-contrib-conf-to-ldap-reorder.886094.patch, - 0023-dhcp-4.2.x-ddns-tsig-hmac-sha-support.890731.patch, - 0025-dhcp-4.2.x-dhcpv6-retransmission-until-MRD.872609.patch, - 0026-dhcp-4.2.x-disable-unused-ddns-port-in-server.891655.patch] - Replaced hostname patch with a dhcpv6 and fqdn aware variant: [- 0006-dhcp-4.2.5-dhclient-send-hostname-rml.patch, + 0006-dhcp-4.3.2-dhclient-send-hostname-or-fqdn.patch] - Replaced infiniband support patch with fixed variant: [- 0017-dhcp-4.2.6-lpf-ip-over-ib-support.patch - 0018-dhcp-4.2.6-improved-xid.patch - 0027-dhcp-4.2.x-handle-ifa_addr-NULL.909189.patch, + 0030-infiniband-support.patch] - Merged/Adopted patches for the dhcp-4.3.3 sources: [* 0004-dhcp-4.1.1-tmpfile.patch, * 0011-dhcp-4.2.6-close-on-exec.patch, * 0020-dhcp-4.2.x-chown-server-leases.bnc868253.patch] OBS-URL: https://build.opensuse.org/package/show/network:dhcp/dhcp?expand=0&rev=151
2015-09-14 14:11:04 +02:00
- verify client-identifier in responses as defined by RFC6864
- generate RFC4361 client-identifier for infiniband as required by
RFC4390; config file can still override it using send statement.
- fixed to set the ib hwaddr and guard copying/compares to chaddr;
it is used for client-identifier, improved xid and other things.
- fixed lpf send_packet to not break unicast on fallback socket.
commit 3173fd96fe8873f7924f8b5c3f2a6a34ebe1c90c
Author: root <root@reg-ovm-036-004.lab.mtl.com>
Date: Tue Mar 25 23:30:18 2014 +0200
dhcp 4.3.2 improved xid
References: bnc#870535
commit 7e27105baa2a86469efa17fe70667baa8bcc627f
Author: Jiri Slaby <jslaby@suse.cz>
Date: Wed Dec 10 13:48:03 2014 +0100
dhcp-4.2.x-handle-ifa_addr-NULL.909189
Fix to not crash in interface discovery when the interface
address is NULL. Bug has been introduced by the infiniband
support patch (bsc#870535).
References: bsc#909189,bnc#870535
commit 7818a340f84c0fe3c750baa721fb4221e2e2d443
Author: root <root@reg-ovm-036-004.lab.mtl.com>
Date: Tue Mar 25 23:15:58 2014 +0200
dhcp 4.3.2 lpf ip over ib support
References: bnc#870535
diff --git a/client/dhclient.c b/client/dhclient.c
index 0c77ae2..b438629 100644
--- a/client/dhclient.c
+++ b/client/dhclient.c
@@ -104,6 +104,40 @@ static int check_option_values(struct universe *universe, unsigned int opt,
static void dhclient_ddns_cb_free(dhcp_ddns_cb_t *ddns_cb,
char* file, int line);
+static void form_interface_duid(struct data_string *duid, struct interface_info *ip, const char *file, int line);
+
+static int check_client_identifier(struct option_state *packet_options, struct option_state *client_options)
+{
+ struct option_cache *client_oc;
+ struct option_cache *packet_oc;
+
+ /* RFC6864 check:
+ *
+ * When a client receives a DHCP message containing a 'client
+ * identifier' option, the client MUST compare that client
+ * identifier to the one it is configured to send.
+ * If the two client identifiers do not match, the client MUST
+ * silently discard the message.
+ */
+
+ /* no identifier received: not RFC6864 server ... */
+ if (!packet_options || !(packet_oc = lookup_option(&dhcp_universe, packet_options,
+ DHO_DHCP_CLIENT_IDENTIFIER)))
+ return 1;
+
+ /* client does not remember them in some cases ... */
+ if (!client_options || !(client_oc = lookup_option(&dhcp_universe, client_options,
+ DHO_DHCP_CLIENT_IDENTIFIER)))
+ return 1;
+
+ /* when we've sent one, the identifiers MUST match */
+ if (client_oc->data.len != packet_oc->data.len ||
+ memcmp(client_oc->data.data, packet_oc->data.data, client_oc->data.len))
+ return -1;
+
+ return 0;
+}
+
#ifndef UNIT_TEST
int
main(int argc, char **argv) {
@@ -635,6 +669,26 @@ main(int argc, char **argv) {
}
}
+ /* We create a backup seed before rediscovering interfaces in order to
+ have a seed built using all of the available interfaces
+ It's interesting if required interfaces doesn't let us defined
+ a really unique seed due to a lack of valid HW addr later
+ (this is the case with DHCP over IB)
+ We only use the last device as using a sum could broke the
+ uniqueness of the seed among multiple nodes
+ */
+ unsigned backup_seed = 0;
+ for (ip = interfaces; ip; ip = ip -> next) {
+ int junk;
+ if ( ip -> hw_address.hlen <= sizeof seed )
+ continue;
+ memcpy (&junk,
+ &ip -> hw_address.hbuf [ip -> hw_address.hlen -
+ sizeof seed], sizeof seed);
+ backup_seed = junk;
+ }
+
+
/* At this point, all the interfaces that the script thinks
are relevant should be running, so now we once again call
discover_interfaces(), and this time ask it to actually set
@@ -649,19 +703,42 @@ main(int argc, char **argv) {
Not much entropy, but we're booting, so we're not likely to
find anything better. */
seed = 0;
+ int seed_flag = 0;
for (ip = interfaces; ip; ip = ip->next) {
int junk;
+ if (ip->hw_address.hlen <= sizeof seed)
+ continue;
memcpy(&junk,
&ip->hw_address.hbuf[ip->hw_address.hlen -
sizeof seed], sizeof seed);
seed += junk;
+ seed_flag = 1;
}
- srandom(seed + cur_time + (unsigned)getpid());
+ if ( seed_flag == 0 ) {
+ if ( backup_seed != 0 ) {
+ seed = backup_seed;
+ log_info ("xid: rand init seed (0x%x) built using all"
+ " available interfaces",seed);
+ }
+ else {
+ seed = cur_time^((unsigned) gethostid()) ;
+ log_info ("xid: warning: no netdev with useable HWADDR found"
+ " for seed's uniqueness enforcement");
+ log_info ("xid: rand init seed (0x%x) built using gethostid",
+ seed);
+ }
+ /* we only use seed and no current time as a broadcast reply */
+ /* will certainly be used by the hwaddrless interface */
+ srandom(seed);
+ }
+ else
+ srandom(seed + cur_time + (unsigned)getpid());
/*
* Establish a default DUID. We always do so for v6 and
- * do so if desired for v4 via the -D or -i options
+ * do so if desired for v4 via the -D or -i options or
+ * when an infiniband interface is involved.
*/
if ((local_family == AF_INET6) ||
((local_family == AF_INET) && (duid_v4 == 1))) {
@@ -672,6 +749,20 @@ main(int argc, char **argv) {
form_duid(&default_duid, MDL);
write_duid(&default_duid);
}
+ } else {
+ for (ip = interfaces; ip; ip = ip->next) {
+ if (!ip->client || ip->hw_address.hbuf[0] != HTYPE_INFINIBAND)
+ continue;
+
+ if (default_duid.len == 0) {
+ if (default_duid.buffer != NULL)
+ data_string_forget(&default_duid, MDL);
+
+ form_duid(&default_duid, MDL);
+ write_duid(&default_duid);
+ break;
+ }
+ }
}
/* Start a configuration state machine for each interface. */
@@ -1143,15 +1234,22 @@ void dhcpack (packet)
if (client -> xid == packet -> raw -> xid)
break;
}
- if (!client ||
- (packet -> interface -> hw_address.hlen - 1 !=
- packet -> raw -> hlen) ||
- (memcmp (&packet -> interface -> hw_address.hbuf [1],
- packet -> raw -> chaddr, packet -> raw -> hlen))) {
+
+ if (!client || (packet -> raw -> hlen &&
+ ((packet -> interface -> hw_address.hlen - 1 !=
+ packet -> raw -> hlen) ||
+ (memcmp (&packet -> interface -> hw_address.hbuf [1],
+ packet -> raw -> chaddr, packet -> raw -> hlen))))) {
#if defined (DEBUG)
log_debug ("DHCPACK in wrong transaction.");
#endif
return;
+ } else
+ if (check_client_identifier(packet->options, client->sent_options) < 0) {
+#if defined (DEBUG)
+ log_debug ("response client identifier does not match ours");
+#endif
+ return;
}
if (client -> state != S_REBOOTING &&
@@ -1164,7 +1262,7 @@ void dhcpack (packet)
return;
}
- log_info ("DHCPACK from %s", piaddr (packet -> client_addr));
+ log_info ("DHCPACK from %s (xid=0x%x)", piaddr (packet -> client_addr), client -> xid);
lease = packet_to_lease (packet, client);
if (!lease) {
@@ -1629,15 +1727,21 @@ void dhcpoffer (packet)
/* If we're not receptive to an offer right now, or if the offer
has an unrecognizable transaction id, then just drop it. */
if (!client ||
- client -> state != S_SELECTING ||
- (packet -> interface -> hw_address.hlen - 1 !=
- packet -> raw -> hlen) ||
- (memcmp (&packet -> interface -> hw_address.hbuf [1],
- packet -> raw -> chaddr, packet -> raw -> hlen))) {
+ client -> state != S_SELECTING || (packet -> raw -> hlen &&
+ ((packet -> interface -> hw_address.hlen - 1 !=
+ packet -> raw -> hlen) ||
+ (memcmp (&packet -> interface -> hw_address.hbuf [1],
+ packet -> raw -> chaddr, packet -> raw -> hlen))))) {
#if defined (DEBUG)
log_debug ("%s in wrong transaction.", name);
#endif
return;
+ } else
+ if (check_client_identifier(packet->options, client->sent_options) < 0) {
+#if defined (DEBUG)
+ log_debug ("response client identifier does not match ours");
+#endif
+ return;
}
sprintf (obuf, "%s from %s", name, piaddr (packet -> client_addr));
@@ -1875,11 +1979,11 @@ void dhcpnak (packet)
/* If we're not receptive to an offer right now, or if the offer
has an unrecognizable transaction id, then just drop it. */
- if (!client ||
- (packet -> interface -> hw_address.hlen - 1 !=
- packet -> raw -> hlen) ||
- (memcmp (&packet -> interface -> hw_address.hbuf [1],
- packet -> raw -> chaddr, packet -> raw -> hlen))) {
+ if (!client || (packet -> raw -> hlen &&
+ ((packet -> interface -> hw_address.hlen - 1 !=
+ packet -> raw -> hlen) ||
+ (memcmp (&packet -> interface -> hw_address.hbuf [1],
+ packet -> raw -> chaddr, packet -> raw -> hlen))))) {
#if defined (DEBUG)
log_debug ("DHCPNAK in wrong transaction.");
#endif
@@ -1894,9 +1998,15 @@ void dhcpnak (packet)
log_debug ("DHCPNAK in wrong state.");
#endif
return;
+ } else
+ if (check_client_identifier(packet->options, client->sent_options) < 0) {
+#if defined (DEBUG)
+ log_debug ("response client identifier does not match ours");
+#endif
+ return;
}
- log_info ("DHCPNAK from %s", piaddr (packet -> client_addr));
+ log_info ("DHCPNAK from %s (xid=0x%x)", piaddr (packet -> client_addr), client -> xid);
if (!client -> active) {
#if defined (DEBUG)
@@ -2023,10 +2133,10 @@ void send_discover (cpp)
client -> packet.secs = htons (65535);
client -> secs = client -> packet.secs;
- log_info ("DHCPDISCOVER on %s to %s port %d interval %ld",
- client -> name ? client -> name : client -> interface -> name,
- inet_ntoa (sockaddr_broadcast.sin_addr),
- ntohs (sockaddr_broadcast.sin_port), (long)(client -> interval));
+ log_info ("DHCPDISCOVER on %s to %s port %d interval %ld (xid=0x%x)",
+ client -> name ? client -> name : client -> interface -> name,
+ inet_ntoa (sockaddr_broadcast.sin_addr),
+ ntohs (sockaddr_broadcast.sin_port), (long)(client -> interval), client -> xid);
/* Send out a packet. */
result = send_packet(client->interface, NULL, &client->packet,
@@ -2295,10 +2405,10 @@ void send_request (cpp)
client -> packet.secs = htons (65535);
}
- log_info ("DHCPREQUEST on %s to %s port %d",
+ log_info ("DHCPREQUEST on %s to %s port %d (xid=0x%x)",
client -> name ? client -> name : client -> interface -> name,
inet_ntoa (destination.sin_addr),
- ntohs (destination.sin_port));
+ ntohs (destination.sin_port), client -> xid);
if (destination.sin_addr.s_addr != INADDR_BROADCAST &&
fallback_interface) {
@@ -2338,10 +2448,10 @@ void send_decline (cpp)
int result;
- log_info ("DHCPDECLINE on %s to %s port %d",
+ log_info ("DHCPDECLINE on %s to %s port %d (xid=0x%x)",
client->name ? client->name : client->interface->name,
inet_ntoa(sockaddr_broadcast.sin_addr),
- ntohs(sockaddr_broadcast.sin_port));
+ ntohs (sockaddr_broadcast.sin_port), client -> xid);
/* Send out a packet. */
result = send_packet(client->interface, NULL, &client->packet,
@@ -2384,10 +2494,10 @@ void send_release (cpp)
return;
}
- log_info ("DHCPRELEASE on %s to %s port %d",
+ log_info ("DHCPRELEASE on %s to %s port %d (xid=0x%x)",
client -> name ? client -> name : client -> interface -> name,
inet_ntoa (destination.sin_addr),
- ntohs (destination.sin_port));
+ ntohs (destination.sin_port), client -> xid);
if (fallback_interface) {
result = send_packet(fallback_interface, NULL, &client->packet,
@@ -2507,10 +2617,17 @@ make_client_options(struct client_state *client, struct client_lease *lease,
* This can be overridden by including a client id in the configuration
* file.
*/
- if (duid_v4 == 1) {
+ if (duid_v4 == 1 || client->interface->hw_address.hbuf[0] == HTYPE_INFINIBAND) {
struct data_string client_identifier;
int hw_idx, hw_len;
+ if (default_duid.len == 0) {
+ if (default_duid.buffer != NULL)
+ data_string_forget(&default_duid, MDL);
+
+ form_interface_duid(&default_duid, client->interface, MDL);
+ }
+
memset(&client_identifier, 0, sizeof(client_identifier));
client_identifier.len = 1 + 4 + default_duid.len;
if (!buffer_allocate(&client_identifier.buffer,
@@ -2600,12 +2717,13 @@ void make_discover (client, lease)
client -> packet.op = BOOTREQUEST;
client -> packet.htype = client -> interface -> hw_address.hbuf [0];
- client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
+ if (client -> interface -> hw_address.hlen - 1 <= sizeof(client -> packet.chaddr))
+ client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
client -> packet.hops = 0;
client -> packet.xid = random ();
client -> packet.secs = 0; /* filled in by send_discover. */
- if (can_receive_unicast_unconfigured (client -> interface))
+ if (can_receive_unicast_unconfigured (client -> interface) && client -> packet.hlen)
client -> packet.flags = 0;
else
client -> packet.flags = htons (BOOTP_BROADCAST);
@@ -2617,7 +2735,7 @@ void make_discover (client, lease)
memset (&(client -> packet.siaddr),
0, sizeof client -> packet.siaddr);
client -> packet.giaddr = giaddr;
- if (client -> interface -> hw_address.hlen > 0)
+ if (client -> interface -> hw_address.hlen > 1 && client -> packet.hlen)
memcpy (client -> packet.chaddr,
&client -> interface -> hw_address.hbuf [1],
(unsigned)(client -> interface -> hw_address.hlen - 1));
@@ -2673,7 +2791,8 @@ void make_request (client, lease)
client -> packet.op = BOOTREQUEST;
client -> packet.htype = client -> interface -> hw_address.hbuf [0];
- client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
+ if (client -> interface -> hw_address.hlen - 1 <= sizeof(client -> packet.chaddr))
+ client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
client -> packet.hops = 0;
client -> packet.xid = client -> xid;
client -> packet.secs = 0; /* Filled in by send_request. */
@@ -2705,7 +2824,7 @@ void make_request (client, lease)
else
memset (&client -> packet.giaddr, 0,
sizeof client -> packet.giaddr);
- if (client -> interface -> hw_address.hlen > 0)
+ if (client -> interface -> hw_address.hlen > 1 && client -> packet.hlen)
memcpy (client -> packet.chaddr,
&client -> interface -> hw_address.hbuf [1],
(unsigned)(client -> interface -> hw_address.hlen - 1));
@@ -2747,7 +2866,8 @@ void make_decline (client, lease)
client -> packet.op = BOOTREQUEST;
client -> packet.htype = client -> interface -> hw_address.hbuf [0];
- client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
+ if (client -> interface -> hw_address.hlen - 1 <= sizeof(client -> packet.chaddr))
+ client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
client -> packet.hops = 0;
client -> packet.xid = client -> xid;
client -> packet.secs = 0; /* Filled in by send_request. */
@@ -2764,9 +2884,10 @@ void make_decline (client, lease)
memset (&client -> packet.siaddr, 0,
sizeof client -> packet.siaddr);
client -> packet.giaddr = giaddr;
- memcpy (client -> packet.chaddr,
- &client -> interface -> hw_address.hbuf [1],
- client -> interface -> hw_address.hlen);
+ if (client -> interface -> hw_address.hlen > 1 && client -> packet.hlen)
+ memcpy (client -> packet.chaddr,
+ &client -> interface -> hw_address.hbuf [1],
+ client -> interface -> hw_address.hlen - 1);
#ifdef DEBUG_PACKET
dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
@@ -2808,7 +2929,8 @@ void make_release (client, lease)
client -> packet.op = BOOTREQUEST;
client -> packet.htype = client -> interface -> hw_address.hbuf [0];
- client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
+ if (client -> interface -> hw_address.hlen - 1 <= sizeof(client -> packet.chaddr))
+ client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
client -> packet.hops = 0;
client -> packet.xid = random ();
client -> packet.secs = 0;
@@ -2820,9 +2942,10 @@ void make_release (client, lease)
memset (&client -> packet.siaddr, 0,
sizeof client -> packet.siaddr);
client -> packet.giaddr = giaddr;
- memcpy (client -> packet.chaddr,
- &client -> interface -> hw_address.hbuf [1],
- client -> interface -> hw_address.hlen);
+ if (client -> interface -> hw_address.hlen > 1 && client -> packet.hlen)
+ memcpy (client -> packet.chaddr,
+ &client -> interface -> hw_address.hbuf [1],
+ client -> interface -> hw_address.hlen);
#ifdef DEBUG_PACKET
dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
@@ -2975,17 +3098,13 @@ write_options(struct client_state *client, struct option_state *options,
* is not how it is intended. Upcoming rearchitecting the client should
* address this "one daemon model."
*/
-void
-form_duid(struct data_string *duid, const char *file, int line)
+static void
+form_interface_duid(struct data_string *duid, struct interface_info *ip, const char *file, int line)
{
- struct interface_info *ip;
int len;
char *str;
- /* For now, just use the first interface on the list. */
- ip = interfaces;
-
- if (ip == NULL)
+ if (ip == NULL || duid == NULL)
log_fatal("Impossible condition at %s:%d.", MDL);
if ((ip->hw_address.hlen == 0) ||
@@ -3033,6 +3152,13 @@ form_duid(struct data_string *duid, const char *file, int line)
}
}
+void
+form_duid(struct data_string *duid, const char *file, int line)
+{
+ /* For now, just use the first interface on the list. */
+ form_interface_duid(duid, interfaces, file, line);
+}
+
/* Write the default DUID to the lease store. */
static isc_result_t
write_duid(struct data_string *duid)
@@ -4368,7 +4494,8 @@ client_dns_update(struct client_state *client, dhcp_ddns_cb_t *ddns_cb)
NULL, client,
client->sent_options, NULL,
&global_scope, oc, MDL)) {
- if ((std_dhcid == 1) && (duid_v4 == 1) &&
+ if ((std_dhcid == 1) && (duid_v4 == 1 ||
+ client->interface->hw_address.hbuf[0] == HTYPE_INFINIBAND) &&
(client_identifier.data[0] == 255)) {
/*
* This appears to be an embedded DUID,
diff --git a/common/bpf.c b/common/bpf.c
index df9facc..23d416a 100644
--- a/common/bpf.c
+++ b/common/bpf.c
@@ -117,7 +117,7 @@ int if_register_bpf (info)
log_fatal ("Can't attach interface %s to bpf device %s: %m",
info -> name, filename);
- get_hw_addr(info->name, &info->hw_address);
+ get_hw_addr(info);
return sock;
}
@@ -199,11 +199,44 @@ struct bpf_insn dhcp_bpf_filter [] = {
BPF_STMT(BPF_RET+BPF_K, 0),
};
+/* Packet filter program for DHCP over Infiniband.
+ * It is a generic UDP in IP packet filter (initialized to port 67 in [6].k).
+ *
+ * XXX
+ * Changes to the filter program may require changes to the constant offsets
+ * used in lpf_gen_filter_setup to patch the port in the BPF program!
+ * XXX
+ */
+struct bpf_insn dhcp_ib_bpf_filter [] = {
+ /* Make sure it's a UDP packet... */
+ BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 9),
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
+
+ /* Make sure this isn't a fragment... */
+ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 6),
+ BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
+
+ /* Get the IP header length... */
+ BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 0),
+
+ /* Make sure it's to the right port... */
+ BPF_STMT(BPF_LD + BPF_H + BPF_IND, 2),
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1),
+
+ /* If we passed all the tests, ask for the whole packet. */
+ BPF_STMT(BPF_RET + BPF_K, (u_int)-1),
+
+ /* Otherwise, drop it. */
+ BPF_STMT(BPF_RET + BPF_K, 0),
+};
+
#if defined (DEC_FDDI)
struct bpf_insn *bpf_fddi_filter;
#endif
int dhcp_bpf_filter_len = sizeof dhcp_bpf_filter / sizeof (struct bpf_insn);
+int dhcp_ib_bpf_filter_len = sizeof dhcp_ib_bpf_filter / sizeof (struct bpf_insn);
+
#if defined (HAVE_TR_SUPPORT)
struct bpf_insn dhcp_bpf_tr_filter [] = {
/* accept all token ring packets due to variable length header */
@@ -550,7 +583,9 @@ void maybe_setup_fallback ()
#if defined(USE_BPF_RECEIVE) || defined(USE_BPF_HWADDR)
void
-get_hw_addr(const char *name, struct hardware *hw) {
+get_hw_addr(struct interface_info *info) {
+ const char *name = info->name;
+ struct hardware *hw = &info->hw_address;
struct ifaddrs *ifa;
struct ifaddrs *p;
struct sockaddr_dl *sa;
diff --git a/common/dlpi.c b/common/dlpi.c
index 944f21c..5cc2f3b 100644
--- a/common/dlpi.c
+++ b/common/dlpi.c
@@ -1330,7 +1330,9 @@ void maybe_setup_fallback ()
#endif /* USE_DLPI_SEND */
void
-get_hw_addr(const char *name, struct hardware *hw) {
+get_hw_addr(struct interface_info *info) {
+ const char *name = info->name;
+ struct hardware *hw = &info->hw_address;
int sock, unit;
long buf[DLPI_MAXDLBUF];
union DL_primitives *dlp;
diff --git a/common/lpf.c b/common/lpf.c
index 8582f31..745d3c0 100644
--- a/common/lpf.c
+++ b/common/lpf.c
@@ -47,12 +47,22 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
+#include <ifaddrs.h>
#endif
#if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE)
/* Reinitializes the specified interface after an address change. This
is not required for packet-filter APIs. */
+/* Default broadcast address for IPoIB */
+static unsigned char default_ib_bcast_addr[20] = {
+ 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0x12, 0x40, 0x1b,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff
+};
+
#ifdef USE_LPF_SEND
void if_reinitialize_send (info)
struct interface_info *info;
@@ -80,10 +90,25 @@ int if_register_lpf (info)
struct sockaddr common;
} sa;
struct ifreq ifr;
+ int type;
+ int protocol;
/* Make an LPF socket. */
- if ((sock = socket(PF_PACKET, SOCK_RAW,
- htons((short)ETH_P_ALL))) < 0) {
+ get_hw_addr(info);
+
+ if (info->hw_address.hbuf[0] == HTYPE_INFINIBAND) {
+ /*
+ * Infiniband provides a 4-octet encapsulation
+ * header [08 00 00 00] only, so just omit it.
+ */
+ type = SOCK_DGRAM;
+ protocol = ETHERTYPE_IP;
+ } else {
+ type = SOCK_RAW;
+ protocol = ETH_P_ALL;
+ }
+
+ if ((sock = socket(PF_PACKET, type, htons((short)protocol))) < 0) {
if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
errno == EAFNOSUPPORT || errno == EINVAL) {
@@ -107,6 +132,7 @@ int if_register_lpf (info)
memset (&sa, 0, sizeof sa);
sa.ll.sll_family = AF_PACKET;
sa.ll.sll_ifindex = ifr.ifr_ifindex;
+ sa.ll.sll_protocol = htons(protocol);
if (bind (sock, &sa.common, sizeof sa)) {
if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
@@ -122,8 +148,6 @@ int if_register_lpf (info)
}
- get_hw_addr(info->name, &info->hw_address);
-
return sock;
}
#endif /* USE_LPF_SEND || USE_LPF_RECEIVE */
@@ -178,6 +202,8 @@ void if_deregister_send (info)
in bpf includes... */
extern struct sock_filter dhcp_bpf_filter [];
extern int dhcp_bpf_filter_len;
+extern struct sock_filter dhcp_ib_bpf_filter [];
+extern int dhcp_ib_bpf_filter_len;
#if defined (HAVE_TR_SUPPORT)
extern struct sock_filter dhcp_bpf_tr_filter [];
@@ -185,6 +211,8 @@ extern int dhcp_bpf_tr_filter_len;
static void lpf_tr_filter_setup (struct interface_info *);
#endif
+static void lpf_ib_filter_setup (struct interface_info *);
+
static void lpf_gen_filter_setup (struct interface_info *);
void if_register_receive (info)
@@ -206,12 +234,14 @@ void if_register_receive (info)
}
#endif
-
#if defined (HAVE_TR_SUPPORT)
if (info -> hw_address.hbuf [0] == HTYPE_IEEE802)
lpf_tr_filter_setup (info);
else
#endif
+ if (info -> hw_address.hbuf [0] == HTYPE_INFINIBAND)
+ lpf_ib_filter_setup (info);
+ else
lpf_gen_filter_setup (info);
if (!quiet_interface_discovery)
@@ -276,6 +306,38 @@ static void lpf_gen_filter_setup (info)
}
}
+static void lpf_ib_filter_setup (info)
+ struct interface_info *info;
+{
+ struct sock_fprog p;
+
+ memset(&p, 0, sizeof(p));
+
+ /* Set up the bpf filter program structure */
+ p.len = dhcp_ib_bpf_filter_len;
+ p.filter = dhcp_ib_bpf_filter;
+
+ /* Patch the server port into the LPF program...
+ XXX changes to filter program may require changes
+ to the insn number(s) used below! XXX */
+ dhcp_ib_bpf_filter [6].k = ntohs ((short)local_port);
+
+ if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p,
+ sizeof p) < 0) {
+ if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
+ errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
+ errno == EAFNOSUPPORT) {
+ log_error ("socket: %m - make sure");
+ log_error ("CONFIG_PACKET (Packet socket) %s",
+ "and CONFIG_FILTER");
+ log_error ("(Socket Filtering) are enabled %s",
+ "in your kernel");
+ log_fatal ("configuration!");
+ }
+ log_fatal ("Can't install packet filter program: %m");
+ }
+}
+
#if defined (HAVE_TR_SUPPORT)
static void lpf_tr_filter_setup (info)
struct interface_info *info;
@@ -315,6 +377,54 @@ static void lpf_tr_filter_setup (info)
#endif /* USE_LPF_RECEIVE */
#ifdef USE_LPF_SEND
+ssize_t send_packet_ib(interface, packet, raw, len, from, to, hto)
+ struct interface_info *interface;
+ struct packet *packet;
+ struct dhcp_packet *raw;
+ size_t len;
+ struct in_addr from;
+ struct sockaddr_in *to;
+ struct hardware *hto;
+{
+ unsigned ibufp = 0;
+ double ih [1536 / sizeof (double)];
+ unsigned char *buf = (unsigned char *)ih;
+ ssize_t result;
+
+ union sockunion {
+ struct sockaddr sa;
+ struct sockaddr_ll sll;
+ struct sockaddr_storage ss;
+ } su;
+
+ assemble_udp_ip_header (interface, buf, &ibufp, from.s_addr,
+ to->sin_addr.s_addr, to->sin_port,
+ (unsigned char *)raw, len);
+ memcpy (buf + ibufp, raw, len);
+
+ memset(&su, 0, sizeof(su));
+ su.sll.sll_family = AF_PACKET;
+ su.sll.sll_protocol = htons(ETHERTYPE_IP);
+
+ if (!(su.sll.sll_ifindex = if_nametoindex(interface->name))) {
+ errno = ENOENT;
+ log_error ("send_packet_ib: %m - failed to get if index");
+ return -1;
+ }
+
+ su.sll.sll_hatype = htons(HTYPE_INFINIBAND);
+ su.sll.sll_halen = sizeof(interface->bcast_addr);
+ memcpy(&su.sll.sll_addr, interface->bcast_addr, 20);
+
+ result = sendto(interface->wfdesc, buf, ibufp + len, 0,
+ &su.sa, sizeof(su));
+
+ if (result < 0)
+ log_error ("send_packet_ib: %m");
+
+ return result;
+}
+
ssize_t send_packet (interface, packet, raw, len, from, to, hto)
struct interface_info *interface;
struct packet *packet;
@@ -335,6 +445,10 @@ ssize_t send_packet (interface, packet, raw, len, from, to, hto)
return send_fallback (interface, packet, raw,
len, from, to, hto);
+ if (interface->hw_address.hbuf[0] == HTYPE_INFINIBAND)
+ return send_packet_ib(interface, packet, raw,
+ len, from, to, hto);
+
if (hto == NULL && interface->anycast_mac_addr.hlen)
hto = &interface->anycast_mac_addr;
@@ -439,7 +553,15 @@ ssize_t receive_packet (interface, buf, len, from, hfrom)
bufix = 0;
/* Decode the physical header... */
- offset = decode_hw_header (interface, ibuf, bufix, hfrom);
+ if (interface->hw_address.hbuf[0] == HTYPE_INFINIBAND) {
+ /* ETHERTYPE_IP packet, no HW header to decode */
+ if (hfrom) {
+ memset(hfrom, 0, sizeof(*hfrom));
+ hfrom->hbuf[0] = HTYPE_INFINIBAND;
+ }
+ } else {
+ offset = decode_hw_header (interface, ibuf, bufix, hfrom);
+ }
/* If a physical layer checksum failed (dunno of any
physical layer that supports this, but WTH), skip this
@@ -507,33 +629,44 @@ void maybe_setup_fallback ()
#if defined (USE_LPF_RECEIVE) || defined (USE_LPF_HWADDR)
void
-get_hw_addr(const char *name, struct hardware *hw) {
- int sock;
- struct ifreq tmp;
- struct sockaddr *sa;
+get_hw_addr(struct interface_info *info)
+{
+ const char *name = info->name;
+ struct hardware *hw = &info->hw_address;
+ struct ifaddrs *ifaddrs;
+ struct ifaddrs *ifa;
+ struct sockaddr_ll *sll = NULL;
- if (strlen(name) >= sizeof(tmp.ifr_name)) {
- log_fatal("Device name too long: \"%s\"", name);
- }
+ if (getifaddrs(&ifaddrs) == -1)
+ log_fatal("Failed to get interfaces");
+
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+
+ if (!ifa->ifa_addr)
+ continue;
+
+ if (ifa->ifa_addr->sa_family != AF_PACKET)
+ continue;
- sock = socket(AF_INET, SOCK_DGRAM, 0);
- if (sock < 0) {
- log_fatal("Can't create socket for \"%s\": %m", name);
+ if (ifa->ifa_flags & IFF_LOOPBACK)
+ continue;
+
+ if (strcmp(ifa->ifa_name, name) == 0) {
+ sll = (struct sockaddr_ll *)(void *)ifa->ifa_addr;
+ break;
+ }
}
- memset(&tmp, 0, sizeof(tmp));
- strcpy(tmp.ifr_name, name);
- if (ioctl(sock, SIOCGIFHWADDR, &tmp) < 0) {
- log_fatal("Error getting hardware address for \"%s\": %m",
- name);
+ if (sll == NULL || sll->sll_halen >= sizeof(hw->hbuf)) {
+ freeifaddrs(ifaddrs);
+ log_fatal("Failed to get HW address for %s\n", name);
}
- sa = &tmp.ifr_hwaddr;
- switch (sa->sa_family) {
+ switch (sll->sll_hatype) {
case ARPHRD_ETHER:
hw->hlen = 7;
hw->hbuf[0] = HTYPE_ETHER;
- memcpy(&hw->hbuf[1], sa->sa_data, 6);
+ memcpy(&hw->hbuf[1], sll->sll_addr, 6);
break;
case ARPHRD_IEEE802:
#ifdef ARPHRD_IEEE802_TR
@@ -541,18 +674,37 @@ get_hw_addr(const char *name, struct hardware *hw) {
#endif /* ARPHRD_IEEE802_TR */
hw->hlen = 7;
hw->hbuf[0] = HTYPE_IEEE802;
- memcpy(&hw->hbuf[1], sa->sa_data, 6);
+ memcpy(&hw->hbuf[1], sll->sll_addr, 6);
break;
case ARPHRD_FDDI:
hw->hlen = 7;
hw->hbuf[0] = HTYPE_FDDI;
- memcpy(&hw->hbuf[1], sa->sa_data, 6);
+ memcpy(&hw->hbuf[1], sll->sll_addr, 6);
+ break;
+ case ARPHRD_INFINIBAND:
+ /* For Infiniband, save the broadcast address and store
+ * the port GUID into the hardware address.
+ */
+ if (ifa->ifa_flags & IFF_BROADCAST) {
+ struct sockaddr_ll *bll;
+
+ bll = (struct sockaddr_ll *)ifa->ifa_broadaddr;
+ memcpy(&info->bcast_addr, bll->sll_addr, sll->sll_halen);
+ } else {
+ memcpy(&info->bcast_addr, default_ib_bcast_addr,
+ sizeof(default_ib_bcast_addr));
+ }
+
+ hw->hlen = sll->sll_halen + 1;
+ hw->hbuf[0] = HTYPE_INFINIBAND;
+ memcpy(&hw->hbuf[1], sll->sll_addr, sll->sll_halen);
break;
default:
+ freeifaddrs(ifaddrs);
log_fatal("Unsupported device type %ld for \"%s\"",
- (long int)sa->sa_family, name);
+ (long int)sll->sll_family, name);
}
- close(sock);
+ freeifaddrs(ifaddrs);
}
#endif
diff --git a/common/print.c b/common/print.c
index dfe0593..aa7b8e2 100644
--- a/common/print.c
+++ b/common/print.c
@@ -162,11 +162,11 @@ char *print_hw_addr (htype, hlen, data)
const int hlen;
const unsigned char *data;
{
- static char habuf [49];
+ static char habuf [64];
char *s;
int i;
- if (hlen <= 0)
+ if (hlen <= 0 || hlen >= sizeof(habuf))
habuf [0] = 0;
else {
s = habuf;
diff --git a/common/socket.c b/common/socket.c
index e8851b4..2c6fb1c 100644
--- a/common/socket.c
+++ b/common/socket.c
@@ -328,7 +328,7 @@ void if_register_send (info)
info->wfdesc = if_register_socket(info, AF_INET, 0, NULL);
/* If this is a normal IPv4 address, get the hardware address. */
if (strcmp(info->name, "fallback") != 0)
- get_hw_addr(info->name, &info->hw_address);
+ get_hw_addr(info);
#if defined (USE_SOCKET_FALLBACK)
/* Fallback only registers for send, but may need to receive as
well. */
@@ -391,7 +391,7 @@ void if_register_receive (info)
#endif /* IP_PKTINFO... */
/* If this is a normal IPv4 address, get the hardware address. */
if (strcmp(info->name, "fallback") != 0)
- get_hw_addr(info->name, &info->hw_address);
+ get_hw_addr(info);
if (!quiet_interface_discovery)
log_info ("Listening on Socket/%s%s%s",
@@ -505,7 +505,7 @@ if_register6(struct interface_info *info, int do_multicast) {
if (req_multi)
if_register_multicast(info);
- get_hw_addr(info->name, &info->hw_address);
+ get_hw_addr(info);
if (!quiet_interface_discovery) {
if (info->shared_network != NULL) {
@@ -561,7 +561,7 @@ if_register_linklocal6(struct interface_info *info) {
info->rfdesc = sock;
info->wfdesc = sock;
- get_hw_addr(info->name, &info->hw_address);
+ get_hw_addr(info);
if (!quiet_interface_discovery) {
if (info->shared_network != NULL) {
@@ -1145,7 +1145,9 @@ void maybe_setup_fallback ()
#if defined(sun) && defined(USE_V4_PKTINFO)
/* This code assumes the existence of SIOCGLIFHWADDR */
void
-get_hw_addr(const char *name, struct hardware *hw) {
+get_hw_addr(struct interface_info *info) {
+ const char *name = info->name;
+ struct hardware *hw = &info->hw_address;
struct sockaddr_dl *dladdrp;
int sock, i;
struct lifreq lifr;
diff --git a/includes/dhcpd.h b/includes/dhcpd.h
index f0f4b20..0a04f04 100644
--- a/includes/dhcpd.h
+++ b/includes/dhcpd.h
@@ -1321,6 +1321,7 @@ struct interface_info {
struct shared_network *shared_network;
/* Networks connected to this interface. */
struct hardware hw_address; /* Its physical address. */
+ u_int8_t bcast_addr[HARDWARE_ADDR_LEN]; /* broadcast hw address */
struct in_addr *addresses; /* Addresses associated with this
* interface.
*/
@@ -2542,7 +2543,7 @@ void print_dns_status (int, struct dhcp_ddns_cb *, isc_result_t);
#endif
const char *print_time(TIME);
-void get_hw_addr(const char *name, struct hardware *hw);
+void get_hw_addr(struct interface_info *info);
/* socket.c */
#if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_RECEIVE) \
diff --git a/server/dhcp.c b/server/dhcp.c
index 1f007e2..0f53ac2 100644
--- a/server/dhcp.c
+++ b/server/dhcp.c
@@ -1806,11 +1806,12 @@ void echo_client_id(packet, lease, in_options, out_options)
/* Check if echo-client-id is enabled */
oc = lookup_option(&server_universe, in_options, SV_ECHO_CLIENT_ID);
- if (oc && evaluate_boolean_option_cache(&ignorep, packet, lease,
+ if ((packet->raw && packet->raw->hlen == 0) ||
+ (oc && evaluate_boolean_option_cache(&ignorep, packet, lease,
NULL, packet->options,
in_options,
(lease ? &lease->scope : NULL),
- oc, MDL)) {
+ oc, MDL))) {
struct data_string client_id;
unsigned int opcode = DHO_DHCP_CLIENT_IDENTIFIER;
@@ -3592,9 +3593,11 @@ void dhcp_reply (lease)
} else
bufs |= 2; /* XXX */
- memcpy (raw.chaddr,
- &lease -> hardware_addr.hbuf [1], sizeof raw.chaddr);
- raw.hlen = lease -> hardware_addr.hlen - 1;
+ if (lease -> hardware_addr.hlen - 1 <= sizeof(raw.chaddr))
+ raw.hlen = lease -> hardware_addr.hlen - 1;
+ if (lease -> hardware_addr.hlen > 1 && raw.hlen)
+ memcpy (raw.chaddr,
+ &lease -> hardware_addr.hbuf [1], raw.hlen);
raw.htype = lease -> hardware_addr.hbuf [0];
/* See if this is a Microsoft client that NUL-terminates its
diff --git a/server/dhcpleasequery.c b/server/dhcpleasequery.c
index 0766b84..c9a1e8b 100644
--- a/server/dhcpleasequery.c
+++ b/server/dhcpleasequery.c
@@ -295,7 +295,7 @@ dhcpleasequery(struct packet *packet, int ms_nulltp) {
assoc_ips,
nassoc_ips);
- } else {
+ } else if (packet->raw->hlen) {
if (packet->raw->hlen+1 > sizeof(h.hbuf)) {
log_info("%s: hardware length too long, "
@@ -405,11 +405,13 @@ dhcpleasequery(struct packet *packet, int ms_nulltp) {
* Set the hardware address fields.
*/
- packet->raw->hlen = lease->hardware_addr.hlen - 1;
packet->raw->htype = lease->hardware_addr.hbuf[0];
- memcpy(packet->raw->chaddr,
- &lease->hardware_addr.hbuf[1],
- sizeof(packet->raw->chaddr));
+ if (lease->hardware_addr.hlen - 1 <= sizeof(packet->raw->chaddr))
+ packet->raw->hlen = lease->hardware_addr.hlen - 1;
+ if (lease->hardware_addr.hlen > 1 && packet->raw->hlen)
+ memcpy(packet->raw->chaddr,
+ &lease->hardware_addr.hbuf[1],
+ packet->raw->hlen);
/*
* Set client identifier option.
diff --git a/server/mdb.c b/server/mdb.c
index 9a7da80..539a233 100644
--- a/server/mdb.c
+++ b/server/mdb.c
@@ -619,6 +619,9 @@ int find_hosts_by_haddr (struct host_decl **hp, int htype,
return ret;
#endif
+ if (!hlen || hlen > HARDWARE_ADDR_LEN)
+ return 0;
+
h.hlen = hlen + 1;
h.hbuf [0] = htype;
memcpy (&h.hbuf [1], haddr, hlen);
--
2.1.4