1116 lines
37 KiB
Diff
1116 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
|
||
|
|
||
|
|
||
|
Index: client/dhclient.c
|
||
|
===================================================================
|
||
|
--- client/dhclient.c.orig
|
||
|
+++ client/dhclient.c
|
||
|
@@ -76,6 +76,40 @@ int decline_wait_time = 10; /* Default t
|
||
|
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-2021 Internet Systems Consortium.";
|
||
|
static const char arr [] = "All rights reserved.";
|
||
|
@@ -885,6 +919,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
|
||
|
@@ -899,19 +953,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))) {
|
||
|
@@ -922,6 +999,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)
|
||
|
@@ -1411,15 +1502,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 &&
|
||
|
@@ -1432,9 +1530,10 @@ void dhcpack (packet)
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
- log_info ("DHCPACK of %s from %s",
|
||
|
+ log_info ("DHCPACK of %s from %s (xid=0x%x)",
|
||
|
inet_ntoa(packet->raw->yiaddr),
|
||
|
- piaddr (packet->client_addr));
|
||
|
+ piaddr (packet->client_addr),
|
||
|
+ client -> xid);
|
||
|
|
||
|
lease = packet_to_lease (packet, client);
|
||
|
if (!lease) {
|
||
|
@@ -2101,15 +2200,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 of %s from %s", name,
|
||
|
@@ -2350,11 +2455,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
|
||
|
@@ -2369,9 +2474,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)
|
||
|
@@ -2504,11 +2615,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) {
|
||
|
@@ -2901,10 +3012,12 @@ void send_request (cpp)
|
||
|
}
|
||
|
|
||
|
strncpy(rip_buf, rip_str, sizeof(rip_buf)-1);
|
||
|
- log_info ("DHCPREQUEST for %s on %s to %s port %d", rip_buf,
|
||
|
+ log_info ("DHCPREQUEST for %s on %s to %s port %d (xid=0x%x)", rip_buf,
|
||
|
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) {
|
||
|
@@ -2961,11 +3074,11 @@ void send_decline (cpp)
|
||
|
log_info ("DHCPDECLINE");
|
||
|
} else
|
||
|
#endif
|
||
|
- log_info ("DHCPDECLINE of %s on %s to %s port %d",
|
||
|
+ log_info ("DHCPDECLINE of %s on %s to %s port %d (xid=0x%x)",
|
||
|
piaddr(client->requested_address),
|
||
|
(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)
|
||
|
@@ -3024,11 +3137,11 @@ void send_release (cpp)
|
||
|
log_info ("DHCPRELEASE");
|
||
|
} else
|
||
|
#endif
|
||
|
- log_info ("DHCPRELEASE of %s on %s to %s port %d",
|
||
|
+ log_info ("DHCPRELEASE of %s on %s to %s port %d (xid=0x%x)",
|
||
|
piaddr(client->active->address),
|
||
|
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) {
|
||
|
@@ -3305,10 +3418,17 @@ make_client_options(struct client_state
|
||
|
* 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,
|
||
|
@@ -3399,12 +3519,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);
|
||
|
@@ -3416,7 +3537,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));
|
||
|
@@ -3473,7 +3594,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. */
|
||
|
@@ -3505,7 +3627,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));
|
||
|
@@ -3548,7 +3670,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. */
|
||
|
@@ -3565,9 +3688,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);
|
||
|
@@ -3610,7 +3734,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;
|
||
|
@@ -3622,9 +3747,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);
|
||
|
@@ -3777,17 +3903,13 @@ write_options(struct client_state *clien
|
||
|
* 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) ||
|
||
|
@@ -3837,6 +3959,13 @@ form_duid(struct data_string *duid, cons
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+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)
|
||
|
@@ -5276,7 +5405,8 @@ client_dns_update(struct client_state *c
|
||
|
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,
|
||
|
Index: common/bpf.c
|
||
|
===================================================================
|
||
|
--- common/bpf.c.orig
|
||
|
+++ 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;
|
||
|
}
|
||
|
@@ -237,11 +237,44 @@ int dhcp_bpf_relay_filter_len =
|
||
|
sizeof dhcp_bpf_relay_filter / sizeof (struct bpf_insn);
|
||
|
#endif
|
||
|
|
||
|
+/* 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 */
|
||
|
@@ -600,7 +633,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;
|
||
|
Index: common/discover.c
|
||
|
===================================================================
|
||
|
--- common/discover.c.orig
|
||
|
+++ common/discover.c
|
||
|
@@ -899,7 +899,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
|
||
|
@@ -912,7 +912,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);
|
||
|
}
|
||
|
Index: common/dlpi.c
|
||
|
===================================================================
|
||
|
--- common/dlpi.c.orig
|
||
|
+++ common/dlpi.c
|
||
|
@@ -1343,7 +1343,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;
|
||
|
Index: common/lpf.c
|
||
|
===================================================================
|
||
|
--- common/lpf.c.orig
|
||
|
+++ common/lpf.c
|
||
|
@@ -45,12 +45,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;
|
||
|
@@ -78,10 +88,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) {
|
||
|
@@ -105,6 +130,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 ||
|
||
|
@@ -120,8 +146,6 @@ int if_register_lpf (info)
|
||
|
|
||
|
}
|
||
|
|
||
|
- get_hw_addr(info->name, &info->hw_address);
|
||
|
-
|
||
|
return sock;
|
||
|
}
|
||
|
#endif /* USE_LPF_SEND || USE_LPF_RECEIVE */
|
||
|
@@ -176,6 +200,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(RELAY_PORT)
|
||
|
extern struct sock_filter dhcp_bpf_relay_filter [];
|
||
|
@@ -188,6 +214,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)
|
||
|
@@ -209,12 +237,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)
|
||
|
@@ -291,6 +321,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;
|
||
|
@@ -330,6 +392,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;
|
||
|
@@ -350,6 +460,10 @@ ssize_t send_packet (interface, packet,
|
||
|
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;
|
||
|
|
||
|
@@ -454,7 +568,15 @@ ssize_t receive_packet (interface, buf,
|
||
|
|
||
|
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
|
||
|
@@ -522,33 +644,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
|
||
|
@@ -556,18 +689,37 @@ get_hw_addr(const char *name, struct har
|
||
|
#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
|
||
|
Index: common/print.c
|
||
|
===================================================================
|
||
|
--- common/print.c.orig
|
||
|
+++ 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;
|
||
|
Index: common/socket.c
|
||
|
===================================================================
|
||
|
--- common/socket.c.orig
|
||
|
+++ common/socket.c
|
||
|
@@ -358,7 +358,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. */
|
||
|
@@ -421,7 +421,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",
|
||
|
@@ -577,7 +577,7 @@ if_register6(struct interface_info *info
|
||
|
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) {
|
||
|
@@ -633,7 +633,7 @@ if_register_linklocal6(struct interface_
|
||
|
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) {
|
||
|
@@ -1246,7 +1246,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;
|
||
|
Index: includes/dhcpd.h
|
||
|
===================================================================
|
||
|
--- includes/dhcpd.h.orig
|
||
|
+++ includes/dhcpd.h
|
||
|
@@ -1372,6 +1372,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.
|
||
|
*/
|
||
|
@@ -2641,7 +2642,7 @@ void print_dns_status (int, struct dhcp_
|
||
|
#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,
|
||
|
Index: server/dhcp.c
|
||
|
===================================================================
|
||
|
--- server/dhcp.c.orig
|
||
|
+++ server/dhcp.c
|
||
|
@@ -2035,11 +2035,12 @@ void echo_client_id(packet, lease, in_op
|
||
|
|
||
|
/* 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;
|
||
|
|
||
|
@@ -3948,9 +3949,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
|
||
|
Index: server/dhcpleasequery.c
|
||
|
===================================================================
|
||
|
--- server/dhcpleasequery.c.orig
|
||
|
+++ server/dhcpleasequery.c
|
||
|
@@ -302,7 +302,7 @@ dhcpleasequery(struct packet *packet, in
|
||
|
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, "
|
||
|
@@ -412,11 +412,13 @@ dhcpleasequery(struct packet *packet, in
|
||
|
* 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.
|
||
|
Index: server/mdb.c
|
||
|
===================================================================
|
||
|
--- server/mdb.c.orig
|
||
|
+++ server/mdb.c
|
||
|
@@ -640,6 +640,9 @@ int find_hosts_by_haddr (struct host_dec
|
||
|
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);
|