2014-07-10 17:01:31 +00:00
|
|
|
diff -up dhcp-4.3.1b1/server/dhcpv6.c.UseMulticast dhcp-4.3.1b1/server/dhcpv6.c
|
|
|
|
--- dhcp-4.3.1b1/server/dhcpv6.c.UseMulticast 2014-07-02 19:58:40.000000000 +0200
|
|
|
|
+++ dhcp-4.3.1b1/server/dhcpv6.c 2014-07-10 18:20:03.066256219 +0200
|
|
|
|
@@ -376,6 +376,48 @@ generate_new_server_duid(void) {
|
2010-03-12 20:18:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-03-19 17:22:59 +00:00
|
|
|
+ * Is the D6O_UNICAST option defined in dhcpd.conf ?
|
|
|
|
+ */
|
|
|
|
+static isc_boolean_t unicast_option_defined;
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Did we already search dhcpd.conf for D6O_UNICAST option ?
|
|
|
|
+ * We need to store it here to not parse dhcpd.conf repeatedly.
|
|
|
|
+ */
|
|
|
|
+static isc_boolean_t unicast_option_parsed = ISC_FALSE;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Is the D6O_UNICAST option defined in dhcpd.conf ?
|
2010-03-12 20:18:59 +00:00
|
|
|
+ */
|
|
|
|
+isc_boolean_t
|
|
|
|
+is_unicast_option_defined(void) {
|
|
|
|
+ struct option_state *opt_state;
|
|
|
|
+ struct option_cache *oc;
|
|
|
|
+
|
2010-03-19 17:22:59 +00:00
|
|
|
+ /*
|
|
|
|
+ * If we are looking for the unicast option for the first time
|
|
|
|
+ */
|
|
|
|
+ if (unicast_option_parsed == ISC_FALSE) {
|
|
|
|
+ unicast_option_parsed = ISC_TRUE;
|
|
|
|
+ opt_state = NULL;
|
|
|
|
+ if (!option_state_allocate(&opt_state, MDL)) {
|
|
|
|
+ log_fatal("No memory for option state.");
|
|
|
|
+ }
|
2010-03-12 20:18:59 +00:00
|
|
|
+
|
2010-03-19 17:22:59 +00:00
|
|
|
+ execute_statements_in_scope(NULL, NULL, NULL, NULL, NULL,
|
2014-01-07 11:37:10 +00:00
|
|
|
+ opt_state, &global_scope, root_group, NULL, NULL);
|
2010-03-12 20:18:59 +00:00
|
|
|
+
|
2010-03-19 17:22:59 +00:00
|
|
|
+ oc = lookup_option(&dhcpv6_universe, opt_state, D6O_UNICAST);
|
|
|
|
+ unicast_option_defined = (oc != NULL);
|
2010-03-12 20:18:59 +00:00
|
|
|
+
|
2010-03-19 17:22:59 +00:00
|
|
|
+ option_state_dereference(&opt_state, MDL);
|
|
|
|
+ }
|
2010-03-12 20:18:59 +00:00
|
|
|
+
|
2010-03-19 17:22:59 +00:00
|
|
|
+ return (unicast_option_defined);
|
2010-03-12 20:18:59 +00:00
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
2010-03-19 17:22:59 +00:00
|
|
|
* Get the client identifier from the packet.
|
|
|
|
*/
|
|
|
|
isc_result_t
|
2014-07-10 17:01:31 +00:00
|
|
|
@@ -706,6 +748,12 @@ static const int required_opts[] = {
|
|
|
|
D6O_PREFERENCE,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
+static const int required_opts_NAA[] = {
|
|
|
|
+ D6O_CLIENTID,
|
|
|
|
+ D6O_SERVERID,
|
|
|
|
+ D6O_STATUS_CODE,
|
|
|
|
+ 0
|
|
|
|
+};
|
|
|
|
static const int required_opts_solicit[] = {
|
|
|
|
D6O_CLIENTID,
|
|
|
|
D6O_SERVERID,
|
|
|
|
@@ -1587,6 +1635,56 @@ lease_to_client(struct data_string *repl
|
2013-12-20 15:13:52 +00:00
|
|
|
reply.shared->group, NULL);
|
2010-03-12 20:18:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
+ /* reject unicast message, unless we set unicast option */
|
|
|
|
+ if ((packet->unicast == ISC_TRUE) && !is_unicast_option_defined())
|
|
|
|
+ /*
|
|
|
|
+ * RFC3315 section 18.2.1 (Request):
|
|
|
|
+ *
|
|
|
|
+ * When the server receives a Request message via unicast from a client
|
|
|
|
+ * to which the server has not sent a unicast option, the server
|
|
|
|
+ * discards the Request message and responds with a Reply message
|
|
|
|
+ * containing a Status Code option with the value UseMulticast, a Server
|
|
|
|
+ * Identifier option containing the server's DUID, the Client Identifier
|
|
|
|
+ * option from the client message, and no other options.
|
|
|
|
+ *
|
|
|
|
+ * Section 18.2.3 (Renew):
|
|
|
|
+ *
|
|
|
|
+ * When the server receives a Renew message via unicast from a client to
|
|
|
|
+ * which the server has not sent a unicast option, the server discards
|
|
|
|
+ * the Renew message and responds with a Reply message containing a
|
|
|
|
+ * Status Code option with the value UseMulticast, a Server Identifier
|
|
|
|
+ * option containing the server's DUID, the Client Identifier option
|
|
|
|
+ * from the client message, and no other options.
|
|
|
|
+ */
|
|
|
|
+ {
|
|
|
|
+ /* Set the UseMulticast status code. */
|
|
|
|
+ if (!set_status_code(STATUS_UseMulticast,
|
|
|
|
+ "Unicast not allowed by server.",
|
|
|
|
+ reply.opt_state)) {
|
|
|
|
+ log_error("lease_to_client: Unable to set "
|
|
|
|
+ "UseMulticast status code.");
|
|
|
|
+ goto exit;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Rewind the cursor to the start. */
|
|
|
|
+ reply.cursor = REPLY_OPTIONS_INDEX;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Produce an reply that includes only:
|
|
|
|
+ *
|
|
|
|
+ * Status code.
|
|
|
|
+ * Server DUID.
|
|
|
|
+ * Client DUID.
|
|
|
|
+ */
|
|
|
|
+ reply.cursor += store_options6((char *)reply.buf.data +
|
|
|
|
+ reply.cursor,
|
|
|
|
+ sizeof(reply.buf) -
|
|
|
|
+ reply.cursor,
|
|
|
|
+ reply.opt_state, reply.packet,
|
|
|
|
+ required_opts_NAA,
|
|
|
|
+ NULL);
|
2012-04-17 09:46:32 +00:00
|
|
|
+ }
|
|
|
|
+
|
2010-03-12 20:18:59 +00:00
|
|
|
/*
|
|
|
|
* RFC3315 section 17.2.2 (Solicit):
|
|
|
|
*
|
2014-07-10 17:01:31 +00:00
|
|
|
@@ -1619,6 +1717,7 @@ lease_to_client(struct data_string *repl
|
2012-04-17 09:46:32 +00:00
|
|
|
* Having stored the client's IA's, store any options that
|
|
|
|
* will fit in the remaining space.
|
|
|
|
*/
|
|
|
|
+ else
|
|
|
|
reply.cursor += store_options6((char *)reply.buf.data + reply.cursor,
|
|
|
|
sizeof(reply.buf) - reply.cursor,
|
|
|
|
reply.opt_state, reply.packet,
|
2014-07-10 17:01:31 +00:00
|
|
|
@@ -4748,7 +4847,6 @@ dhcpv6_solicit(struct data_string *reply
|
2010-03-12 20:18:59 +00:00
|
|
|
* Very similar to Solicit handling, except the server DUID is required.
|
|
|
|
*/
|
|
|
|
|
|
|
|
-/* TODO: reject unicast messages, unless we set unicast option */
|
|
|
|
static void
|
|
|
|
dhcpv6_request(struct data_string *reply_ret, struct packet *packet) {
|
|
|
|
struct data_string client_id;
|
2014-07-10 17:01:31 +00:00
|
|
|
@@ -5078,7 +5176,6 @@ exit:
|
2010-03-12 20:18:59 +00:00
|
|
|
* except for the error code of when addresses don't match.
|
|
|
|
*/
|
|
|
|
|
|
|
|
-/* TODO: reject unicast messages, unless we set unicast option */
|
|
|
|
static void
|
|
|
|
dhcpv6_renew(struct data_string *reply, struct packet *packet) {
|
|
|
|
struct data_string client_id;
|
2014-07-10 17:01:31 +00:00
|
|
|
@@ -5322,18 +5419,60 @@ iterate_over_ia_na(struct data_string *r
|
2010-03-12 20:18:59 +00:00
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
- snprintf(status_msg, sizeof(status_msg), "%s received.", packet_type);
|
|
|
|
- if (!set_status_code(STATUS_Success, status_msg, opt_state)) {
|
|
|
|
- goto exit;
|
|
|
|
- }
|
|
|
|
+ /* reject unicast message, unless we set unicast option */
|
|
|
|
+ if ((packet->unicast == ISC_TRUE) && !is_unicast_option_defined()) {
|
|
|
|
+ /*
|
|
|
|
+ * RFC3315 section 18.2.6 (Release):
|
|
|
|
+ *
|
|
|
|
+ * When the server receives a Release message via unicast from a client
|
|
|
|
+ * to which the server has not sent a unicast option, the server
|
|
|
|
+ * discards the Release message and responds with a Reply message
|
|
|
|
+ * containing a Status Code option with value UseMulticast, a Server
|
|
|
|
+ * Identifier option containing the server's DUID, the Client Identifier
|
|
|
|
+ * option from the client message, and no other options.
|
|
|
|
+ *
|
|
|
|
+ * Section 18.2.7 (Decline):
|
|
|
|
+ *
|
|
|
|
+ * When the server receives a Decline message via unicast from a client
|
|
|
|
+ * to which the server has not sent a unicast option, the server
|
|
|
|
+ * discards the Decline message and responds with a Reply message
|
|
|
|
+ * containing a Status Code option with the value UseMulticast, a Server
|
|
|
|
+ * Identifier option containing the server's DUID, the Client Identifier
|
|
|
|
+ * option from the client message, and no other options.
|
|
|
|
+ */
|
|
|
|
+ snprintf(status_msg, sizeof(status_msg),
|
|
|
|
+ "%s received unicast.", packet_type);
|
|
|
|
+ if (!set_status_code(STATUS_UseMulticast, status_msg, opt_state)) {
|
|
|
|
+ goto exit;
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- /*
|
|
|
|
- * Add our options that are not associated with any IA_NA or IA_TA.
|
|
|
|
- */
|
|
|
|
- reply_ofs += store_options6(reply_data+reply_ofs,
|
|
|
|
- sizeof(reply_data)-reply_ofs,
|
|
|
|
+ /*
|
|
|
|
+ * Produce an reply that includes only:
|
|
|
|
+ *
|
|
|
|
+ * Status code.
|
|
|
|
+ * Server DUID.
|
|
|
|
+ * Client DUID.
|
|
|
|
+ */
|
|
|
|
+ reply_ofs += store_options6(reply_data+reply_ofs,
|
|
|
|
+ sizeof(reply_data)-reply_ofs,
|
|
|
|
opt_state, packet,
|
|
|
|
- required_opts, NULL);
|
|
|
|
+ required_opts_NAA, NULL);
|
|
|
|
+
|
|
|
|
+ goto return_reply;
|
|
|
|
+ } else {
|
|
|
|
+ snprintf(status_msg, sizeof(status_msg), "%s received.", packet_type);
|
|
|
|
+ if (!set_status_code(STATUS_Success, status_msg, opt_state)) {
|
|
|
|
+ goto exit;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Add our options that are not associated with any IA_NA or IA_TA.
|
|
|
|
+ */
|
|
|
|
+ reply_ofs += store_options6(reply_data+reply_ofs,
|
|
|
|
+ sizeof(reply_data)-reply_ofs,
|
|
|
|
+ opt_state, packet,
|
|
|
|
+ required_opts, NULL);
|
|
|
|
+ }
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Loop through the IA_NA reported by the client, and deal with
|
2014-07-10 17:01:31 +00:00
|
|
|
@@ -5471,6 +5610,7 @@ iterate_over_ia_na(struct data_string *r
|
2010-03-12 20:18:59 +00:00
|
|
|
/*
|
|
|
|
* Return our reply to the caller.
|
|
|
|
*/
|
|
|
|
+return_reply:
|
|
|
|
reply_ret->len = reply_ofs;
|
|
|
|
reply_ret->buffer = NULL;
|
|
|
|
if (!buffer_allocate(&reply_ret->buffer, reply_ofs, MDL)) {
|
2014-07-10 17:01:31 +00:00
|
|
|
@@ -5516,7 +5656,6 @@ exit:
|
2010-03-12 20:18:59 +00:00
|
|
|
* we still need to be aware of this possibility.
|
|
|
|
*/
|
|
|
|
|
|
|
|
-/* TODO: reject unicast messages, unless we set unicast option */
|
|
|
|
/* TODO: IA_TA */
|
|
|
|
static void
|
|
|
|
dhcpv6_decline(struct data_string *reply, struct packet *packet) {
|
2014-07-10 17:01:31 +00:00
|
|
|
@@ -5986,7 +6125,6 @@ exit:
|
2010-03-12 20:18:59 +00:00
|
|
|
* Release means a client is done with the leases.
|
|
|
|
*/
|
|
|
|
|
|
|
|
-/* TODO: reject unicast messages, unless we set unicast option */
|
|
|
|
static void
|
|
|
|
dhcpv6_release(struct data_string *reply, struct packet *packet) {
|
|
|
|
struct data_string client_id;
|