853382bddd
- fixed a typo in nis-servers option name breaking the config file introduced in previous change to workaround issues in NetworkManager parser. - Update to dhcp-4.3.5 - Corrected a bug which could cause the server to sporadically crash while loading lease files with the lease-id-format is set to "hex". Our thanks to Jay Ford, University of Iowa for reporting the issue. [ISC-Bugs #43185] - Eliminated a noisy, but otherwise harmless debug log statment that may appear during server startup when building with --enable-binary-leases and configuring multiple pools in a shared network. Thanks to Fernando Soto from BlueCat Networks for reporting the issue and supplying a patch. [ISC-Bugs #43262] - Fixed util/bindvar.sh error handling. [ISC-Bugs #41973] - Correct error message in relay to use remote id length instead of circuit id length. [ISC-Bugs #42556] - Add logic to test directory Makefiles to avoid copying Attfile(s) when building within the source tree. This eliminates a noisy but otherwise harmless error message when running "make check". [ISC-Bugs #41883] - Leases are now scrubbed of certain prior use information when pool re-balancing reassigns them from one FO peer to the other. This corrects an issue where leases that were offered but not used by the client retained the client hostname from the original client. Thanks to Pavel Polacek, Jan Evangelista Purkyne University for reporting the issue. [ISC-Bugs #42008] - In the LDAP code and schema add some missing '6' characters to use the v6 instead of the v4 versions. Thanks to Denis Taranushin for OBS-URL: https://build.opensuse.org/request/show/508601 OBS-URL: https://build.opensuse.org/package/show/network:dhcp/dhcp?expand=0&rev=174
1108 lines
37 KiB
Diff
1108 lines
37 KiB
Diff
References: bnc#870535,bsc#909189,bsc#910984
|
|
|
|
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
|
|
|
|
dhcp 4.3.3 ip over ib support fixes (bsc#910984)
|
|
|
|
- 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 3f2f8b2..40d9fe0 100644
|
|
--- a/client/dhclient.c
|
|
+++ b/client/dhclient.c
|
|
@@ -71,6 +71,40 @@ int std_dhcid = 0;
|
|
assert (state_is == state_shouldbe). */
|
|
#define ASSERT_STATE(state_is, state_shouldbe) {}
|
|
|
|
+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
|
|
static const char copyright[] = "Copyright 2004-2016 Internet Systems Consortium.";
|
|
static const char arr [] = "All rights reserved.";
|
|
@@ -756,6 +790,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
|
|
@@ -770,19 +824,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))) {
|
|
@@ -793,6 +870,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;
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
#if defined(DHCPv6) && defined(DHCP4o6)
|
|
@@ -1282,15 +1373,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 &&
|
|
@@ -1303,7 +1401,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) {
|
|
@@ -1951,15 +2049,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));
|
|
@@ -2197,11 +2301,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
|
|
@@ -2216,9 +2320,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)
|
|
@@ -2351,11 +2461,11 @@ void send_discover (cpp)
|
|
(long)(client -> interval));
|
|
} else
|
|
#endif
|
|
- 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. */
|
|
#if defined(DHCPv6) && defined(DHCP4o6)
|
|
if (dhcpv4_over_dhcpv6) {
|
|
@@ -2639,10 +2749,10 @@ void send_request (cpp)
|
|
log_info ("DHCPREQUEST");
|
|
} else
|
|
#endif
|
|
- 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 defined(DHCPv6) && defined(DHCP4o6)
|
|
if (dhcpv4_over_dhcpv6) {
|
|
@@ -2699,10 +2809,10 @@ void send_decline (cpp)
|
|
log_info ("DHCPDECLINE");
|
|
} else
|
|
#endif
|
|
- 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. */
|
|
#if defined(DHCPv6) && defined(DHCP4o6)
|
|
@@ -2761,10 +2871,10 @@ void send_release (cpp)
|
|
log_info ("DHCPRELEASE");
|
|
} else
|
|
#endif
|
|
- 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 defined(DHCPv6) && defined(DHCP4o6)
|
|
if (dhcpv4_over_dhcpv6) {
|
|
@@ -3041,10 +3151,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,
|
|
@@ -3135,12 +3252,13 @@ void make_discover (client, lease)
|
|
client -> packet.op = BOOTREQUEST;
|
|
client -> packet.htype = client -> interface -> hw_address.hbuf [0];
|
|
/* Assumes hw_address is known, otherwise a random value may result */
|
|
- 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);
|
|
@@ -3152,7 +3270,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));
|
|
@@ -3209,7 +3327,8 @@ void make_request (client, lease)
|
|
client -> packet.op = BOOTREQUEST;
|
|
client -> packet.htype = client -> interface -> hw_address.hbuf [0];
|
|
/* Assumes hw_address is known, otherwise a random value may result */
|
|
- 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. */
|
|
@@ -3241,7 +3360,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));
|
|
@@ -3284,7 +3403,8 @@ void make_decline (client, lease)
|
|
client -> packet.op = BOOTREQUEST;
|
|
client -> packet.htype = client -> interface -> hw_address.hbuf [0];
|
|
/* Assumes hw_address is known, otherwise a random value may result */
|
|
- 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. */
|
|
@@ -3301,9 +3421,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);
|
|
@@ -3346,7 +3467,8 @@ void make_release (client, lease)
|
|
client -> packet.op = BOOTREQUEST;
|
|
client -> packet.htype = client -> interface -> hw_address.hbuf [0];
|
|
/* Assumes hw_address is known, otherwise a random value may result */
|
|
- 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;
|
|
@@ -3358,9 +3480,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);
|
|
@@ -3513,17 +3636,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) ||
|
|
@@ -3573,6 +3692,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)
|
|
@@ -4946,7 +5072,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 34bbd5b..c415c22 100644
|
|
--- a/common/bpf.c
|
|
+++ b/common/bpf.c
|
|
@@ -116,7 +116,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;
|
|
}
|
|
@@ -198,11 +198,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 = NULL;
|
|
#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 */
|
|
@@ -549,7 +582,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/discover.c b/common/discover.c
|
|
index c48d67b..969ee3e 100644
|
|
--- a/common/discover.c
|
|
+++ b/common/discover.c
|
|
@@ -1280,7 +1280,7 @@ discover_interfaces(int state) {
|
|
if_register_send(tmp);
|
|
} else {
|
|
/* get_hw_addr() was called by register. */
|
|
- get_hw_addr(tmp->name, &tmp->hw_address);
|
|
+ get_hw_addr(tmp);
|
|
}
|
|
break;
|
|
#ifdef DHCPv6
|
|
@@ -1293,7 +1293,7 @@ discover_interfaces(int state) {
|
|
so now we have to call it explicitly
|
|
to not leave the hardware address unknown
|
|
(some code expects it cannot be. */
|
|
- get_hw_addr(tmp->name, &tmp->hw_address);
|
|
+ get_hw_addr(tmp);
|
|
} else {
|
|
if_register_linklocal6(tmp);
|
|
}
|
|
diff --git a/common/dlpi.c b/common/dlpi.c
|
|
index 1014e29..3e6a3d3 100644
|
|
--- a/common/dlpi.c
|
|
+++ b/common/dlpi.c
|
|
@@ -1339,7 +1339,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 123790d..943d679 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 ce368c4..7dd9f52 100644
|
|
--- a/common/print.c
|
|
+++ b/common/print.c
|
|
@@ -173,11 +173,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 fa7d6fb..e55309e 100644
|
|
--- a/includes/dhcpd.h
|
|
+++ b/includes/dhcpd.h
|
|
@@ -1345,6 +1345,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.
|
|
*/
|
|
@@ -2583,7 +2584,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);
|
|
char *buf_to_hex (const unsigned char *s, unsigned len,
|
|
const char *file, int line);
|
|
char *format_lease_id(const unsigned char *s, unsigned len, int format,
|
|
diff --git a/server/dhcp.c b/server/dhcp.c
|
|
index c9b3632..effa9b1 100644
|
|
--- a/server/dhcp.c
|
|
+++ b/server/dhcp.c
|
|
@@ -1967,11 +1967,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;
|
|
|
|
@@ -3766,9 +3767,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 75a0e72..6207c31 100644
|
|
--- a/server/dhcpleasequery.c
|
|
+++ b/server/dhcpleasequery.c
|
|
@@ -299,7 +299,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, "
|
|
@@ -409,11 +409,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 6af6b63..a143452 100644
|
|
--- a/server/mdb.c
|
|
+++ b/server/mdb.c
|
|
@@ -618,6 +618,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);
|