Commit a2a0f98c authored by Francis Dupont's avatar Francis Dupont

Added local-address6

parent f1208e79
......@@ -296,6 +296,14 @@ dhcp-users@lists.isc.org.
[ISC-Bugs #34097]
[ISC-Bugs #41054]
- Added to the server (-6) a new statement, local-address6, which specifies
the source address of packets sent by the server. An additional flag,
bind-local-address6, disabled by default makes the service socket to
be bound to local-address6. Note as for local-address this does not
work with direct client: a relay has to forward packets to the server
using the local-address6 destination.
[ISC-Bugs #46084]
Changes since 4.3.6 (Bugs):
- Corrected an issue where the server would return a client's previously
......
......@@ -55,6 +55,14 @@ struct in_addr limited_broadcast;
int local_family = AF_INET;
struct in_addr local_address;
#ifdef DHCPv6
/*
* Another clear abuse of the fact that undefined IP addresses are all zeroes.
*/
struct in6_addr local_address6;
int bind_local_address6 = 0;
#endif /* DHCPv6 */
void (*bootp_packet_handler) (struct interface_info *,
struct dhcp_packet *, unsigned,
unsigned int,
......
......@@ -157,10 +157,19 @@ if_register_socket(struct interface_info *info, int family,
addr6 = (struct sockaddr_in6 *)&name;
addr6->sin6_family = AF_INET6;
addr6->sin6_port = local_port;
/* A server feature */
if (bind_local_address6) {
memcpy(&addr6->sin6_addr,
&local_address6,
sizeof(addr6->sin6_addr));
}
/* A client feature */
if (linklocal6) {
memcpy(&addr6->sin6_addr,
linklocal6,
sizeof(addr6->sin6_addr));
}
if (IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr)) {
addr6->sin6_scope_id = if_nametoindex(info->name);
}
#ifdef HAVE_SA_LEN
......@@ -497,8 +506,21 @@ if_register6(struct interface_info *info, int do_multicast) {
* create a socket, this is just a sanity check.
*/
log_fatal("Impossible condition at %s:%d", MDL);
} else if (bind_local_address6) {
char addr6_str[INET6_ADDRSTRLEN];
if (inet_ntop(AF_INET6,
&local_address6,
addr6_str,
sizeof(addr6_str)) == NULL) {
log_fatal("inet_ntop: unable to convert "
"local-address6");
}
log_info("Bound to [%s]:%d",
addr6_str,
(int) ntohs(local_port));
} else {
log_info("Bound to *:%d", ntohs(local_port));
log_info("Bound to *:%d", (int) ntohs(local_port));
}
}
......@@ -828,6 +850,7 @@ ssize_t send_packet6(struct interface_info *interface,
cmsg->cmsg_len = CMSG_LEN(sizeof(*pktinfo));
pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
memset(pktinfo, 0, sizeof(*pktinfo));
pktinfo->ipi6_addr = local_address6;
pktinfo->ipi6_ifindex = ifindex;
result = sendmsg(interface->wfdesc, &m, 0);
......
......@@ -810,6 +810,8 @@ struct lease_state {
#define SV_DDNS_GUARD_ID_MUST_MATCH 93
#define SV_DDNS_OTHER_GUARD_IS_DYNAMIC 94
#define SV_RELEASE_ON_ROAM 95
#define SV_LOCAL_ADDRESS6 96
#define SV_BIND_LOCAL_ADDRESS6 97
#if !defined (DEFAULT_PING_TIMEOUT)
# define DEFAULT_PING_TIMEOUT 1
......@@ -2826,6 +2828,8 @@ void interface_trace_setup (void);
extern struct in_addr limited_broadcast;
extern int local_family;
extern struct in_addr local_address;
extern struct in6_addr local_address6;
extern int bind_local_address6;
extern u_int16_t local_port;
extern u_int16_t remote_port;
......
......@@ -1150,6 +1150,29 @@ void postconf_initialization (int quiet)
data_string_forget(&db, MDL);
path_dhcpd_pid = s;
}
oc = lookup_option(&server_universe, options,
SV_LOCAL_ADDRESS6);
if (oc &&
evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
&global_scope, oc, MDL)) {
if (db.len == 16) {
memcpy(&local_address6, db.data, 16);
} else
log_fatal("invalid local address "
"data length");
data_string_forget(&db, MDL);
}
oc = lookup_option(&server_universe, options,
SV_BIND_LOCAL_ADDRESS6);
if (oc &&
evaluate_boolean_option_cache(NULL, NULL, NULL,
NULL, options, NULL,
&global_scope, oc, MDL)) {
bind_local_address6 = 1;
}
}
#endif /* DHCPv6 */
......
......@@ -2744,6 +2744,29 @@ time.
.RE
.PP
The
.I local-address6
and
.I bind-local-address6
statements
.RS 0.25i
.PP
.B local-address6 \fIaddress\fB;\fR
.PP
.B bind-local-address6 \fIflag\fB;\fR
.PP
The \fIlocal-address6\fR statement causes the DHCP server to send IPv6
packets as originating from the specified IPv6 \fIaddress\fR, rather than
leaving the kernel to fill in the source address field.
.PP
When \fIbind-local-address6\fR is present and has a value of true or on,
service sockets are bound to \fIaddress\fR too.
.PP
By default \fIaddress\fR is the undefined address and the
\fIbind-local-address6\fR is disabled, both may only be set at the global
scope.
.RE
.PP
The
.I log-facility
statement
.RS 0.25i
......
......@@ -288,6 +288,8 @@ static struct option server_options[] = {
{ "ddns-guard-id-must-match", "f", &server_universe, SV_DDNS_GUARD_ID_MUST_MATCH, 1 },
{ "ddns-other-guard-is-dynamic", "f", &server_universe, SV_DDNS_OTHER_GUARD_IS_DYNAMIC, 1 },
{ "release-on-roam", "f", &server_universe, SV_RELEASE_ON_ROAM, 1 },
{ "local-address6", "6", &server_universe, SV_LOCAL_ADDRESS6, 1 },
{ "bind-local-address6", "f", &server_universe, SV_BIND_LOCAL_ADDRESS6, 1 },
{ NULL, NULL, NULL, 0, 0 }
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment