summaryrefslogtreecommitdiff
path: root/server/dhcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/dhcp.c')
-rw-r--r--server/dhcp.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/server/dhcp.c b/server/dhcp.c
index 58072c93..03815948 100644
--- a/server/dhcp.c
+++ b/server/dhcp.c
@@ -4360,6 +4360,7 @@ int locate_network (packet)
struct data_string data;
struct subnet *subnet = (struct subnet *)0;
struct option_cache *oc;
+ int sso = 0;
/* See if there's a Relay Agent Link Selection Option, or a
* Subnet Selection Option. The Link-Select and Subnet-Select
@@ -4370,10 +4371,44 @@ int locate_network (packet)
RAI_LINK_SELECT)) == NULL)
oc = lookup_option(&dhcp_universe, packet->options,
DHO_SUBNET_SELECTION);
+ if (oc)
+ sso = 1;
+
+#ifdef DHCPv6
+ /* See if there is a Relay Agent CRA6ADDR Option. */
+ if (!sso)
+ oc = lookup_option(&agent_universe, packet->options,
+ RAI_CRA6ADDR);
+ if (!sso && oc) {
+ memset (&data, 0, sizeof data);
+ if (!evaluate_option_cache (&data, packet, (struct lease *)0,
+ (struct client_state *)0,
+ packet -> options,
+ (struct option_state *)0,
+ &global_scope, oc, MDL)) {
+ return 0;
+ }
+ if (data.len != 16) {
+ return 0;
+ }
+ ia.len = 16;
+ memcpy (ia.iabuf, data.data, 16);
+ data_string_forget (&data, MDL);
+
+ /* Get the subnet of this IPv6 address. */
+ if (find_subnet (&subnet, ia, MDL)) {
+ shared_network_reference (&packet -> shared_network,
+ subnet -> shared_network,
+ MDL);
+ subnet_dereference (&subnet, MDL);
+ return 1;
+ }
+ }
+#endif
/* If there's no SSO and no giaddr, then use the shared_network
from the interface, if there is one. If not, fail. */
- if (!oc && !packet -> raw -> giaddr.s_addr) {
+ if (!sso && !packet -> raw -> giaddr.s_addr) {
if (packet -> interface -> shared_network) {
shared_network_reference
(&packet -> shared_network,
@@ -4386,7 +4421,7 @@ int locate_network (packet)
/* If there's an option indicating link connection, and it's valid,
* use it to figure out the subnet. If it's not valid, fail.
*/
- if (oc) {
+ if (sso) {
memset (&data, 0, sizeof data);
if (!evaluate_option_cache (&data, packet, (struct lease *)0,
(struct client_state *)0,