diff --git a/includes/dhcp6.h b/includes/dhcp6.h index bf8205c..e2258f1 100644 --- a/includes/dhcp6.h +++ b/includes/dhcp6.h @@ -115,6 +115,7 @@ #define D6O_V6_PCP_SERVER 86 /* RFC7291 */ #define D6O_DHCPV4_MSG 87 /* RFC7341 */ #define D6O_DHCP4_O_DHCP6_SERVER 88 /* RFC7341 */ +#define D6O_RELAY_PORT 90 /* XXX draft relay-port */ /* * Status Codes, from RFC 3315 section 24.4, and RFC 3633, 5007, 5460. diff --git a/includes/dhcpd.h b/includes/dhcpd.h index 261714d..05a5c12 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -472,6 +472,9 @@ struct packet { /* Propogates server value SV_ECHO_CLIENT_ID so it is available * in cons_options() */ int sv_echo_client_id; + + /* Relay port check */ + isc_boolean_t relay_source_port; }; /* @@ -2788,6 +2791,7 @@ extern struct in_addr local_address; extern u_int16_t local_port; extern u_int16_t remote_port; +extern u_int16_t relay_port; extern int dhcpv4_over_dhcpv6; extern int (*dhcp_interface_setup_hook) (struct interface_info *, struct iaddr *); diff --git a/server/dhcpv6.c b/server/dhcpv6.c index 18d8bb8..4b8a41c 100644 --- a/server/dhcpv6.c +++ b/server/dhcpv6.c @@ -844,6 +844,7 @@ static const int required_opts_solicit[] = { }; static const int required_opts_agent[] = { D6O_INTERFACE_ID, + D6O_RELAY_PORT, D6O_RELAY_MSG, 0 }; @@ -6545,6 +6546,33 @@ dhcpv6_relay_forw(struct data_string *reply_ret, struct packet *packet) { } /* + * Append the relay_port option if present. + */ + oc = lookup_option(&dhcpv6_universe, packet->options, + D6O_RELAY_PORT); + if (oc != NULL) { + if (!evaluate_option_cache(&a_opt, packet, + NULL, NULL, + packet->options, NULL, + &global_scope, oc, MDL)) { + log_error("dhcpv6_relay_forw: error evaluating " + "Relay Port."); + goto exit; + } + if (!save_option_buffer(&dhcpv6_universe, opt_state, NULL, + (unsigned char *)a_opt.data, + a_opt.len, + D6O_RELAY_PORT, 0)) { + log_error("dhcpv6_relay_forw: error saving " + "Relay Port."); + goto exit; + } + data_string_forget(&a_opt, MDL); + + packet->relay_source_port = ISC_TRUE; + } + + /* * Append our encapsulated stuff for caller. */ if (!save_option_buffer(&dhcpv6_universe, opt_state, NULL, @@ -7379,6 +7407,10 @@ dhcpv6(struct packet *packet) { */ to_addr.sin6_port = packet->client_port; #endif + /* Check relay source port */ + if (packet->relay_source_port && packet->client_port != 547) { + to_addr.sin6_port = packet->client_port; + } memcpy(&to_addr.sin6_addr, packet->client_addr.iabuf, sizeof(to_addr.sin6_addr));