void config_dhcp_reset(void) {
config_dhcp.release = true;
config_dhcp.dscp = 0;
- config_dhcp.sol_timeout = DHCPV6_SOL_MAX_RT;
config_dhcp.sk_prio = 0;
config_dhcp.stateful_only_mode = false;
config_dhcp.ia_na_mode = IA_MODE_TRY;
config_dhcp.client_options = DHCPV6_CLIENT_FQDN | DHCPV6_ACCEPT_RECONFIGURE;
config_dhcp.allow_slaac_only = -1;
config_dhcp.oro_user_cnt = 0;
+ memset(config_dhcp.message_rtx, 0, sizeof(config_dhcp.message_rtx));
+ config_dhcp.message_rtx[CONFIG_DHCP_SOLICIT].delay_max = DHCPV6_MAX_DELAY;
+ config_dhcp.message_rtx[CONFIG_DHCP_SOLICIT].timeout_init = DHCPV6_SOL_INIT_RT;
+ config_dhcp.message_rtx[CONFIG_DHCP_SOLICIT].timeout_max = DHCPV6_SOL_MAX_RT;
+ config_dhcp.message_rtx[CONFIG_DHCP_REQUEST].timeout_init = DHCPV6_REQ_INIT_RT;
+ config_dhcp.message_rtx[CONFIG_DHCP_REQUEST].timeout_max = DHCPV6_REQ_MAX_RT;
+ config_dhcp.message_rtx[CONFIG_DHCP_REQUEST].rc_max = DHCPV6_REQ_MAX_RC;
+ config_dhcp.message_rtx[CONFIG_DHCP_RENEW].timeout_init = DHCPV6_REN_INIT_RT;
+ config_dhcp.message_rtx[CONFIG_DHCP_RENEW].timeout_max = DHCPV6_REN_MAX_RT;
+ config_dhcp.message_rtx[CONFIG_DHCP_REBIND].timeout_init = DHCPV6_REB_INIT_RT;
+ config_dhcp.message_rtx[CONFIG_DHCP_REBIND].timeout_max = DHCPV6_REB_MAX_RT;
+ config_dhcp.message_rtx[CONFIG_DHCP_INFO_REQ].delay_max = DHCPV6_MAX_DELAY;
+ config_dhcp.message_rtx[CONFIG_DHCP_INFO_REQ].timeout_init = DHCPV6_INF_INIT_RT;
+ config_dhcp.message_rtx[CONFIG_DHCP_INFO_REQ].timeout_max = DHCPV6_INF_MAX_RT;
+ config_dhcp.message_rtx[CONFIG_DHCP_RELEASE].timeout_init = DHCPV6_REL_INIT_RT;
+ config_dhcp.message_rtx[CONFIG_DHCP_RELEASE].rc_max = DHCPV6_REL_MAX_RC;
+ config_dhcp.message_rtx[CONFIG_DHCP_DECLINE].timeout_init = DHCPV6_DEC_INIT_RT;
+ config_dhcp.message_rtx[CONFIG_DHCP_DECLINE].rc_max = DHCPV6_DEC_MAX_RC;
+ config_dhcp.irt_default = DHCPV6_IRT_DEFAULT;
+ config_dhcp.irt_min = DHCPV6_IRT_MIN;
+ config_dhcp.rand_factor = DHCPV6_RAND_FACTOR;
}
void config_set_release(bool enable) {
}
bool config_set_dscp(unsigned int value) {
- if (value > 63)
+ if (value > 63) {
+ syslog(LOG_ERR, "Invalid DSCP value");
return false;
+ }
config_dhcp.dscp = value;
return true;
}
-bool config_set_solicit_timeout(unsigned int timeout) {
- if (timeout > INT32_MAX)
- return false;
-
- config_dhcp.sol_timeout = timeout;
- return true;
-}
-
bool config_set_sk_priority(unsigned int priority) {
- if (priority > 6)
+ if (priority > 6) {
+ syslog(LOG_ERR, "Invalid SK priority value");
return false;
-
+ }
config_dhcp.sk_prio = priority;
return true;
}
} else if (!strcmp(mode, "try")) {
config_dhcp.ia_na_mode = IA_MODE_TRY;
} else {
+ syslog(LOG_ERR, "Invalid IA_NA Request Addresses mode");
return false;
}
}
bool config_add_requested_options(unsigned int option) {
- if (option > UINT16_MAX)
+ if (option > UINT16_MAX) {
+ syslog(LOG_ERR, "Invalid requested option");
return false;
+ }
option = htons(option);
if (odhcp6c_insert_state(STATE_ORO, 0, &option, 2)) {
+ syslog(LOG_ERR, "Failed to set requested option");
return false;
}
config_dhcp.oro_user_cnt++;
return (config_parse_opt(option) == 0);
}
+bool config_set_rtx_delay_max(enum config_dhcp_msg msg, unsigned int value)
+{
+ if (msg >= CONFIG_DHCP_MAX || value > UINT8_MAX) {
+ syslog(LOG_ERR, "Invalid retransmission Maximum Delay value");
+ return false;
+ }
+ config_dhcp.message_rtx[msg].delay_max = value;
+ return true;
+}
+
+bool config_set_rtx_timeout_init(enum config_dhcp_msg msg, unsigned int value)
+{
+ if (msg >= CONFIG_DHCP_MAX || value > UINT8_MAX || value == 0) {
+ syslog(LOG_ERR, "Invalid retransmission Initial Timeout value");
+ return false;
+ }
+ config_dhcp.message_rtx[msg].timeout_init = value;
+ return true;
+}
+
+bool config_set_rtx_timeout_max(enum config_dhcp_msg msg, unsigned int value)
+{
+ if (msg >= CONFIG_DHCP_MAX || value > UINT16_MAX) {
+ syslog(LOG_ERR, "Invalid retransmission Maximum Timeout value");
+ return false;
+ }
+ config_dhcp.message_rtx[msg].timeout_max = value;
+ return true;
+}
+
+bool config_set_rtx_rc_max(enum config_dhcp_msg msg, unsigned int value)
+{
+ if (msg >= CONFIG_DHCP_MAX || value > UINT8_MAX) {
+ syslog(LOG_ERR, "Invalid retransmission Retry Attempt value");
+ return false;
+ }
+ config_dhcp.message_rtx[msg].rc_max = value;
+ return true;
+}
+
+bool config_set_irt_default(unsigned int value)
+{
+ if (value == 0) {
+ syslog(LOG_ERR, "Invalid Default Information Refresh Time value");
+ return false;
+ }
+ config_dhcp.irt_default = value;
+ return true;
+}
+
+bool config_set_irt_min(unsigned int value)
+{
+ if (value == 0) {
+ syslog(LOG_ERR, "Invalid Minimum Information Refresh Time value");
+ return false;
+ }
+ config_dhcp.irt_min = value;
+ return true;
+}
+
+bool config_set_rand_factor(unsigned int value)
+{
+ if (value > 999 || value < 10) {
+ syslog(LOG_ERR, "Invalid Random Factor value");
+ return false;
+ }
+ config_dhcp.rand_factor = value;
+ return true;
+}
+
static int config_parse_opt_u8(const char *src, uint8_t **dst)
{
int len = strlen(src);
return ret;
}
+
+void config_apply_dhcp_rtx(struct dhcpv6_retx* dhcpv6_retx)
+{
+ dhcpv6_retx[DHCPV6_MSG_SOLICIT].max_delay = config_dhcp.message_rtx[CONFIG_DHCP_SOLICIT].delay_max;
+ dhcpv6_retx[DHCPV6_MSG_SOLICIT].init_timeo = config_dhcp.message_rtx[CONFIG_DHCP_SOLICIT].timeout_init;
+ dhcpv6_retx[DHCPV6_MSG_SOLICIT].max_timeo = config_dhcp.message_rtx[CONFIG_DHCP_SOLICIT].timeout_max;
+ dhcpv6_retx[DHCPV6_MSG_REQUEST].init_timeo = config_dhcp.message_rtx[CONFIG_DHCP_REQUEST].timeout_init;
+ dhcpv6_retx[DHCPV6_MSG_REQUEST].max_timeo = config_dhcp.message_rtx[CONFIG_DHCP_REQUEST].timeout_max;
+ dhcpv6_retx[DHCPV6_MSG_REQUEST].max_rc = config_dhcp.message_rtx[CONFIG_DHCP_REQUEST].rc_max;
+ dhcpv6_retx[DHCPV6_MSG_RENEW].init_timeo = config_dhcp.message_rtx[CONFIG_DHCP_RENEW].timeout_init;
+ dhcpv6_retx[DHCPV6_MSG_RENEW].max_timeo = config_dhcp.message_rtx[CONFIG_DHCP_RENEW].timeout_max;
+ dhcpv6_retx[DHCPV6_MSG_REBIND].init_timeo = config_dhcp.message_rtx[CONFIG_DHCP_REBIND].timeout_init;
+ dhcpv6_retx[DHCPV6_MSG_REBIND].max_timeo = config_dhcp.message_rtx[CONFIG_DHCP_REBIND].timeout_max;
+ dhcpv6_retx[DHCPV6_MSG_INFO_REQ].max_delay = config_dhcp.message_rtx[CONFIG_DHCP_INFO_REQ].delay_max;
+ dhcpv6_retx[DHCPV6_MSG_INFO_REQ].init_timeo = config_dhcp.message_rtx[CONFIG_DHCP_INFO_REQ].timeout_init;
+ dhcpv6_retx[DHCPV6_MSG_INFO_REQ].max_timeo = config_dhcp.message_rtx[CONFIG_DHCP_INFO_REQ].timeout_max;
+ dhcpv6_retx[DHCPV6_MSG_RELEASE].init_timeo = config_dhcp.message_rtx[CONFIG_DHCP_RELEASE].timeout_init;
+ dhcpv6_retx[DHCPV6_MSG_RELEASE].max_rc = config_dhcp.message_rtx[CONFIG_DHCP_RELEASE].rc_max;
+ dhcpv6_retx[DHCPV6_MSG_DECLINE].init_timeo = config_dhcp.message_rtx[CONFIG_DHCP_DECLINE].timeout_init;
+ dhcpv6_retx[DHCPV6_MSG_DECLINE].max_rc = config_dhcp.message_rtx[CONFIG_DHCP_DECLINE].rc_max;
+}
\ No newline at end of file
#include "odhcp6c.h"
+struct config_dhcp_rtx {
+ uint8_t delay_max;
+ uint8_t timeout_init;
+ uint16_t timeout_max;
+ uint8_t rc_max;
+};
+
+enum config_dhcp_msg {
+ CONFIG_DHCP_SOLICIT,
+ CONFIG_DHCP_REQUEST,
+ CONFIG_DHCP_RENEW,
+ CONFIG_DHCP_REBIND,
+ CONFIG_DHCP_RELEASE,
+ CONFIG_DHCP_DECLINE,
+ CONFIG_DHCP_INFO_REQ,
+ CONFIG_DHCP_MAX
+};
+
struct config_dhcp {
bool release;
int dscp;
- int sol_timeout;
int sk_prio;
bool stateful_only_mode;
enum odhcp6c_ia_mode ia_na_mode;
unsigned int client_options;
int allow_slaac_only;
unsigned int oro_user_cnt;
+ struct config_dhcp_rtx message_rtx[CONFIG_DHCP_MAX];
+ uint32_t irt_default;
+ uint32_t irt_min;
+ uint16_t rand_factor;
};
struct config_dhcp *config_dhcp_get(void);
void config_dhcp_reset(void);
void config_set_release(bool enable);
bool config_set_dscp(unsigned int value) ;
-bool config_set_solicit_timeout(unsigned int timeout);
bool config_set_sk_priority(unsigned int priority);
void config_set_client_options(enum dhcpv6_config option, bool enable);
bool config_set_request_addresses(char *mode);
bool config_add_requested_options(unsigned int option);
void config_clear_send_options(void);
bool config_add_send_options(char *option);
+bool config_set_rtx_delay_max(enum config_dhcp_msg msg, unsigned int value);
+bool config_set_rtx_timeout_init(enum config_dhcp_msg msg, unsigned int value);
+bool config_set_rtx_timeout_max(enum config_dhcp_msg msg, unsigned int value);
+bool config_set_rtx_rc_max(enum config_dhcp_msg msg, unsigned int value);
+bool config_set_irt_default(unsigned int value);
+bool config_set_irt_min(unsigned int value);
+bool config_set_rand_factor(unsigned int value);
int config_add_opt(const uint16_t code, const uint8_t *data, const uint16_t len);
int config_parse_opt_data(const char *data, uint8_t **dst, const unsigned int type, const bool array);
int config_parse_opt(const char *opt);
+void config_apply_dhcp_rtx(struct dhcpv6_retx* dhcpv6_retx);
+
#endif /* _CONFIG_H_ */
#include <net/ethernet.h>
#include <libubox/md5.h>
+#include "config.h"
#include "odhcp6c.h"
#define DHCPV6_CLIENT_PORT 546
#define DHCPV6_SERVER_PORT 547
#define DHCPV6_DUID_LLADDR 3
-#define DHCPV6_REQ_DELAY 1
#define DHCPV6_SOL_MAX_RT_MIN 60
#define DHCPV6_SOL_MAX_RT_MAX 86400
// RFC 3315 - 5.5 Timeout and Delay values
static const struct dhcpv6_retx dhcpv6_retx_default[_DHCPV6_MSG_MAX] = {
- [DHCPV6_MSG_UNKNOWN] = {false, 1, 120, 0, "<POLL>",
- dhcpv6_handle_reconfigure, NULL, false, 0, 0, 0, {0, 0, 0}, 0, 0, 0, -1, 0},
- [DHCPV6_MSG_SOLICIT] = {true, 1, DHCPV6_SOL_MAX_RT, 0, "SOLICIT",
- dhcpv6_handle_advert, dhcpv6_commit_advert, false, 0, 0, 0, {0, 0, 0}, 0, 0, 0, -1, 0},
- [DHCPV6_MSG_REQUEST] = {true, 1, DHCPV6_REQ_MAX_RT, 10, "REQUEST",
- dhcpv6_handle_reply, NULL, false, 0, 0, 0, {0, 0, 0}, 0, 0, 0, -1, 0},
- [DHCPV6_MSG_RENEW] = {false, 10, DHCPV6_REN_MAX_RT, 0, "RENEW",
- dhcpv6_handle_reply, NULL, false, 0, 0, 0, {0, 0, 0}, 0, 0, 0, -1, 0},
- [DHCPV6_MSG_REBIND] = {false, 10, DHCPV6_REB_MAX_RT, 0, "REBIND",
- dhcpv6_handle_rebind_reply, NULL, false, 0, 0, 0, {0, 0, 0}, 0, 0, 0, -1, 0},
- [DHCPV6_MSG_RELEASE] = {false, 1, 0, 5, "RELEASE", NULL, NULL, false, 0, 0, 0, {0, 0, 0}, 0, 0, 0, -1, 0},
- [DHCPV6_MSG_DECLINE] = {false, 1, 0, 5, "DECLINE", NULL, NULL, false, 0, 0, 0,{0, 0, 0}, 0, 0, 0, -1, 0},
- [DHCPV6_MSG_INFO_REQ] = {true, 1, DHCPV6_INF_MAX_RT, 0, "INFOREQ",
- dhcpv6_handle_reply, NULL, false, 0, 0, 0, {0, 0, 0}, 0, 0, 0, -1, 0},
+ [DHCPV6_MSG_UNKNOWN] = {
+ 0,
+ 1,
+ 120,
+ 0,
+ "<POLL>",
+ dhcpv6_handle_reconfigure,
+ NULL,
+ false,
+ 0,
+ 0,
+ 0,
+ {0, 0, 0},
+ 0,
+ 0,
+ 0,
+ -1,
+ 0
+ },
+ [DHCPV6_MSG_SOLICIT] = {
+ DHCPV6_MAX_DELAY,
+ DHCPV6_SOL_INIT_RT,
+ DHCPV6_SOL_MAX_RT,
+ 0,
+ "SOLICIT",
+ dhcpv6_handle_advert,
+ dhcpv6_commit_advert,
+ false,
+ 0,
+ 0,
+ 0,
+ {0, 0, 0},
+ 0,
+ 0,
+ 0,
+ -1,
+ 0
+ },
+ [DHCPV6_MSG_REQUEST] = {
+ 0,
+ DHCPV6_REQ_INIT_RT,
+ DHCPV6_REQ_MAX_RT,
+ DHCPV6_REQ_MAX_RC,
+ "REQUEST",
+ dhcpv6_handle_reply,
+ NULL,
+ false,
+ 0,
+ 0,
+ 0,
+ {0, 0, 0},
+ 0,
+ 0,
+ 0,
+ -1,
+ 0
+ },
+ [DHCPV6_MSG_RENEW] = {
+ 0,
+ DHCPV6_REN_INIT_RT,
+ DHCPV6_REN_MAX_RT,
+ 0,
+ "RENEW",
+ dhcpv6_handle_reply,
+ NULL,
+ false,
+ 0,
+ 0,
+ 0,
+ {0, 0, 0},
+ 0,
+ 0,
+ 0,
+ -1,
+ 0
+ },
+ [DHCPV6_MSG_REBIND] = {
+ 0,
+ DHCPV6_REB_INIT_RT,
+ DHCPV6_REB_MAX_RT,
+ 0,
+ "REBIND",
+ dhcpv6_handle_rebind_reply,
+ NULL,
+ false,
+ 0,
+ 0,
+ 0,
+ {0, 0, 0},
+ 0,
+ 0,
+ 0,
+ -1,
+ 0
+ },
+ [DHCPV6_MSG_RELEASE] = {
+ 0,
+ DHCPV6_REL_INIT_RT,
+ 0,
+ DHCPV6_REL_MAX_RC,
+ "RELEASE",
+ NULL,
+ NULL,
+ false,
+ 0,
+ 0,
+ 0,
+ {0, 0, 0},
+ 0,
+ 0,
+ 0,
+ -1,
+ 0
+ },
+ [DHCPV6_MSG_DECLINE] = {
+ 0,
+ DHCPV6_DEC_INIT_RT,
+ 0,
+ DHCPV6_DEC_MAX_RC,
+ "DECLINE",
+ NULL,
+ NULL,
+ false,
+ 0,
+ 0,
+ 0,
+ {0, 0, 0},
+ 0,
+ 0,
+ 0,
+ -1,
+ 0
+ },
+ [DHCPV6_MSG_INFO_REQ] = {
+ DHCPV6_MAX_DELAY,
+ DHCPV6_INF_INIT_RT,
+ DHCPV6_INF_MAX_RT,
+ 0,
+ "INFOREQ",
+ dhcpv6_handle_reply,
+ NULL,
+ false,
+ 0,
+ 0,
+ 0,
+ {0, 0, 0},
+ 0,
+ 0,
+ 0,
+ -1,
+ 0
+ },
};
static struct dhcpv6_retx dhcpv6_retx[_DHCPV6_MSG_MAX] = {0};
// counters for statistics
static struct dhcpv6_stats dhcpv6_stats = {0};
+// config
+static struct config_dhcp* config_dhcp = NULL;
+
static uint32_t ntohl_unaligned(const uint8_t *data)
{
uint32_t buf;
memset(&dhcpv6_stats, 0, sizeof(dhcpv6_stats));
}
-int init_dhcpv6(const char *ifname, unsigned int options, int sk_prio, int sol_timeout, unsigned int dscp)
+int init_dhcpv6(const char *ifname)
{
+ config_dhcp = config_dhcp_get();
+
memcpy(dhcpv6_retx, dhcpv6_retx_default, sizeof(dhcpv6_retx));
- client_options = options;
- dhcpv6_retx[DHCPV6_MSG_SOLICIT].max_timeo = sol_timeout;
+ config_apply_dhcp_rtx(dhcpv6_retx);
+
+ client_options = config_dhcp->client_options;
sock = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
if (sock < 0)
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname)) < 0)
goto failure;
- if (setsockopt(sock, SOL_SOCKET, SO_PRIORITY, &sk_prio, sizeof(sk_prio)) < 0)
+ if (setsockopt(sock, SOL_SOCKET, SO_PRIORITY, &(config_dhcp->sk_prio), sizeof(config_dhcp->sk_prio)) < 0)
goto failure;
- val = dscp << 2;
+ val = config_dhcp->dscp << 2;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0) {
goto failure;
}
int random;
odhcp6c_random(&random, sizeof(random));
- return (time * ((int64_t)random % 1000LL)) / 10000LL;
+ return (time * ((int64_t)random % (config_dhcp->rand_factor*10LL))) / 10000LL;
}
// Message validation checks according to RFC3315 chapter 15
{
uint8_t *odata;
uint16_t otype, olen;
- uint32_t refresh = 86400;
+ uint32_t refresh = config_dhcp->irt_default;
int ret = 1;
unsigned int state_IAs;
unsigned int updated_IAs = 0;
odhcp6c_clear_state(STATE_SERVER_ADDR);
odhcp6c_add_state(STATE_SERVER_ADDR, &from->sin6_addr, 16);
- t1 = refresh;
+ t1 = (refresh < config_dhcp->irt_min) ? config_dhcp->irt_min : refresh;
break;
default:
struct dhcpv6_retx *retx = &dhcpv6_retx[type];
uint64_t current_milli_time = 0;
- if (retx->delay ) {
- if (retx->delay_msec == 0) {
- retx->delay_msec = (dhcpv6_rand_delay((10000 * DHCPV6_REQ_DELAY) / 2) + (1000 * DHCPV6_REQ_DELAY) / 2);
- dhcpv6_set_state_timeout(retx->delay_msec);
- retx->delay_msec += odhcp6c_get_milli_time();
- return 1;
- } else {
- current_milli_time = odhcp6c_get_milli_time();
- if (current_milli_time < retx->delay_msec) {
- dhcpv6_set_state_timeout(retx->delay_msec - current_milli_time);
+ if (!retx->is_retransmit) {
+ if (retx->max_delay) {
+ if (retx->delay_msec == 0) {
+ retx->delay_msec = (dhcpv6_rand_delay((10000 * retx->max_delay) / 2) + (1000 * retx->max_delay) / 2);
+ dhcpv6_set_state_timeout(retx->delay_msec);
+ retx->delay_msec += odhcp6c_get_milli_time();
return 1;
+ } else {
+ current_milli_time = odhcp6c_get_milli_time();
+ if (current_milli_time < retx->delay_msec) {
+ dhcpv6_set_state_timeout(retx->delay_msec - current_milli_time);
+ return 1;
+ }
+ retx->delay_msec = 0;
}
- retx->delay_msec = 0;
}
- }
-
- if (!retx->is_retransmit) {
+
retx->is_retransmit = true;
retx->rc = 0;
retx->timeout = UINT32_MAX;
break;
case 't':
- config_set_solicit_timeout(atoi(optarg));
+ config_set_rtx_timeout_max(CONFIG_DHCP_SOLICIT, atoi(optarg));
break;
case 'C':
- if (!config_set_dscp(atoi(optarg))) {
- syslog(LOG_ERR, "Invalid DSCP value, using default (0)");
- }
+ config_set_dscp(atoi(optarg));
break;
case 'm':
odhcp6c_get_state(STATE_ORO, &oro_len);
config_dhcp->oro_user_cnt = oro_len / sizeof(uint16_t);
- if (init_dhcpv6(ifname, config_dhcp->client_options, config_dhcp->sk_prio, config_dhcp->sol_timeout, config_dhcp->dscp)) {
+ if (init_dhcpv6(ifname)) {
syslog(LOG_ERR, "failed to initialize: %s", strerror(errno));
return 1;
}
case DHCPV6_SOLICIT_PROCESSING:
case DHCPV6_REQUEST_PROCESSING:
res = dhcpv6_state_processing(msg_type);
-
- if (signal_usr2 || signal_term)
- dhcpv6_set_state(DHCPV6_EXIT);
break;
case DHCPV6_BOUND_PROCESSING:
if (signal_usr1)
dhcpv6_set_state(mode == DHCPV6_STATELESS ? DHCPV6_INFO : DHCPV6_RENEW);
- if (signal_usr2 || signal_term)
- dhcpv6_set_state(DHCPV6_EXIT);
break;
case DHCPV6_RENEW_PROCESSING:
if (signal_usr1)
signal_usr1 = false; // Acknowledged
- if (signal_usr2 || signal_term)
- dhcpv6_set_state(DHCPV6_EXIT);
break;
case DHCPV6_EXIT:
break;
}
+ if (signal_usr2 || signal_term)
+ dhcpv6_set_state(DHCPV6_EXIT);
+
poll_res = poll(fds, nfds, dhcpv6_get_state_timeout());
dhcpv6_reset_state_timeout();
if (poll_res == -1 && (errno == EINTR || errno == EAGAIN)) {
#define ND_OPT_RECURSIVE_DNS 25
#define ND_OPT_DNSSL 31
+#define DHCPV6_MAX_DELAY 1
+#define DHCPV6_IRT_DEFAULT 86400
+#define DHCPV6_IRT_MIN 600
+#define DHCPV6_RAND_FACTOR 100
+
+#define DHCPV6_SOL_INIT_RT 1
#define DHCPV6_SOL_MAX_RT 120
+
+#define DHCPV6_REQ_INIT_RT 1
#define DHCPV6_REQ_MAX_RT 30
-#define DHCPV6_CNF_MAX_RT 4
+#define DHCPV6_REQ_MAX_RC 10
+
+#define DHCPV6_REN_INIT_RT 10
#define DHCPV6_REN_MAX_RT 600
+
+#define DHCPV6_REB_INIT_RT 10
#define DHCPV6_REB_MAX_RT 600
-#define DHCPV6_INF_MAX_RT 120
+
+#define DHCPV6_INF_INIT_RT 1
+#define DHCPV6_INF_MAX_RT 3600
+
+#define DHCPV6_REL_INIT_RT 1
+#define DHCPV6_REL_MAX_RC 4
+
+#define DHCPV6_DEC_INIT_RT 1
+#define DHCPV6_DEC_MAX_RC 4
#define RA_MIN_ADV_INTERVAL 3 /* RFC 4861 paragraph 6.2.1 */
// retransmission strategy
struct dhcpv6_retx {
- bool delay;
+ uint8_t max_delay;
uint8_t init_timeo;
uint16_t max_timeo;
uint8_t max_rc;
const char *str;
};
-int init_dhcpv6(const char *ifname, unsigned int client_options, int sk_prio, int sol_timeout, unsigned int dscp);
+int init_dhcpv6(const char *ifname);
int dhcpv6_set_ia_mode(enum odhcp6c_ia_mode na, enum odhcp6c_ia_mode pd, bool stateful_only);
int dhcpv6_promote_server_cand(void);
int dhcpv6_send_request(enum dhcpv6_msg type);
void notify_state_change(const char *status, int delay, bool resume);
-void config_set_release(bool enable);
-bool config_set_dscp(unsigned int value);
-bool config_set_solicit_timeout(unsigned int timeout);
-bool config_set_sk_priority(unsigned int value);
-void config_set_client_options(enum dhcpv6_config option, bool enable);
-bool config_set_request_addresses(char *mode);
-bool config_set_request_prefix(unsigned int length, unsigned int id);
-void config_set_stateful_only(bool enable);
-void config_clear_requested_options(void);
-bool config_add_requested_options(unsigned int option);
-void config_clear_send_options(void);
-bool config_add_send_options(char *option);
-
int script_init(const char *path, const char *ifname);
ssize_t script_unhexlify(uint8_t *dst, size_t len, const char *src);
void script_hexlify(char *dst, const uint8_t *src, size_t len);
#include <libubox/blobmsg.h>
#include "ubus.h"
+#include "config.h"
#define CHECK(stmt) \
do { \
RECONFIGURE_DHCP_ATTR_REQ_ADDRESSES,
RECONFIGURE_DHCP_ATTR_REQ_PREFIXES,
RECONFIGURE_DHCP_ATTR_STATEFUL,
+ RECONFIGURE_DHCP_ATTR_MSG_SOLICIT,
+ RECONFIGURE_DHCP_ATTR_MSG_REQUEST,
+ RECONFIGURE_DHCP_ATTR_MSG_RENEW,
+ RECONFIGURE_DHCP_ATTR_MSG_REBIND,
+ RECONFIGURE_DHCP_ATTR_MSG_RELEASE,
+ RECONFIGURE_DHCP_ATTR_MSG_DECLINE,
+ RECONFIGURE_DHCP_ATTR_MSG_INFO_REQ,
+ RECONFIGURE_DHCP_ATTR_IRT_DEFAULT,
+ RECONFIGURE_DHCP_ATTR_IRT_MIN,
+ RECONFIGURE_DHCP_ATTR_RAND_FACTOR,
RECONFIGURE_DHCP_ATTR_MAX,
};
[RECONFIGURE_DHCP_ATTR_REQ_ADDRESSES] = { .name = "req_addresses", .type = BLOBMSG_TYPE_STRING},
[RECONFIGURE_DHCP_ATTR_REQ_PREFIXES] = { .name = "req_prefixes", .type = BLOBMSG_TYPE_INT32},
[RECONFIGURE_DHCP_ATTR_STATEFUL] = { .name = "stateful_only", .type = BLOBMSG_TYPE_BOOL},
+ [RECONFIGURE_DHCP_ATTR_MSG_SOLICIT] = { .name = "msg_solicit", .type = BLOBMSG_TYPE_TABLE},
+ [RECONFIGURE_DHCP_ATTR_MSG_REQUEST] = { .name = "msg_request", .type = BLOBMSG_TYPE_TABLE},
+ [RECONFIGURE_DHCP_ATTR_MSG_RENEW] = { .name = "msg_renew", .type = BLOBMSG_TYPE_TABLE},
+ [RECONFIGURE_DHCP_ATTR_MSG_REBIND] = { .name = "msg_rebind", .type = BLOBMSG_TYPE_TABLE},
+ [RECONFIGURE_DHCP_ATTR_MSG_RELEASE] = { .name = "msg_release", .type = BLOBMSG_TYPE_TABLE},
+ [RECONFIGURE_DHCP_ATTR_MSG_DECLINE] = { .name = "msg_decline", .type = BLOBMSG_TYPE_TABLE},
+ [RECONFIGURE_DHCP_ATTR_MSG_INFO_REQ] = { .name = "msg_inforeq", .type = BLOBMSG_TYPE_TABLE},
+ [RECONFIGURE_DHCP_ATTR_IRT_DEFAULT] = { .name = "irt_default", .type = BLOBMSG_TYPE_INT32},
+ [RECONFIGURE_DHCP_ATTR_IRT_MIN] = { .name = "irt_min", .type = BLOBMSG_TYPE_INT32},
+ [RECONFIGURE_DHCP_ATTR_RAND_FACTOR] = { .name = "rand_factor", .type = BLOBMSG_TYPE_INT32},
};
static struct ubus_method odhcp6c_object_methods[] = {
return UBUS_STATUS_OK;
}
-
static int ubus_handle_get_state(struct ubus_context *ctx, _unused struct ubus_object *obj,
struct ubus_request_data *req, _unused const char *method,
_unused struct blob_attr *msg)
return UBUS_STATUS_OK;
}
+static int ubus_handle_reconfigure_dhcp_rtx(enum config_dhcp_msg msg, struct blob_attr* table)
+{
+ struct blob_attr *cur = NULL;
+ uint32_t value = 0;
+ size_t rem = 0;
+
+ if (msg >= CONFIG_DHCP_MAX || blobmsg_data_len(table) == 0)
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ blobmsg_for_each_attr(cur, table, rem) {
+ if (!blobmsg_check_attr(cur, true) || blobmsg_type(cur) != BLOBMSG_TYPE_INT32)
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ const char* name = blobmsg_name(cur);
+ if (strcmp("delay_max", name) == 0) {
+ value = blobmsg_get_u32(cur);
+ if (!config_set_rtx_delay_max(msg, value))
+ return UBUS_STATUS_INVALID_ARGUMENT;
+ } else if (strcmp("timeout_init", name) == 0 ) {
+ value = blobmsg_get_u32(cur);
+ if (!config_set_rtx_timeout_init(msg, value))
+ return UBUS_STATUS_INVALID_ARGUMENT;
+ } else if (strcmp("timeout_max", name) == 0 ) {
+ value = blobmsg_get_u32(cur);
+ if (!config_set_rtx_timeout_max(msg, value))
+ return UBUS_STATUS_INVALID_ARGUMENT;
+ } else if (strcmp("rc_max", name) == 0) {
+ value = blobmsg_get_u32(cur);
+ if (!config_set_rtx_rc_max(msg, value))
+ return UBUS_STATUS_INVALID_ARGUMENT;
+ } else {
+ return UBUS_STATUS_INVALID_ARGUMENT;
+ }
+ }
+
+ return UBUS_STATUS_OK;
+}
+
static int ubus_handle_reconfigure_dhcp(_unused struct ubus_context *ctx, _unused struct ubus_object *obj,
_unused struct ubus_request_data *req, _unused const char *method,
struct blob_attr *msg)
if ((cur = tb[RECONFIGURE_DHCP_ATTR_SOL_TIMEOUT])) {
value = blobmsg_get_u32(cur);
- if (!config_set_solicit_timeout(value))
+ if (!config_set_rtx_timeout_max(CONFIG_DHCP_SOLICIT, value))
return UBUS_STATUS_INVALID_ARGUMENT;
need_reinit = true;
valid_args = true;
valid_args = true;
}
+ if ((cur = tb[RECONFIGURE_DHCP_ATTR_MSG_SOLICIT])) {
+ if (ubus_handle_reconfigure_dhcp_rtx(CONFIG_DHCP_SOLICIT, cur))
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ need_reinit = true;
+ valid_args = true;
+ }
+
+ if ((cur = tb[RECONFIGURE_DHCP_ATTR_MSG_REQUEST])) {
+ if (ubus_handle_reconfigure_dhcp_rtx(CONFIG_DHCP_REQUEST, cur))
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ need_reinit = true;
+ valid_args = true;
+ }
+
+ if ((cur = tb[RECONFIGURE_DHCP_ATTR_MSG_RENEW])) {
+ if (ubus_handle_reconfigure_dhcp_rtx(CONFIG_DHCP_RENEW, cur))
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ need_reinit = true;
+ valid_args = true;
+ }
+
+ if ((cur = tb[RECONFIGURE_DHCP_ATTR_MSG_REBIND])) {
+ if (ubus_handle_reconfigure_dhcp_rtx(CONFIG_DHCP_REBIND, cur))
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ need_reinit = true;
+ valid_args = true;
+ }
+
+ if ((cur = tb[RECONFIGURE_DHCP_ATTR_MSG_RELEASE])) {
+ if (ubus_handle_reconfigure_dhcp_rtx(CONFIG_DHCP_RELEASE, cur))
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ need_reinit = true;
+ valid_args = true;
+ }
+
+ if ((cur = tb[RECONFIGURE_DHCP_ATTR_MSG_DECLINE])) {
+ if (ubus_handle_reconfigure_dhcp_rtx(CONFIG_DHCP_DECLINE, cur))
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ need_reinit = true;
+ valid_args = true;
+ }
+
+ if ((cur = tb[RECONFIGURE_DHCP_ATTR_MSG_INFO_REQ])) {
+ if (ubus_handle_reconfigure_dhcp_rtx(CONFIG_DHCP_INFO_REQ, cur))
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ need_reinit = true;
+ valid_args = true;
+ }
+
+ if ((cur = tb[RECONFIGURE_DHCP_ATTR_IRT_MIN])) {
+ value = blobmsg_get_u32(cur);
+
+ if (!config_set_irt_min(value))
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ need_reinit = true;
+ valid_args = true;
+ }
+
+ if ((cur = tb[RECONFIGURE_DHCP_ATTR_IRT_DEFAULT])) {
+ value = blobmsg_get_u32(cur);
+
+ if (!config_set_irt_default(value))
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ need_reinit = true;
+ valid_args = true;
+ }
+
+ if ((cur = tb[RECONFIGURE_DHCP_ATTR_RAND_FACTOR])) {
+ value = blobmsg_get_u32(cur);
+
+ if (!config_set_rand_factor(value))
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ need_reinit = true;
+ valid_args = true;
+ }
+
if (need_reinit)
raise(SIGUSR2);