version 1.1.1.2, 2014/06/15 16:31:38
|
version 1.1.1.3, 2016/11/02 09:57:01
|
Line 1
|
Line 1
|
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley | /* dnsmasq is Copyright (c) 2000-2016 Simon Kelley |
|
|
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
Line 130 static int dhcp6_maybe_relay(struct state *state, void
|
Line 130 static int dhcp6_maybe_relay(struct state *state, void
|
MAC address from the local ND cache. */ |
MAC address from the local ND cache. */ |
|
|
if (!state->link_address) |
if (!state->link_address) |
get_client_mac(client_addr, state->interface, state->mac, &state->mac_len, &state->mac_type); | get_client_mac(client_addr, state->interface, state->mac, &state->mac_len, &state->mac_type, now); |
else |
else |
{ |
{ |
struct dhcp_context *c; |
struct dhcp_context *c; |
Line 313 static int dhcp6_no_relay(struct state *state, int msg
|
Line 313 static int dhcp6_no_relay(struct state *state, int msg
|
else if (msg_type != DHCP6IREQ) |
else if (msg_type != DHCP6IREQ) |
return 0; |
return 0; |
|
|
/* server-id must match except for SOLICIT and CONFIRM messages */ | /* server-id must match except for SOLICIT, CONFIRM and REBIND messages */ |
if (msg_type != DHCP6SOLICIT && msg_type != DHCP6CONFIRM && msg_type != DHCP6IREQ && | if (msg_type != DHCP6SOLICIT && msg_type != DHCP6CONFIRM && msg_type != DHCP6IREQ && msg_type != DHCP6REBIND && |
(!(opt = opt6_find(state->packet_options, state->end, OPTION6_SERVER_ID, 1)) || |
(!(opt = opt6_find(state->packet_options, state->end, OPTION6_SERVER_ID, 1)) || |
opt6_len(opt) != daemon->duid_len || |
opt6_len(opt) != daemon->duid_len || |
memcmp(opt6_ptr(opt, 0), daemon->duid, daemon->duid_len) != 0)) |
memcmp(opt6_ptr(opt, 0), daemon->duid, daemon->duid_len) != 0)) |
Line 328 static int dhcp6_no_relay(struct state *state, int msg
|
Line 328 static int dhcp6_no_relay(struct state *state, int msg
|
(msg_type == DHCP6REQUEST || msg_type == DHCP6RENEW || msg_type == DHCP6RELEASE || msg_type == DHCP6DECLINE)) |
(msg_type == DHCP6REQUEST || msg_type == DHCP6RENEW || msg_type == DHCP6RELEASE || msg_type == DHCP6DECLINE)) |
|
|
{ |
{ |
|
*outmsgtypep = DHCP6REPLY; |
o1 = new_opt6(OPTION6_STATUS_CODE); |
o1 = new_opt6(OPTION6_STATUS_CODE); |
put_opt6_short(DHCP6USEMULTI); |
put_opt6_short(DHCP6USEMULTI); |
put_opt6_string("Use multicast"); |
put_opt6_string("Use multicast"); |
Line 690 static int dhcp6_no_relay(struct state *state, int msg
|
Line 691 static int dhcp6_no_relay(struct state *state, int msg
|
#endif |
#endif |
|
|
o = build_ia(state, &t1cntr); |
o = build_ia(state, &t1cntr); |
|
if (address_assigned) |
|
address_assigned = 2; |
|
|
for (ia_counter = 0; ia_option; ia_counter++, ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24)) |
for (ia_counter = 0; ia_option; ia_counter++, ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24)) |
{ |
{ |
Line 780 static int dhcp6_no_relay(struct state *state, int msg
|
Line 783 static int dhcp6_no_relay(struct state *state, int msg
|
address_assigned = 1; |
address_assigned = 1; |
} |
} |
|
|
|
if (address_assigned != 1) |
|
{ |
|
/* If the server will not assign any addresses to any IAs in a |
|
subsequent Request from the client, the server MUST send an Advertise |
|
message to the client that doesn't include any IA options. */ |
|
if (!state->lease_allocate) |
|
{ |
|
save_counter(o); |
|
continue; |
|
} |
|
|
|
/* If the server cannot assign any addresses to an IA in the message |
|
from the client, the server MUST include the IA in the Reply message |
|
with no addresses in the IA and a Status Code option in the IA |
|
containing status code NoAddrsAvail. */ |
|
o1 = new_opt6(OPTION6_STATUS_CODE); |
|
put_opt6_short(DHCP6NOADDRS); |
|
put_opt6_string(_("address unavailable")); |
|
end_opt6(o1); |
|
} |
|
|
end_ia(t1cntr, min_time, 0); |
end_ia(t1cntr, min_time, 0); |
end_opt6(o); |
end_opt6(o); |
} |
} |
Line 805 static int dhcp6_no_relay(struct state *state, int msg
|
Line 829 static int dhcp6_no_relay(struct state *state, int msg
|
put_opt6_short(DHCP6NOADDRS); |
put_opt6_short(DHCP6NOADDRS); |
put_opt6_string(_("no addresses available")); |
put_opt6_string(_("no addresses available")); |
end_opt6(o1); |
end_opt6(o1); |
log6_packet(state, "DHCPADVERTISE", NULL, _("no addresses available")); | |
| /* Some clients will ask repeatedly when we're not giving |
| out addresses because we're in stateless mode. Avoid spamming |
| the log in that case. */ |
| for (c = state->context; c; c = c->current) |
| if (!(c->flags & CONTEXT_RA_STATELESS)) |
| { |
| log6_packet(state, state->lease_allocate ? "DHCPREPLY" : "DHCPADVERTISE", NULL, _("no addresses available")); |
| break; |
| } |
} |
} |
|
|
break; |
break; |
Line 861 static int dhcp6_no_relay(struct state *state, int msg
|
Line 894 static int dhcp6_no_relay(struct state *state, int msg
|
{ |
{ |
/* Static range, not configured. */ |
/* Static range, not configured. */ |
o1 = new_opt6(OPTION6_STATUS_CODE); |
o1 = new_opt6(OPTION6_STATUS_CODE); |
put_opt6_short(DHCP6UNSPEC); | put_opt6_short(DHCP6NOADDRS); |
put_opt6_string(_("address unavailable")); |
put_opt6_string(_("address unavailable")); |
end_opt6(o1); |
end_opt6(o1); |
} |
} |
Line 1014 static int dhcp6_no_relay(struct state *state, int msg
|
Line 1047 static int dhcp6_no_relay(struct state *state, int msg
|
{ |
{ |
preferred_time = valid_time = 0; |
preferred_time = valid_time = 0; |
message = _("address invalid"); |
message = _("address invalid"); |
} | } |
|
|
if (message) | if (message && (message != state->hostname)) |
log6_packet(state, "DHCPREPLY", req_addr, message); |
log6_packet(state, "DHCPREPLY", req_addr, message); |
else |
else |
log6_quiet(state, "DHCPREPLY", req_addr, message); |
log6_quiet(state, "DHCPREPLY", req_addr, message); |
Line 1039 static int dhcp6_no_relay(struct state *state, int msg
|
Line 1072 static int dhcp6_no_relay(struct state *state, int msg
|
|
|
case DHCP6CONFIRM: |
case DHCP6CONFIRM: |
{ |
{ |
|
int good_addr = 0; |
|
|
/* set reply message type */ |
/* set reply message type */ |
*outmsgtypep = DHCP6REPLY; |
*outmsgtypep = DHCP6REPLY; |
|
|
Line 1054 static int dhcp6_no_relay(struct state *state, int msg
|
Line 1089 static int dhcp6_no_relay(struct state *state, int msg
|
{ |
{ |
struct in6_addr *req_addr = opt6_ptr(ia_option, 0); |
struct in6_addr *req_addr = opt6_ptr(ia_option, 0); |
|
|
if (!address6_available(state->context, req_addr, tagif, 1)) | if (!address6_valid(state->context, req_addr, tagif, 1)) |
{ |
{ |
o1 = new_opt6(OPTION6_STATUS_CODE); |
o1 = new_opt6(OPTION6_STATUS_CODE); |
put_opt6_short(DHCP6NOTONLINK); |
put_opt6_short(DHCP6NOTONLINK); |
Line 1063 static int dhcp6_no_relay(struct state *state, int msg
|
Line 1098 static int dhcp6_no_relay(struct state *state, int msg
|
return 1; |
return 1; |
} |
} |
|
|
|
good_addr = 1; |
log6_quiet(state, "DHCPREPLY", req_addr, state->hostname); |
log6_quiet(state, "DHCPREPLY", req_addr, state->hostname); |
} |
} |
} |
} |
|
|
|
/* No addresses, no reply: RFC 3315 18.2.2 */ |
|
if (!good_addr) |
|
return 0; |
|
|
o1 = new_opt6(OPTION6_STATUS_CODE); |
o1 = new_opt6(OPTION6_STATUS_CODE); |
put_opt6_short(DHCP6SUCCESS ); |
put_opt6_short(DHCP6SUCCESS ); |
Line 1232 static int dhcp6_no_relay(struct state *state, int msg
|
Line 1272 static int dhcp6_no_relay(struct state *state, int msg
|
} |
} |
|
|
} |
} |
|
|
|
/* We must anwser with 'success' in global section anyway */ |
|
o1 = new_opt6(OPTION6_STATUS_CODE); |
|
put_opt6_short(DHCP6SUCCESS); |
|
put_opt6_string(_("success")); |
|
end_opt6(o1); |
break; |
break; |
} |
} |
|
|
Line 1274 static struct dhcp_netid *add_options(struct state *st
|
Line 1320 static struct dhcp_netid *add_options(struct state *st
|
|
|
if (opt_cfg->opt == OPTION6_REFRESH_TIME) |
if (opt_cfg->opt == OPTION6_REFRESH_TIME) |
done_refresh = 1; |
done_refresh = 1; |
|
|
|
if (opt_cfg->opt == OPTION6_DNS_SERVER) |
|
done_dns = 1; |
|
|
if (opt_cfg->flags & DHOPT_ADDR6) |
if (opt_cfg->flags & DHOPT_ADDR6) |
{ |
{ |
int len, j; |
int len, j; |
struct in6_addr *a; |
struct in6_addr *a; |
|
|
if (opt_cfg->opt == OPTION6_DNS_SERVER) |
|
done_dns = 1; |
|
|
|
for (a = (struct in6_addr *)opt_cfg->val, len = opt_cfg->len, j = 0; |
for (a = (struct in6_addr *)opt_cfg->val, len = opt_cfg->len, j = 0; |
j < opt_cfg->len; j += IN6ADDRSZ, a++) |
j < opt_cfg->len; j += IN6ADDRSZ, a++) |
if ((IN6_IS_ADDR_ULA_ZERO(a) && IN6_IS_ADDR_UNSPECIFIED(state->ula_addr)) || |
if ((IN6_IS_ADDR_ULA_ZERO(a) && IN6_IS_ADDR_UNSPECIFIED(state->ula_addr)) || |
Line 2008 static unsigned int opt6_uint(unsigned char *opt, int
|
Line 2054 static unsigned int opt6_uint(unsigned char *opt, int
|
return ret; |
return ret; |
} |
} |
|
|
void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer_address, u32 scope_id) | void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, |
| struct in6_addr *peer_address, u32 scope_id, time_t now) |
{ |
{ |
/* ->local is same value for all relays on ->current chain */ |
/* ->local is same value for all relays on ->current chain */ |
|
|
Line 2022 void relay_upstream6(struct dhcp_relay *relay, ssize_t
|
Line 2069 void relay_upstream6(struct dhcp_relay *relay, ssize_t
|
unsigned char mac[DHCP_CHADDR_MAX]; |
unsigned char mac[DHCP_CHADDR_MAX]; |
|
|
inet_pton(AF_INET6, ALL_SERVERS, &multicast); |
inet_pton(AF_INET6, ALL_SERVERS, &multicast); |
get_client_mac(peer_address, scope_id, mac, &maclen, &mactype); | get_client_mac(peer_address, scope_id, mac, &maclen, &mactype, now); |
|
|
/* source address == relay address */ |
/* source address == relay address */ |
from.addr.addr6 = relay->local.addr.addr6; |
from.addr.addr6 = relay->local.addr.addr6; |