mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-26 20:08:15 +00:00
[master] Add support for relayed client-linklayer-address option (RFC 6939)
Merges in rt40334.
This commit is contained in:
parent
cab61f4377
commit
62a9eb918c
6
RELNOTES
6
RELNOTES
@ -181,6 +181,12 @@ by Eric Young (eay@cryptsoft.com).
|
|||||||
to be set at configure time via the environment variable 'AR'.
|
to be set at configure time via the environment variable 'AR'.
|
||||||
[ISC-Bugs #41536]
|
[ISC-Bugs #41536]
|
||||||
|
|
||||||
|
- The server will now match DHCPv6 relayed clients to host declarations
|
||||||
|
which include the "hardware" statement, if the relay connected to the
|
||||||
|
client supplies the client's hardware address via client-linklayer-address
|
||||||
|
option as per RFC 6939.
|
||||||
|
[ISC-Bugs #40334]
|
||||||
|
|
||||||
Changes since 4.3.3b1
|
Changes since 4.3.3b1
|
||||||
|
|
||||||
- None
|
- None
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
DHCPv6 Protocol structures... */
|
DHCPv6 Protocol structures... */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 by Internet Systems Consortium, Inc. ("ISC")
|
* Copyright (c) 2013,2016 by Internet Systems Consortium, Inc. ("ISC")
|
||||||
* Copyright (c) 2006-2009 by Internet Systems Consortium, Inc. ("ISC")
|
* Copyright (c) 2006-2009 by Internet Systems Consortium, Inc. ("ISC")
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
@ -76,6 +76,7 @@
|
|||||||
#define D6O_CLT_TIME 46 /* RFC5007 */
|
#define D6O_CLT_TIME 46 /* RFC5007 */
|
||||||
#define D6O_LQ_RELAY_DATA 47 /* RFC5007 */
|
#define D6O_LQ_RELAY_DATA 47 /* RFC5007 */
|
||||||
#define D6O_LQ_CLIENT_LINK 48 /* RFC5007 */
|
#define D6O_LQ_CLIENT_LINK 48 /* RFC5007 */
|
||||||
|
#define D6O_CLIENT_LINKLAYER_ADDR 79 /* RFC6939 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Status Codes, from RFC 3315 section 24.4, and RFC 3633, 5007.
|
* Status Codes, from RFC 3315 section 24.4, and RFC 3633, 5007.
|
||||||
|
@ -3429,6 +3429,7 @@ int find_hosts_by_option(struct host_decl **, struct packet *,
|
|||||||
struct option_state *, const char *, int);
|
struct option_state *, const char *, int);
|
||||||
int find_host_for_network (struct subnet **, struct host_decl **,
|
int find_host_for_network (struct subnet **, struct host_decl **,
|
||||||
struct iaddr *, struct shared_network *);
|
struct iaddr *, struct shared_network *);
|
||||||
|
|
||||||
void new_address_range (struct parse *, struct iaddr, struct iaddr,
|
void new_address_range (struct parse *, struct iaddr, struct iaddr,
|
||||||
struct subnet *, struct pool *,
|
struct subnet *, struct pool *,
|
||||||
struct lease **);
|
struct lease **);
|
||||||
@ -3750,6 +3751,11 @@ void mark_phosts_unavailable(void);
|
|||||||
void mark_interfaces_unavailable(void);
|
void mark_interfaces_unavailable(void);
|
||||||
void report_jumbo_ranges();
|
void report_jumbo_ranges();
|
||||||
|
|
||||||
|
#if defined(DHCPv6)
|
||||||
|
int find_hosts6(struct host_decl** host, struct packet* packet,
|
||||||
|
const struct data_string* client_id, char* file, int line);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined (BINARY_LEASES)
|
#if defined (BINARY_LEASES)
|
||||||
/* leasechain.c */
|
/* leasechain.c */
|
||||||
int lc_not_empty(struct leasechain *lc);
|
int lc_not_empty(struct leasechain *lc);
|
||||||
|
135
server/dhcpv6.c
135
server/dhcpv6.c
@ -147,8 +147,6 @@ static isc_result_t reply_process_send_prefix(struct reply_state *reply,
|
|||||||
static struct iasubopt *prefix_compare(struct reply_state *reply,
|
static struct iasubopt *prefix_compare(struct reply_state *reply,
|
||||||
struct iasubopt *alpha,
|
struct iasubopt *alpha,
|
||||||
struct iasubopt *beta);
|
struct iasubopt *beta);
|
||||||
static int find_hosts_by_duid_chaddr(struct host_decl **host,
|
|
||||||
const struct data_string *client_id);
|
|
||||||
static void schedule_lease_timeout_reply(struct reply_state *reply);
|
static void schedule_lease_timeout_reply(struct reply_state *reply);
|
||||||
|
|
||||||
static int eval_prefix_mode(int thislen, int preflen, int prefix_mode);
|
static int eval_prefix_mode(int thislen, int preflen, int prefix_mode);
|
||||||
@ -1643,27 +1641,10 @@ lease_to_client(struct data_string *reply_ret,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find a host record that matches from the packet, if any, and is
|
* Find a host record that matches the packet, if any, and is
|
||||||
* valid for the shared network the client is on.
|
* valid for the shared network the client is on.
|
||||||
*/
|
*/
|
||||||
if (find_hosts_by_uid(&reply.host, client_id->data, client_id->len,
|
if (find_hosts6(&reply.host, packet, client_id, MDL)) {
|
||||||
MDL)) {
|
|
||||||
packet->known = 1;
|
|
||||||
seek_shared_host(&reply.host, reply.shared);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((reply.host == NULL) &&
|
|
||||||
find_hosts_by_option(&reply.host, packet, packet->options, MDL)) {
|
|
||||||
packet->known = 1;
|
|
||||||
seek_shared_host(&reply.host, reply.shared);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check for 'hardware' matches last, as some of the synthesis methods
|
|
||||||
* are not considered to be as reliable.
|
|
||||||
*/
|
|
||||||
if ((reply.host == NULL) &&
|
|
||||||
find_hosts_by_duid_chaddr(&reply.host, client_id)) {
|
|
||||||
packet->known = 1;
|
packet->known = 1;
|
||||||
seek_shared_host(&reply.host, reply.shared);
|
seek_shared_host(&reply.host, reply.shared);
|
||||||
}
|
}
|
||||||
@ -5552,24 +5533,7 @@ iterate_over_ia_na(struct data_string *reply_ret,
|
|||||||
* Find the host record that matches from the packet, if any.
|
* Find the host record that matches from the packet, if any.
|
||||||
*/
|
*/
|
||||||
packet_host = NULL;
|
packet_host = NULL;
|
||||||
if (!find_hosts_by_uid(&packet_host,
|
find_hosts6(&packet_host, packet, client_id, MDL);
|
||||||
client_id->data, client_id->len, MDL)) {
|
|
||||||
packet_host = NULL;
|
|
||||||
/*
|
|
||||||
* Note: In general, we don't expect a client to provide
|
|
||||||
* enough information to match by option for these
|
|
||||||
* types of messages, but if we don't have a UID
|
|
||||||
* match we can check anyway.
|
|
||||||
*/
|
|
||||||
if (!find_hosts_by_option(&packet_host,
|
|
||||||
packet, packet->options, MDL)) {
|
|
||||||
packet_host = NULL;
|
|
||||||
|
|
||||||
if (!find_hosts_by_duid_chaddr(&packet_host,
|
|
||||||
client_id))
|
|
||||||
packet_host = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set our reply information.
|
* Set our reply information.
|
||||||
@ -6081,24 +6045,7 @@ iterate_over_ia_pd(struct data_string *reply_ret,
|
|||||||
* Find the host record that matches from the packet, if any.
|
* Find the host record that matches from the packet, if any.
|
||||||
*/
|
*/
|
||||||
packet_host = NULL;
|
packet_host = NULL;
|
||||||
if (!find_hosts_by_uid(&packet_host,
|
find_hosts6(&packet_host, packet, client_id, MDL);
|
||||||
client_id->data, client_id->len, MDL)) {
|
|
||||||
packet_host = NULL;
|
|
||||||
/*
|
|
||||||
* Note: In general, we don't expect a client to provide
|
|
||||||
* enough information to match by option for these
|
|
||||||
* types of messages, but if we don't have a UID
|
|
||||||
* match we can check anyway.
|
|
||||||
*/
|
|
||||||
if (!find_hosts_by_option(&packet_host,
|
|
||||||
packet, packet->options, MDL)) {
|
|
||||||
packet_host = NULL;
|
|
||||||
|
|
||||||
if (!find_hosts_by_duid_chaddr(&packet_host,
|
|
||||||
client_id))
|
|
||||||
packet_host = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Build our option state for reply.
|
* Build our option state for reply.
|
||||||
@ -6922,79 +6869,6 @@ fixed_matches_shared(struct host_decl *host, struct shared_network *shared) {
|
|||||||
return matched;
|
return matched;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* find_host_by_duid_chaddr() synthesizes a DHCPv4-like 'hardware'
|
|
||||||
* parameter from a DHCPv6 supplied DUID (client-identifier option),
|
|
||||||
* and may seek to use client or relay supplied hardware addresses.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
find_hosts_by_duid_chaddr(struct host_decl **host,
|
|
||||||
const struct data_string *client_id) {
|
|
||||||
static int once_htype;
|
|
||||||
int htype, hlen;
|
|
||||||
const unsigned char *chaddr;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The DUID-LL and DUID-LLT must have a 2-byte DUID type and 2-byte
|
|
||||||
* htype.
|
|
||||||
*/
|
|
||||||
if (client_id->len < 4)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The third and fourth octets of the DUID-LL and DUID-LLT
|
|
||||||
* is the hardware type, but in 16 bits.
|
|
||||||
*/
|
|
||||||
htype = getUShort(client_id->data + 2);
|
|
||||||
hlen = 0;
|
|
||||||
chaddr = NULL;
|
|
||||||
|
|
||||||
/* The first two octets of the DUID identify the type. */
|
|
||||||
switch(getUShort(client_id->data)) {
|
|
||||||
case DUID_LLT:
|
|
||||||
if (client_id->len > 8) {
|
|
||||||
hlen = client_id->len - 8;
|
|
||||||
chaddr = client_id->data + 8;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DUID_LL:
|
|
||||||
/*
|
|
||||||
* Note that client_id->len must be greater than or equal
|
|
||||||
* to four to get to this point in the function.
|
|
||||||
*/
|
|
||||||
hlen = client_id->len - 4;
|
|
||||||
chaddr = client_id->data + 4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((hlen == 0) || (hlen > HARDWARE_ADDR_LEN))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* XXX: DHCPv6 gives a 16-bit field for the htype. DHCPv4 gives an
|
|
||||||
* 8-bit field. To change the semantics of the generic 'hardware'
|
|
||||||
* structure, we would have to adjust many DHCPv4 sources (from
|
|
||||||
* interface to DHCPv4 lease code), and we would have to update the
|
|
||||||
* 'hardware' config directive (probably being reverse compatible and
|
|
||||||
* providing a new upgrade/replacement primitive). This is a little
|
|
||||||
* too much to change for now. Hopefully we will revisit this before
|
|
||||||
* hardware types exceeding 8 bits are assigned.
|
|
||||||
*/
|
|
||||||
if ((htype & 0xFF00) && !once_htype) {
|
|
||||||
once_htype = 1;
|
|
||||||
log_error("Attention: At least one client advertises a "
|
|
||||||
"hardware type of %d, which exceeds the software "
|
|
||||||
"limitation of 255.", htype);
|
|
||||||
}
|
|
||||||
|
|
||||||
return find_hosts_by_haddr(host, htype, chaddr, hlen, MDL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
* \brief Constructs a REPLY with status of UseMulticast to a given packet
|
* \brief Constructs a REPLY with status of UseMulticast to a given packet
|
||||||
@ -7305,4 +7179,3 @@ get_first_ia_addr_val (struct packet* packet, int addr_type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif /* DHCPv6 */
|
#endif /* DHCPv6 */
|
||||||
|
|
||||||
|
219
server/mdb6.c
219
server/mdb6.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2007-2015 by Internet Systems Consortium, Inc. ("ISC")
|
* Copyright (C) 2007-2016 by Internet Systems Consortium, Inc. ("ISC")
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@ -2560,4 +2560,221 @@ report_jumbo_ranges() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* \brief Tests that 16-bit hardware type is less than 256
|
||||||
|
*
|
||||||
|
* XXX: DHCPv6 gives a 16-bit field for the htype. DHCPv4 gives an
|
||||||
|
* 8-bit field. To change the semantics of the generic 'hardware'
|
||||||
|
* structure, we would have to adjust many DHCPv4 sources (from
|
||||||
|
* interface to DHCPv4 lease code), and we would have to update the
|
||||||
|
* 'hardware' config directive (probably being reverse compatible and
|
||||||
|
* providing a new upgrade/replacement primitive). This is a little
|
||||||
|
* too much to change for now. Hopefully we will revisit this before
|
||||||
|
* hardware types exceeding 8 bits are assigned.
|
||||||
|
*
|
||||||
|
* Uses a static variable to limit log occurence to once per startup
|
||||||
|
*
|
||||||
|
* \param htype hardware type value to test
|
||||||
|
*
|
||||||
|
* \return returns 0 if the value is too large
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int htype_bounds_check(uint16_t htype) {
|
||||||
|
static int log_once = 0;
|
||||||
|
|
||||||
|
if (htype & 0xFF00) {
|
||||||
|
if (!log_once) {
|
||||||
|
log_error("Attention: At least one client advertises a "
|
||||||
|
"hardware type of %d, which exceeds the software "
|
||||||
|
"limitation of 255.", htype);
|
||||||
|
log_once = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Look for hosts by MAC address if it's available
|
||||||
|
*
|
||||||
|
* Checks the inbound packet against host declarations which specified:
|
||||||
|
*
|
||||||
|
* "hardware ethernet <MAC>;"
|
||||||
|
*
|
||||||
|
* For directly connected clients, the function will use the MAC address
|
||||||
|
* contained in packet:haddr if it's populated. \TODO - While the logic is in
|
||||||
|
* place for this search, the socket layer does not yet populate packet:haddr,
|
||||||
|
* this is to be done under rt41523.
|
||||||
|
*
|
||||||
|
* For relayed clients, the function will use the MAC address from the
|
||||||
|
* client-linklayer-address option if it has been supplied by the relay
|
||||||
|
* directly connected to the client.
|
||||||
|
*
|
||||||
|
* \param hp[out] - pointer to storage for the host delcaration if found
|
||||||
|
* \param packet - received packet
|
||||||
|
* \param opt_state - option state to search
|
||||||
|
* \param file - source file
|
||||||
|
* \param line - line number
|
||||||
|
*
|
||||||
|
* \return non-zero if a matching host was found, zero otherwise
|
||||||
|
*/
|
||||||
|
int find_hosts_by_haddr6(struct host_decl **hp,
|
||||||
|
struct packet *packet,
|
||||||
|
struct option_state *opt_state,
|
||||||
|
const char *file, int line) {
|
||||||
|
int found = 0;
|
||||||
|
int htype;
|
||||||
|
int hlen;
|
||||||
|
|
||||||
|
/* For directly connected clients, use packet:haddr if populated */
|
||||||
|
if (packet->dhcpv6_container_packet == NULL) {
|
||||||
|
if (packet->haddr) {
|
||||||
|
htype = packet->haddr->hbuf[0];
|
||||||
|
hlen = packet->haddr->hlen - 1,
|
||||||
|
log_debug("find_hosts_by_haddr6: using packet->haddr,"
|
||||||
|
" type: %d, len: %d", htype, hlen);
|
||||||
|
found = find_hosts_by_haddr (hp, htype,
|
||||||
|
&packet->haddr->hbuf[1],
|
||||||
|
hlen, MDL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* The first container packet is the from the relay directly
|
||||||
|
* connected to the client. Per RFC 6939, that is only relay
|
||||||
|
* that may supply the client linklayer address option. */
|
||||||
|
struct packet *relay_packet = packet->dhcpv6_container_packet;
|
||||||
|
struct option_state *relay_state = relay_packet->options;
|
||||||
|
struct data_string rel_addr;
|
||||||
|
struct option_cache *oc;
|
||||||
|
|
||||||
|
/* Look for the option in the first relay packet */
|
||||||
|
oc = lookup_option(&dhcpv6_universe, relay_state,
|
||||||
|
D6O_CLIENT_LINKLAYER_ADDR);
|
||||||
|
if (!oc) {
|
||||||
|
/* Not there, so bail */
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The option is present, fetch the address data */
|
||||||
|
memset(&rel_addr, 0, sizeof(rel_addr));
|
||||||
|
if (!evaluate_option_cache(&rel_addr, relay_packet, NULL, NULL,
|
||||||
|
relay_state, NULL, &global_scope,
|
||||||
|
oc, MDL)) {
|
||||||
|
log_error("find_hosts_by_add6:"
|
||||||
|
"Error evaluating option cache");
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The relay address data should be:
|
||||||
|
* byte 0 - 1 = hardware type
|
||||||
|
* bytes 2 - hlen = hardware address
|
||||||
|
* where hlen ( hardware address len) is option data len - 2 */
|
||||||
|
hlen = rel_addr.len - 2;
|
||||||
|
if (hlen > 0 && hlen <= HARDWARE_ADDR_LEN) {
|
||||||
|
htype = getUShort(rel_addr.data);
|
||||||
|
if (htype_bounds_check(htype)) {
|
||||||
|
/* Looks valid, let's search with it */
|
||||||
|
log_debug("find_hosts_by_haddr6:"
|
||||||
|
"using relayed haddr"
|
||||||
|
" type: %d, len: %d", htype, hlen);
|
||||||
|
found = find_hosts_by_haddr (hp, htype,
|
||||||
|
&rel_addr.data[2],
|
||||||
|
hlen, MDL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data_string_forget(&rel_addr, MDL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (found);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find_host_by_duid_chaddr() synthesizes a DHCPv4-like 'hardware'
|
||||||
|
* parameter from a DHCPv6 supplied DUID (client-identifier option),
|
||||||
|
* and may seek to use client or relay supplied hardware addresses.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
find_hosts_by_duid_chaddr(struct host_decl **host,
|
||||||
|
const struct data_string *client_id) {
|
||||||
|
int htype, hlen;
|
||||||
|
const unsigned char *chaddr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The DUID-LL and DUID-LLT must have a 2-byte DUID type and 2-byte
|
||||||
|
* htype.
|
||||||
|
*/
|
||||||
|
if (client_id->len < 4)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The third and fourth octets of the DUID-LL and DUID-LLT
|
||||||
|
* is the hardware type, but in 16 bits.
|
||||||
|
*/
|
||||||
|
htype = getUShort(client_id->data + 2);
|
||||||
|
hlen = 0;
|
||||||
|
chaddr = NULL;
|
||||||
|
|
||||||
|
/* The first two octets of the DUID identify the type. */
|
||||||
|
switch(getUShort(client_id->data)) {
|
||||||
|
case DUID_LLT:
|
||||||
|
if (client_id->len > 8) {
|
||||||
|
hlen = client_id->len - 8;
|
||||||
|
chaddr = client_id->data + 8;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DUID_LL:
|
||||||
|
/*
|
||||||
|
* Note that client_id->len must be greater than or equal
|
||||||
|
* to four to get to this point in the function.
|
||||||
|
*/
|
||||||
|
hlen = client_id->len - 4;
|
||||||
|
chaddr = client_id->data + 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((hlen == 0) || (hlen > HARDWARE_ADDR_LEN) ||
|
||||||
|
!htype_bounds_check(htype)) {
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return find_hosts_by_haddr(host, htype, chaddr, hlen, MDL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* \brief Finds a host record that matches the packet, if any
|
||||||
|
*
|
||||||
|
* This function centralizes the logic for matching v6 client
|
||||||
|
* packets to host declarations. We check in the following order
|
||||||
|
* for matches with:
|
||||||
|
*
|
||||||
|
* 1. client_id if specified
|
||||||
|
* 2. MAC address when explicitly available
|
||||||
|
* 3. packet option
|
||||||
|
* 4. synthesized hardware address - this is done last as some
|
||||||
|
* synthesis methods are not consided to be reliable
|
||||||
|
*
|
||||||
|
* \param[out] host - pointer to storage for the located host
|
||||||
|
* \param packet - inbound client packet
|
||||||
|
* \param client_id - client identifier (if one)
|
||||||
|
* \param file - source file
|
||||||
|
* \param line - source file line number
|
||||||
|
* \return non-zero if a host is found, zero otherwise
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
find_hosts6(struct host_decl** host, struct packet* packet,
|
||||||
|
const struct data_string* client_id, char* file, int line) {
|
||||||
|
return (find_hosts_by_uid(host, client_id->data, client_id->len, MDL)
|
||||||
|
|| find_hosts_by_haddr6(host, packet, packet->options, MDL)
|
||||||
|
|| find_hosts_by_option(host, packet, packet->options, MDL)
|
||||||
|
|| find_hosts_by_duid_chaddr(host, client_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* unittest moved to server/tests/mdb6_unittest.c */
|
/* unittest moved to server/tests/mdb6_unittest.c */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user