35 #if defined (FAILOVER_PROTOCOL)
38 dhcp_failover_link_t *);
41 static isc_result_t failover_message_reference (failover_message_t **,
44 static isc_result_t failover_message_dereference (failover_message_t **,
47 static void dhcp_failover_pool_balance(dhcp_failover_state_t *state);
48 static void dhcp_failover_pool_reqbalance(dhcp_failover_state_t *state);
49 static int dhcp_failover_pool_dobalance(dhcp_failover_state_t *state,
50 isc_boolean_t *sendreq);
51 static inline int secondary_not_hoarding(dhcp_failover_state_t *state,
57 dhcp_failover_state_t *state;
64 if (state -> pool_count == 0) {
65 log_error (
"failover peer declaration with no %s",
67 log_error (
"In order to use failover, you MUST %s",
68 "refer to your main failover declaration");
69 log_error (
"in each pool declaration. You MUST %s",
70 "NOT use range declarations outside");
77 #if defined (DEBUG_FAILOVER_TIMING)
78 log_info (
"add_timeout +90 dhcp_failover_reconnect");
85 dhcp_failover_state_reference,
87 dhcp_failover_state_dereference);
88 log_error (
"failover peer %s: %s", state -> name,
89 isc_result_totext (status));
94 if (status != ISC_R_SUCCESS) {
95 #if defined (DEBUG_FAILOVER_TIMING)
97 "dhcp_failover_listener_restart");
112 dhcp_failover_state_t *state;
122 dhcp_failover_state_t *peer;
124 dhcp_failover_state_t *dup = (dhcp_failover_state_t *)0;
128 if (status == ISC_R_NOTFOUND) {
130 dhcp_failover_state_reference (&peer -> next,
136 return ISC_R_SUCCESS;
138 dhcp_failover_state_dereference (&dup,
MDL);
139 if (status == ISC_R_SUCCESS)
145 dhcp_failover_state_t **peer;
150 dhcp_failover_state_t *p;
153 if (!strcmp (name, p -> name))
156 return dhcp_failover_state_reference (peer, p, file, line);
157 return ISC_R_NOTFOUND;
179 dhcp_failover_link_t *obj;
180 dhcp_failover_state_t *state;
188 for (o = h; o -> outer; o = o -> outer)
190 for (; o; o = o -> inner) {
196 state = (dhcp_failover_state_t *)o;
198 obj = (dhcp_failover_link_t *)0;
199 status = dhcp_failover_link_allocate (&obj,
MDL);
200 if (status != ISC_R_SUCCESS)
203 state -> partner.address,
MDL);
204 obj -> peer_port = state -> partner.port;
205 dhcp_failover_state_reference (&obj -> state_object, state,
MDL);
207 memset (&ds, 0,
sizeof ds);
213 dhcp_failover_link_dereference (&obj,
MDL);
214 return ISC_R_UNEXPECTED;
220 if (status != ISC_R_SUCCESS) {
221 dhcp_failover_link_dereference (&obj,
MDL);
225 for (i = 0; i < addrs -> count; i++) {
226 addrs -> addresses [i].addrtype = AF_INET;
227 addrs -> addresses [i].addrlen =
sizeof (
struct in_addr);
228 memcpy (addrs -> addresses [i].address,
229 &ds.data [i * 4], sizeof (
struct in_addr));
230 addrs -> addresses [i].port = obj -> peer_port;
235 if (!state -> me.address ||
243 memset (&local_addr, 0,
sizeof local_addr);
245 local_addr.
addrlen =
sizeof (
struct in_addr);
247 log_fatal (
"failover peer %s: no local address.",
251 if (ds.len != sizeof (
struct in_addr)) {
252 log_error(
"failover peer %s: 'address' parameter "
253 "fails to resolve to an IPv4 address",
256 dhcp_failover_link_dereference (&obj,
MDL);
262 memcpy (local_addr.
address, ds.data, ds.len);
274 dhcp_failover_link_dereference (&obj,
MDL);
279 const char *name, va_list ap)
282 dhcp_failover_link_t *link;
284 dhcp_failover_state_t *s, *state = (dhcp_failover_state_t *)0;
291 return ISC_R_UNEXPECTED;
293 link = (dhcp_failover_link_t *)h;
295 if (!strcmp (name,
"connect")) {
296 if (link -> state_object -> i_am == primary) {
298 if (status != ISC_R_SUCCESS) {
299 log_info (
"dhcp_failover_send_connect: %s",
300 isc_result_totext (status));
304 status = ISC_R_SUCCESS;
307 #if defined (DEBUG_FAILOVER_TIMING)
309 "dhcp_failover_link_startup_timeout");
316 (
tvref_t)dhcp_failover_link_reference,
317 (
tvunref_t)dhcp_failover_link_dereference);
321 if (!strcmp (name,
"disconnect")) {
322 if (link -> state_object) {
323 dhcp_failover_state_reference (&state,
324 link -> state_object,
MDL);
325 link -> state = dhcp_flink_disconnected;
328 if (state->link_to_peer == link)
332 #if defined (DEBUG_FAILOVER_TIMING)
333 log_info(
"add_timeout +5 dhcp_failover_reconnect");
336 tv.tv_usec =
cur_tv.tv_usec;
338 (
tvref_t)dhcp_failover_state_reference,
339 (
tvunref_t)dhcp_failover_state_dereference);
341 dhcp_failover_state_dereference (&state,
MDL);
343 return ISC_R_SUCCESS;
346 if (!strcmp (name,
"status")) {
347 if (link -> state_object) {
350 status = va_arg(ap, isc_result_t);
352 if ((status == ISC_R_HOSTUNREACH) || (status == ISC_R_TIMEDOUT)) {
353 dhcp_failover_state_reference (&state,
354 link -> state_object,
MDL);
355 link -> state = dhcp_flink_disconnected;
362 #if defined (DEBUG_FAILOVER_TIMING)
364 "dhcp_failover_reconnect");
370 (
tvref_t)dhcp_failover_state_reference,
371 (
tvunref_t)dhcp_failover_state_dereference);
373 dhcp_failover_state_dereference (&state,
MDL);
375 return ISC_R_SUCCESS;
379 if (strcmp (name,
"ready")) {
380 if (h -> inner && h -> inner -> type -> signal_handler)
381 return (*(h -> inner -> type -> signal_handler))
382 (h -> inner, name, ap);
383 return ISC_R_NOTFOUND;
393 switch (link -> state) {
394 case dhcp_flink_start:
395 link -> state = dhcp_flink_message_length_wait;
398 case dhcp_flink_message_length_wait:
400 link -> state = dhcp_flink_message_wait;
401 link -> imsg =
dmalloc (
sizeof (failover_message_t),
MDL);
403 status = ISC_R_NOMEMORY;
406 failover_message_dereference (&link->imsg,
409 link -> state = dhcp_flink_disconnected;
410 log_info (
"message length wait: %s",
411 isc_result_totext (status));
415 return ISC_R_UNEXPECTED;
417 memset (link -> imsg, 0,
sizeof (failover_message_t));
418 link -> imsg -> refcnt = 1;
421 link -> imsg_count = 0;
424 if (link->imsg_len < DHCP_FAILOVER_MIN_MESSAGE_SIZE ||
425 link->imsg_len > DHCP_FAILOVER_MAX_MESSAGE_SIZE) {
426 status = ISC_R_UNEXPECTED;
427 goto dhcp_flink_fail;
433 case dhcp_flink_message_wait:
443 link -> imsg_count += 2;
447 link -> imsg_count++;
451 link -> imsg_count++;
455 link -> imsg_count += 4;
459 link -> imsg_count += 4;
461 #if defined (DEBUG_FAILOVER_MESSAGES)
462 # if !defined(DEBUG_FAILOVER_CONTACT_MESSAGES)
463 if (link->imsg->type == FTM_CONTACT)
466 log_info (
"link: message %s payoff %d time %ld xid %ld",
469 (
unsigned long)link -> imsg -> time,
470 (
unsigned long)link -> imsg -> xid);
471 # if !defined(DEBUG_FAILOVER_CONTACT_MESSAGES)
477 if (link -> imsg_payoff - link -> imsg_count) {
479 (link -> imsg_payoff -
480 link -> imsg_count));
481 link -> imsg_count = link -> imsg_payoff;
485 while (link -> imsg_count < link -> imsg_len) {
486 status = do_a_failover_option (c, link);
487 if (status != ISC_R_SUCCESS)
488 goto dhcp_flink_fail;
494 if (link -> imsg -> type == FTM_CONNECT) {
498 if (!(link->imsg->options_present &
499 FTB_RELATIONSHIP_NAME)) {
500 errmsg =
"missing relationship-name";
501 reason = FTR_INVALID_PARTNER;
510 &link->imsg->relationship_name))
517 errmsg =
"unknown failover relationship name";
518 reason = FTR_INVALID_PARTNER;
526 slen = strlen(sname);
527 }
else if (link->imsg->options_present &
528 FTB_RELATIONSHIP_NAME) {
529 sname = (
char *)link->imsg->
530 relationship_name.data;
531 slen = link->imsg->relationship_name.count;
534 slen = strlen(sname);
537 log_error(
"Failover CONNECT from %.*s: %s",
538 slen, sname, errmsg);
542 log_info (
"failover: disconnect: %s", errmsg);
544 link -> state = dhcp_flink_disconnected;
545 return ISC_R_SUCCESS;
548 if ((
cur_time > link -> imsg -> time &&
549 cur_time - link -> imsg -> time > 60) ||
550 (cur_time < link -> imsg -> time &&
551 link -> imsg -> time -
cur_time > 60)) {
552 errmsg =
"time offset too large";
553 reason = FTR_TIMEMISMATCH;
557 if (!(link -> imsg -> options_present & FTB_HBA) ||
558 link -> imsg -> hba.count != 32) {
559 errmsg =
"invalid HBA";
560 reason = FTR_HBA_CONFLICT;
567 errmsg =
"no memory";
568 reason = FTR_MISC_REJECT;
571 memcpy (state -> hba, link -> imsg -> hba.data, 32);
573 if (!link -> state_object)
574 dhcp_failover_state_reference
575 (&link -> state_object, state,
MDL);
576 if (!link -> peer_address)
578 (&link -> peer_address,
579 state -> partner.address,
MDL);
585 if (!link -> state_object) {
586 log_info (
"failover: connect: no matching state.");
588 link -> state = dhcp_flink_disconnected;
596 link -> state = dhcp_flink_message_length_wait;
598 failover_message_dereference (&link -> imsg,
MDL);
612 return ISC_R_SUCCESS;
615 static isc_result_t do_a_failover_option (c, link)
617 dhcp_failover_link_t *link;
619 u_int16_t option_code;
620 u_int16_t option_len;
626 if (link -> imsg_count + 2 > link -> imsg_len) {
627 log_error (
"FAILOVER: message overflow at option code.");
631 if (link->imsg->type > FTM_MAX) {
632 log_error (
"FAILOVER: invalid message type: %d",
639 link -> imsg_count += 2;
641 if (link -> imsg_count + 2 > link -> imsg_len) {
642 log_error (
"FAILOVER: message overflow at length.");
648 link -> imsg_count += 2;
650 if (link -> imsg_count + option_len > link -> imsg_len) {
651 log_error (
"FAILOVER: message overflow at data.");
656 if ((option_code > FTO_MAX) ||
658 #if defined (DEBUG_FAILOVER_MESSAGES)
659 log_debug (
" option code %d (%s) len %d (not recognized)",
665 link -> imsg_count += option_len;
666 return ISC_R_SUCCESS;
670 if (
ft_options [option_code].type == FT_DIGEST) {
671 link -> imsg_count += option_len;
672 if (link -> imsg_count != link -> imsg_len) {
673 log_error (
"FAILOVER: digest not at end of message");
676 #if defined (DEBUG_FAILOVER_MESSAGES)
682 return ISC_R_SUCCESS;
686 if (link -> imsg -> options_present &
ft_options [option_code].bit) {
687 log_error (
"FAILOVER: duplicate option %s",
702 link -> imsg_count += option_len;
703 return ISC_R_SUCCESS;
713 op = ((
unsigned char *)link -> imsg) +
716 op_count = ft_options [option_code].num_present;
718 if (option_len != op_size * op_count) {
719 log_error (
"FAILOVER: option size (%d:%d), option %s",
721 (
ft_sizes [ft_options [option_code].type] *
722 ft_options [option_code].num_present),
723 ft_options [option_code].name);
727 failover_option_t *fo;
734 if (ft_options [option_code].type == FT_DDNS ||
735 ft_options [option_code].type == FT_DDNS1) {
738 (((
char *)link -> imsg) +
739 ft_options [option_code].offset));
741 op_count = (ft_options [option_code].type == FT_DDNS1
746 link -> imsg_count += op_count;
748 ddns -> codes [1] = 0;
750 op_count = option_len - op_count;
752 ddns -> length = op_count;
755 log_error (
"FAILOVER: no memory getting%s(%d)",
756 " DNS data ", op_count);
771 op_size =
ft_sizes [ft_options [option_code].type];
775 if (op_size > 1 && option_len % op_size) {
776 log_error (
"FAILOVER: option_len %d not %s%d",
777 option_len,
"multiple of ", op_size);
781 op_count = option_len / op_size;
783 fo = ((failover_option_t *)
784 (((
char *)link -> imsg) +
785 ft_options [option_code].offset));
787 fo -> count = op_count;
790 log_error (
"FAILOVER: no memory getting %s (%d)",
791 "option data", op_count);
800 if (op_size == 1 || ft_options [option_code].type == FT_IPADDR) {
802 link -> imsg_count += option_len;
825 if ((option_code == 11) && (option_len > 9) &&
826 (strncmp((
const char *)op,
"isc-V3.0.", 9) == 0)) {
827 log_error(
"WARNING: failover as of versions 3.1.0 and "
828 "on are not reverse compatible with "
837 for (i = 0; i < op_count; i++) {
838 switch (ft_options [option_code].type) {
842 link -> imsg_count += 4;
848 link -> imsg_count += 2;
854 log_error (
"FAILOVER: option %s: bad type %d",
855 ft_options [option_code].name,
856 ft_options [option_code].type);
862 link -> imsg -> options_present |= ft_options [option_code].bit;
863 return ISC_R_SUCCESS;
880 if (h -> inner && h -> inner -> type -> set_value)
881 return (*(h -> inner -> type -> set_value))
882 (h -> inner, id, name, value);
883 return ISC_R_NOTFOUND;
891 dhcp_failover_link_t *link;
895 link = (dhcp_failover_link_t *)h;
899 (
int)link -> peer_port,
MDL);
901 if (link -> state >= dhcp_flink_state_max)
903 "invalid link state",
910 if (h -> inner && h -> inner -> type -> get_value)
911 return (*(h -> inner -> type -> get_value))
912 (h -> inner, id, name, value);
913 return ISC_R_NOTFOUND;
917 const char *file,
int line)
919 dhcp_failover_link_t *link;
922 link = (dhcp_failover_link_t *)h;
924 if (link -> peer_address)
927 failover_message_dereference (&link -> imsg, file, line);
928 if (link -> state_object)
929 dhcp_failover_state_dereference (&link -> state_object,
931 return ISC_R_SUCCESS;
941 dhcp_failover_link_t *link;
946 link = (dhcp_failover_link_t *)l;
949 if (status != ISC_R_SUCCESS)
952 if (status != ISC_R_SUCCESS)
955 if (status != ISC_R_SUCCESS)
959 if (status != ISC_R_SUCCESS)
961 if (link -> state >= dhcp_flink_state_max)
966 if (status != ISC_R_SUCCESS)
969 if (link -> inner && link -> inner -> type -> stuff_values)
970 return (*(link -> inner -> type -> stuff_values)) (c,
id,
972 return ISC_R_SUCCESS;
987 "local-port", &value);
988 if (status != ISC_R_SUCCESS)
990 if (!value -> value) {
997 if (status != ISC_R_SUCCESS)
999 local_addr.
port = port;
1002 "local-address", &value);
1003 if (status != ISC_R_SUCCESS)
1005 if (!value -> value) {
1012 value -> value -> u.buffer.len != sizeof (
struct in_addr))
1015 memcpy (local_addr.
address, value -> value -> u.buffer.
value,
1016 value -> value -> u.buffer.len);
1017 local_addr.
addrlen = value -> value -> u.buffer.len;
1023 for (l = failover_listeners; l; l = l -> next) {
1024 if (l -> address.port == local_addr.
port &&
1025 l -> address.addrtype == local_addr.
addrtype &&
1026 l -> address.addrlen == local_addr.
addrlen &&
1027 !memcmp (l -> address.address, local_addr.
address,
1033 return ISC_R_SUCCESS;
1036 status = dhcp_failover_listener_allocate (&obj,
MDL);
1037 if (status != ISC_R_SUCCESS)
1039 obj -> address = local_addr;
1042 if (status != ISC_R_SUCCESS)
1047 if (status != ISC_R_SUCCESS) {
1048 dhcp_failover_listener_dereference (&obj,
MDL);
1052 if (status != ISC_R_SUCCESS) {
1053 dhcp_failover_listener_dereference (&obj,
MDL);
1058 if (failover_listeners) {
1059 dhcp_failover_listener_reference (&obj -> next,
1060 failover_listeners,
MDL);
1061 dhcp_failover_listener_dereference (&failover_listeners,
MDL);
1063 dhcp_failover_listener_reference (&failover_listeners, obj,
MDL);
1065 return dhcp_failover_listener_dereference (&obj,
MDL);
1072 const char *name, va_list ap)
1074 isc_result_t status;
1076 dhcp_failover_link_t *obj;
1078 dhcp_failover_state_t *s, *state = (dhcp_failover_state_t *)0;
1085 if (strcmp (name,
"connect")) {
1086 if (p -> inner && p -> inner -> type -> signal_handler)
1087 return (*(p -> inner -> type -> signal_handler))
1088 (p -> inner, name, ap);
1089 return ISC_R_NOTFOUND;
1100 (s, (u_int8_t *)&c -> remote_addr.sin_addr,
1101 sizeof c -> remote_addr.sin_addr)) {
1107 log_info (
"failover: listener: no matching state");
1109 return(ISC_R_NOTFOUND);
1112 obj = (dhcp_failover_link_t *)0;
1113 status = dhcp_failover_link_allocate (&obj,
MDL);
1114 if (status != ISC_R_SUCCESS)
1116 obj -> peer_port = ntohs (c -> remote_addr.sin_port);
1120 if (status != ISC_R_SUCCESS) {
1122 dhcp_failover_link_dereference (&obj,
MDL);
1123 log_info (
"failover: listener: picayune failure.");
1130 if (status != ISC_R_SUCCESS)
1133 status = dhcp_failover_state_reference (&obj -> state_object,
1135 if (status != ISC_R_SUCCESS)
1140 return dhcp_failover_link_dereference (&obj,
MDL);
1151 if (h -> inner && h -> inner -> type -> set_value)
1152 return (*(h -> inner -> type -> set_value))
1153 (h -> inner, id, name, value);
1154 return ISC_R_NOTFOUND;
1165 if (h -> inner && h -> inner -> type -> get_value)
1166 return (*(h -> inner -> type -> get_value))
1167 (h -> inner, id, name, value);
1168 return ISC_R_NOTFOUND;
1172 const char *file,
int line)
1180 dhcp_failover_listener_dereference (&l -> next, file, line);
1182 return ISC_R_SUCCESS;
1195 if (p -> inner && p -> inner -> type -> stuff_values)
1196 return (*(p -> inner -> type -> stuff_values)) (c, id,
1198 return ISC_R_SUCCESS;
1205 isc_result_t status;
1206 dhcp_failover_state_t *obj;
1211 "local-port", &value);
1212 if (status != ISC_R_SUCCESS)
1214 if (!value -> value) {
1221 if (status != ISC_R_SUCCESS)
1224 obj = (dhcp_failover_state_t *)0;
1225 dhcp_failover_state_allocate (&obj,
MDL);
1226 obj -> me.port = port;
1229 if (status != ISC_R_SUCCESS) {
1230 dhcp_failover_state_dereference (&obj,
MDL);
1236 if (status != ISC_R_SUCCESS) {
1237 dhcp_failover_state_dereference (&obj,
MDL);
1241 dhcp_failover_state_dereference (&obj,
MDL);
1248 const char *name, va_list ap)
1250 isc_result_t status;
1251 dhcp_failover_state_t *state;
1252 dhcp_failover_link_t *link;
1257 state = (dhcp_failover_state_t *)o;
1260 if (strcmp (name,
"disconnect") &&
1261 strcmp (name,
"message")) {
1262 if (state -> inner && state -> inner -> type -> signal_handler)
1263 return (*(state -> inner -> type -> signal_handler))
1264 (state -> inner, name, ap);
1265 return ISC_R_NOTFOUND;
1270 if (!strcmp (name,
"disconnect")) {
1271 link = va_arg (ap, dhcp_failover_link_t *);
1273 dhcp_failover_link_dereference (&state -> link_to_peer,
MDL);
1275 if (state -> i_am == primary) {
1276 #if defined (DEBUG_FAILOVER_TIMING)
1278 "dhcp_failover_reconnect");
1284 (
tvref_t)dhcp_failover_state_reference,
1286 dhcp_failover_state_dereference);
1288 }
else if (!strcmp (name,
"message")) {
1289 link = va_arg (ap, dhcp_failover_link_t *);
1291 if (link -> imsg -> type == FTM_CONNECT) {
1297 if (state -> link_to_peer) {
1301 "already connected");
1303 return ISC_R_SUCCESS;
1305 if (!(link -> imsg -> options_present & FTB_MCLT)) {
1309 "no MCLT provided");
1311 return ISC_R_SUCCESS;
1314 dhcp_failover_link_reference (&state -> link_to_peer,
1318 if (status != ISC_R_SUCCESS) {
1319 dhcp_failover_link_dereference
1320 (&state -> link_to_peer,
MDL);
1321 log_info (
"dhcp_failover_send_connectack: %s",
1322 isc_result_totext (status));
1324 return ISC_R_SUCCESS;
1326 if (link -> imsg -> options_present & FTB_MAX_UNACKED)
1327 state -> partner.max_flying_updates =
1328 link -> imsg -> max_unacked;
1329 if (link -> imsg -> options_present & FTB_RECEIVE_TIMER)
1330 state -> partner.max_response_delay =
1331 link -> imsg -> receive_timer;
1332 state -> mclt = link -> imsg -> mclt;
1336 }
else if (link -> imsg -> type == FTM_CONNECTACK) {
1344 if (!(link->imsg->options_present &
1345 FTB_RELATIONSHIP_NAME)) {
1346 errmsg =
"missing relationship-name";
1347 reason = FTR_INVALID_PARTNER;
1351 if (link->imsg->options_present & FTB_REJECT_REASON) {
1353 log_error (
"Failover CONNECT to %s rejected: %s",
1354 state ? state->name :
"unknown",
1356 (link -> imsg -> reject_reason)));
1359 return ISC_R_SUCCESS;
1363 &link->imsg->relationship_name)) {
1365 snprintf(errbuf,
sizeof(errbuf),
"remote failover "
1366 "relationship name %.*s does not match",
1367 (
int)link->imsg->relationship_name.count,
1368 link->imsg->relationship_name.data);
1370 reason = FTR_INVALID_PARTNER;
1372 log_error(
"Failover CONNECTACK from %s: %s",
1373 state->name, errmsg);
1377 return ISC_R_SUCCESS;
1380 if (state -> link_to_peer) {
1381 errmsg =
"already connected";
1382 reason = FTR_DUP_CONNECTION;
1386 if ((
cur_time > link -> imsg -> time &&
1387 cur_time - link -> imsg -> time > 60) ||
1388 (cur_time < link -> imsg -> time &&
1389 link -> imsg -> time -
cur_time > 60)) {
1390 errmsg =
"time offset too large";
1391 reason = FTR_TIMEMISMATCH;
1395 dhcp_failover_link_reference (&state -> link_to_peer,
1402 if (state -> me.state ==
startup)
1404 state -> saved_state);
1409 if (link -> imsg -> options_present & FTB_MAX_UNACKED)
1410 state -> partner.max_flying_updates =
1411 link -> imsg -> max_unacked;
1412 if (link -> imsg -> options_present & FTB_RECEIVE_TIMER)
1413 state -> partner.max_response_delay =
1414 link -> imsg -> receive_timer;
1415 #if defined (DEBUG_FAILOVER_CONTACT_TIMING)
1417 (
int)state -> partner.max_response_delay / 3,
1418 "dhcp_failover_send_contact");
1421 (
int)state -> partner.max_response_delay / 3;
1425 (
tvref_t)dhcp_failover_state_reference,
1426 (
tvunref_t)dhcp_failover_state_dereference);
1427 #if defined (DEBUG_FAILOVER_CONTACT_TIMING)
1429 (
int)state -> me.max_response_delay,
1430 "dhcp_failover_timeout");
1433 (
int)state -> me.max_response_delay;
1437 (
tvref_t)dhcp_failover_state_reference,
1438 (
tvunref_t)dhcp_failover_state_dereference);
1439 }
else if (link -> imsg -> type == FTM_DISCONNECT) {
1440 if (link -> imsg -> reject_reason) {
1441 log_error (
"Failover DISCONNECT from %s: %s",
1442 state ? state->name :
"unknown",
1444 (link -> imsg -> reject_reason)));
1447 }
else if (link -> imsg -> type == FTM_BNDUPD) {
1450 }
else if (link -> imsg -> type == FTM_BNDACK) {
1452 }
else if (link -> imsg -> type == FTM_UPDREQ) {
1455 }
else if (link -> imsg -> type == FTM_UPDREQALL) {
1457 (state, link -> imsg);
1458 }
else if (link -> imsg -> type == FTM_UPDDONE) {
1461 }
else if (link -> imsg -> type == FTM_POOLREQ) {
1462 dhcp_failover_pool_reqbalance(state);
1463 }
else if (link -> imsg -> type == FTM_POOLRESP) {
1464 log_info (
"pool response: %ld leases",
1466 link -> imsg -> addresses_transferred);
1467 }
else if (link -> imsg -> type == FTM_STATE) {
1476 if (state -> link_to_peer &&
1477 state -> link_to_peer == link &&
1478 state -> link_to_peer -> state != dhcp_flink_disconnected)
1480 #if defined (DEBUG_FAILOVER_CONTACT_TIMING)
1482 (
int)state -> me.max_response_delay,
1483 "dhcp_failover_timeout");
1486 (
int)state -> me.max_response_delay;
1490 (
tvref_t)dhcp_failover_state_reference,
1491 (
tvunref_t)dhcp_failover_state_dereference);
1497 return ISC_R_SUCCESS;
1503 isc_result_t status;
1506 if (!strcmp (name,
"disconnect")) {
1507 if (state -> link_to_peer) {
1508 log_info (
"peer %s: disconnected", state -> name);
1509 if (state -> link_to_peer -> state_object)
1510 dhcp_failover_state_dereference
1511 (&state -> link_to_peer -> state_object,
MDL);
1512 dhcp_failover_link_dereference (&state -> link_to_peer,
1519 switch (state -> me.state ==
startup ?
1520 state -> saved_state : state -> me.state) {
1542 if (state -> me.state ==
startup)
1544 (state, state -> saved_state));
1545 return ISC_R_SUCCESS;
1563 }
else if (!strcmp (name,
"connect")) {
1564 switch (state -> me.state) {
1591 }
else if (!strcmp (name,
"startup")) {
1593 return ISC_R_SUCCESS;
1594 }
else if (!strcmp (name,
"connect-timeout")) {
1595 switch (state -> me.state) {
1603 return ISC_R_SUCCESS;
1627 switch (state -> me.state) {
1630 state -> nrr =
" (my state unknown)";
1652 state -> nrr =
" (resolving conflicts)";
1657 state -> nrr =
" (recovering)";
1662 state -> nrr =
" (shut down)";
1667 state -> nrr =
" (paused)";
1672 state -> nrr =
" (recover wait)";
1677 state -> nrr =
" (recover done)";
1682 state -> nrr =
" (startup)";
1694 switch (state -> partner.state) {
1697 state -> nrr =
" (peer demands: recovering)";
1704 state -> nrr =
" (peer demands: resolving conflicts)";
1713 return ISC_R_SUCCESS;
1732 if (state->ack_queue_tail == NULL)
1736 for (lp = state->ack_queue_head; lp; lp = lp->
next_pending)
1740 if (state->update_queue_head) {
1741 lease_reference(&state->ack_queue_tail->next_pending,
1742 state->update_queue_head,
MDL);
1743 lease_dereference(&state->update_queue_head,
MDL);
1745 lease_reference(&state->update_queue_head, state->ack_queue_head,
MDL);
1747 if (!state->update_queue_tail) {
1748 #if defined (POINTER_DEBUG)
1749 if (state->ack_queue_tail->next_pending) {
1750 log_error(
"next pending on ack queue tail.");
1754 lease_reference(&state->update_queue_tail,
1755 state->ack_queue_tail,
MDL);
1757 lease_dereference(&state->ack_queue_tail,
MDL);
1758 lease_dereference(&state->ack_queue_head,
MDL);
1759 state->cur_unacked_updates = 0;
1778 switch (state -> me.state) {
1794 saved_state = state -> me.state;
1795 saved_stos = state -> me.stos;
1810 !state -> update_queue_head && !state -> ack_queue_head)
1811 state -> me.stos =
cur_time - state -> mclt;
1813 state -> me.state = new_state;
1815 state -> saved_state = saved_state;
1819 log_error (
"Unable to record current failover state for %s",
1821 state -> me.state = saved_state;
1822 state -> me.stos = saved_stos;
1823 return ISC_R_IOERROR;
1826 log_info (
"failover peer %s: I move from %s to %s",
1831 if ((state->me.state ==
normal) && (state->partner.state ==
normal))
1832 log_info(
"failover peer %s: Both servers normal", state->name);
1848 if (state -> link_to_peer)
1851 switch (new_state) {
1861 if (state->auto_partner_down == 0)
1864 #if defined (DEBUG_FAILOVER_TIMING)
1865 log_info(
"add_timeout +%lu dhcp_failover_auto_partner_down",
1866 (
unsigned long)state->auto_partner_down);
1868 tv.tv_sec =
cur_time + state->auto_partner_down;
1881 dhcp_failover_pool_balance(state);
1884 if (state->update_queue_tail != NULL) {
1886 log_info(
"Sending updates to %s.", state->name);
1892 if ((state->i_am == primary) ||
1893 ((state->i_am == secondary) &&
1899 #if defined (DEBUG_FAILOVER_TIMING)
1901 "dhcp_failover_startup_timeout");
1908 (
tvref_t)omapi_object_reference,
1916 if (state -> me.stos + state -> mclt >
cur_time) {
1917 #if defined (DEBUG_FAILOVER_TIMING)
1920 state -> me.stos + state -> mclt),
1921 "dhcp_failover_startup_timeout");
1923 tv . tv_sec = (
int)(state -> me.stos + state -> mclt);
1928 (
tvref_t)omapi_object_reference,
1940 if (state -> link_to_peer)
1947 for (p = s ->
pools; p; p = p -> next) {
1948 if (p -> failover_peer == state) {
1950 l->
tsfp = state->me.stos + state->mclt;
1958 #if defined (DEBUG_FAILOVER_TIMING)
1981 return ISC_R_SUCCESS;
1985 failover_message_t *msg)
1991 new_state = msg -> server_state;
1992 startupp = (msg -> server_flags & FTF_SERVER_STARTUP) ? 1 : 0;
1994 if (state -> partner.state == new_state && state -> me.state) {
1995 switch (state -> me.state) {
2008 state->saved_state);
2009 return ISC_R_SUCCESS;
2018 return ISC_R_SUCCESS;
2035 state -> partner.state = new_state;
2038 log_info (
"failover peer %s: peer moves from %s to %s",
2044 if ((state->me.state ==
normal) && (state->partner.state ==
normal))
2045 log_info(
"failover peer %s: Both servers normal", state->name);
2051 log_error (
"Unable to record current failover state for %s",
2058 switch (new_state) {
2075 log_error(
"failover peer %s: Invalid state: %d", state->name,
2078 return ISC_R_SUCCESS;
2084 switch (state -> me.state ==
startup ?
2085 state -> saved_state : state -> me.state) {
2087 switch (new_state) {
2093 if (state -> me.state ==
startup)
2104 log_error(
"Peer %s: Invalid state transition %s "
2105 "to %s.", state->name,
2130 switch (new_state) {
2132 log_info (
"failover peer %s: requesting %s",
2133 state -> name,
"full update from peer");
2137 if (state -> me.state ==
recover)
2163 if (state -> me.state ==
recover)
2184 switch (new_state) {
2187 log_error(
"Peer %s moves to normal during conflict "
2188 "resolution - panic, shutting down.",
2197 log_error(
"Peer %s: Unexpected move to "
2198 "conflict-done.", state->name);
2225 switch (new_state) {
2243 log_fatal(
"Peer %s: Invalid attempt to move from %s "
2244 "to %s while local state is conflict-done.",
2256 switch (new_state) {
2282 switch (new_state) {
2322 switch (new_state) {
2350 switch (new_state) {
2352 log_error(
"Both servers have entered recover-done!");
2393 if (state -> me.state ==
startup && state -> saved_state !=
startup)
2400 return ISC_R_SUCCESS;
2409 dhcp_failover_pool_balance(dhcp_failover_state_t *state)
2413 state->sched_balance = 0;
2415 dhcp_failover_pool_dobalance(state, NULL);
2426 dhcp_failover_state_t *state;
2427 isc_boolean_t sendreq = ISC_FALSE;
2429 state = (dhcp_failover_state_t *)failover_state;
2432 state->sched_balance = 0;
2434 if (dhcp_failover_pool_dobalance(state, &sendreq))
2446 dhcp_failover_pool_reqbalance(dhcp_failover_state_t *state)
2452 state->sched_balance = 0;
2454 queued = dhcp_failover_pool_dobalance(state, NULL);
2461 log_info(
"peer %s: Got POOLREQ, answering negatively! "
2462 "Peer may be out of leases or database inconsistent.",
2474 dhcp_failover_pool_dobalance(dhcp_failover_state_t *state,
2475 isc_boolean_t *sendreq)
2477 int lts, total, thresh, hold, panic, pass;
2478 int leases_queued = 0;
2487 int (*log_func)(
const char *, ...);
2488 const char *result, *reqlog;
2490 if (state -> me.state !=
normal)
2522 thresh = ((total * state->max_lease_misbalance) + 50) / 100;
2523 hold = ((total * state->max_lease_ownership) + 50) / 100;
2538 panic = thresh * -2;
2543 if ((sendreq != NULL) && (lts < panic)) {
2544 reqlog =
" (requesting peer rebalance!)";
2545 *sendreq = ISC_TRUE;
2549 log_info(
"balancing pool %lx %s total %d free %d "
2550 "backup %d lts %d max-own (+/-)%d%s",
2552 (p->shared_network ?
2554 p->free_leases, p->backup_leases, lts, hold,
2570 lease_reference(&lp, *lq,
MDL);
2574 lease_dereference(&next,
MDL);
2576 lease_reference(&next, lp->
next,
MDL);
2603 }
else if (lts <= -hold)
2619 lease_dereference(&lp,
MDL);
2621 lease_reference(&lp, next,
MDL);
2624 lease_reference(&lp, *lq,
MDL);
2629 lease_dereference(&next,
MDL);
2631 lease_dereference(&lp,
MDL);
2634 result =
"IMBALANCED";
2637 result =
"balanced";
2641 log_func(
"%s pool %lx %s total %d free %d backup %d "
2642 "lts %d max-misbal %d", result, (
unsigned long)p,
2643 (p->shared_network ?
2644 p->shared_network->name :
""), p->lease_count,
2645 p->free_leases, p->backup_leases, lts, thresh);
2657 return leases_queued;
2667 dhcp_failover_state_t *peer;
2673 if(!peer || peer->me.state !=
normal)
2700 est1 = ((est1 * peer->max_lease_misbalance) + 50) / 100;
2701 est2 = ((est2 * peer->max_lease_misbalance) + 50) / 100;
2706 if(peer->i_am == primary)
2716 if(est1 > peer->max_balance)
2717 est1 = peer->max_balance;
2723 est2 = peer->last_balance + peer->min_balance;
2724 if(peer->last_balance && (est1 < est2))
2728 est1 += random() % 5;
2731 if(peer->sched_balance) {
2732 if (est1 >= peer->sched_balance)
2742 peer->sched_balance = est1;
2744 #if defined(DEBUG_FAILOVER_TIMING)
2745 log_info(
"add_timeout +%d dhcp_failover_pool_rebalance",
2751 (
tvref_t)dhcp_failover_state_reference,
2752 (
tvunref_t)dhcp_failover_state_dereference);
2761 for (p = s ->
pools; p; p = p ->
next) {
2773 isc_result_t status;
2776 if (!state -> link_to_peer)
2777 return ISC_R_SUCCESS;
2782 if (state->toack_queue_head != NULL)
2785 while ((state -> partner.max_flying_updates >
2786 state -> cur_unacked_updates) && state -> update_queue_head) {
2788 lease_reference (&lp, state -> update_queue_head,
MDL);
2792 if (status != ISC_R_SUCCESS) {
2793 lease_dereference (&lp,
MDL);
2800 lease_dereference (&state -> update_queue_head,
MDL);
2802 lease_reference (&state -> update_queue_head,
2806 lease_dereference (&state -> update_queue_tail,
MDL);
2809 if (state -> ack_queue_head) {
2813 lease_dereference (&state -> ack_queue_tail,
MDL);
2815 lease_reference (&state -> ack_queue_head, lp,
MDL);
2817 #if defined (POINTER_DEBUG)
2819 log_error (
"ack_queue_tail: lp -> next_pending");
2823 lease_reference (&state -> ack_queue_tail, lp,
MDL);
2825 lease_dereference (&lp,
MDL);
2828 state -> cur_unacked_updates++;
2830 return ISC_R_SUCCESS;
2839 dhcp_failover_state_t *
state;
2841 if (!lease -> pool ||
2842 !lease -> pool -> failover_peer)
2850 state = lease -> pool -> failover_peer;
2856 if (state -> update_queue_head) {
2857 lease_reference (&state -> update_queue_tail ->
next_pending,
2859 lease_dereference (&state -> update_queue_tail,
MDL);
2861 lease_reference (&state -> update_queue_head, lease,
MDL);
2863 #if defined (POINTER_DEBUG)
2865 log_error (
"next pending on update queue lease.");
2866 #if defined (DEBUG_RC_HISTORY)
2867 dump_rc_history (lease);
2872 lease_reference (&state -> update_queue_tail, lease,
MDL);
2881 failover_message_t *msg = (failover_message_t *)0;
2887 while (state -> toack_queue_head) {
2888 failover_message_reference
2889 (&msg, state -> toack_queue_head,
MDL);
2890 failover_message_dereference
2891 (&state -> toack_queue_head,
MDL);
2893 failover_message_reference
2894 (&state -> toack_queue_head, msg -> next,
MDL);
2899 failover_message_dereference (&msg,
MDL);
2902 if (state -> toack_queue_tail)
2903 failover_message_dereference (&state -> toack_queue_tail,
MDL);
2904 state -> pending_acks = 0;
2911 dhcp_failover_state_t *state = vs;
2913 #if defined (DEBUG_FAILOVER_TIMING)
2914 log_info (
"dhcp_failover_toack_queue_timeout");
2924 failover_message_t *msg)
2928 if (state -> toack_queue_head) {
2929 failover_message_reference
2930 (&state -> toack_queue_tail -> next, msg,
MDL);
2931 failover_message_dereference (&state -> toack_queue_tail,
MDL);
2933 failover_message_reference (&state -> toack_queue_head,
2936 failover_message_reference (&state -> toack_queue_tail, msg,
MDL);
2938 state -> pending_acks++;
2942 if (state -> pending_acks >= state -> partner.max_flying_updates / 2) {
2947 if (state -> pending_acks > 0) {
2948 #if defined (DEBUG_FAILOVER_TIMING)
2950 "dhcp_failover_toack_queue_timeout");
2956 (
tvref_t)dhcp_failover_state_reference,
2957 (
tvunref_t)dhcp_failover_state_dereference);
2964 struct lease *lease)
2968 if (!(lease ->
flags & ON_ACK_QUEUE))
2971 if (state -> ack_queue_head == lease) {
2972 lease_dereference (&state -> ack_queue_head,
MDL);
2974 lease_reference (&state -> ack_queue_head,
2978 lease_dereference (&state -> ack_queue_tail,
MDL);
2981 for (lp = state -> ack_queue_head;
2995 lease_dereference (&state -> ack_queue_tail,
MDL);
3000 lease_reference (&state -> ack_queue_tail, lp,
MDL);
3004 lease ->
flags &= ~ON_ACK_QUEUE;
3011 state -> cur_unacked_updates--;
3018 if (state -> cur_unacked_updates == 0) {
3028 isc_result_t status;
3038 return ISC_R_SUCCESS;
3040 return ISC_R_SUCCESS;
3042 return ISC_R_SUCCESS;
3044 return ISC_R_SUCCESS;
3046 return ISC_R_SUCCESS;
3048 return ISC_R_SUCCESS;
3050 return ISC_R_SUCCESS;
3052 return ISC_R_SUCCESS;
3054 return ISC_R_SUCCESS;
3056 return ISC_R_SUCCESS;
3060 if (status != ISC_R_SUCCESS)
3064 return ISC_R_SUCCESS;
3066 return ISC_R_SUCCESS;
3068 return ISC_R_SUCCESS;
3070 return ISC_R_SUCCESS;
3072 return ISC_R_SUCCESS;
3074 return ISC_R_SUCCESS;
3076 return ISC_R_SUCCESS;
3078 return ISC_R_SUCCESS;
3081 if (h -> inner && h -> inner -> type -> set_value)
3082 return (*(h -> inner -> type -> set_value))
3083 (h -> inner, id, name, value);
3084 return ISC_R_NOTFOUND;
3093 dhcp_failover_state_t *state = vs;
3094 isc_result_t status;
3097 #if defined (DEBUG_FAILOVER_TIMING)
3098 log_info (
"dhcp_failover_reconnect");
3102 if (state -> link_to_peer)
3107 log_info (
"failover peer %s: %s", state -> name,
3108 isc_result_totext (status));
3109 #if defined (DEBUG_FAILOVER_TIMING)
3110 log_info(
"add_timeout +90 dhcp_failover_reconnect");
3115 (
tvref_t)dhcp_failover_state_reference,
3116 (
tvunref_t)dhcp_failover_state_dereference);
3122 dhcp_failover_state_t *state = vs;
3124 #if defined (DEBUG_FAILOVER_TIMING)
3125 log_info (
"dhcp_failover_startup_timeout");
3133 dhcp_failover_link_t *link = vl;
3138 for (; p; p = p -> outer)
3142 log_info (
"failover: link startup timeout");
3149 dhcp_failover_state_t *state = vs;
3150 isc_result_t status;
3153 #if defined (DEBUG_FAILOVER_TIMING)
3154 log_info (
"dhcp_failover_listener_restart");
3158 if (status != ISC_R_SUCCESS) {
3159 log_info (
"failover peer %s: %s", state -> name,
3160 isc_result_totext (status));
3161 #if defined (DEBUG_FAILOVER_TIMING)
3163 "dhcp_failover_listener_restart");
3169 (
tvref_t)dhcp_failover_state_reference,
3170 (
tvunref_t)dhcp_failover_state_dereference);
3177 dhcp_failover_state_t *state = vs;
3179 #if defined (DEBUG_FAILOVER_TIMING)
3180 log_info(
"dhcp_failover_auto_partner_down");
3191 dhcp_failover_state_t *s;
3194 isc_result_t status;
3198 s = (dhcp_failover_state_t *)h;
3203 name, s -> name,
MDL);
3204 return ISC_R_NOTFOUND;
3206 oc = s -> partner.address;
3208 memset (&ds, 0,
sizeof ds);
3215 return ISC_R_NOTFOUND;
3218 name, ds.data, ds.
len,
MDL);
3225 oc = s -> me.address;
3229 s -> partner.port,
MDL);
3232 name, s -> me.port,
MDL);
3235 s -> me.max_flying_updates,
3241 s -> load_balance_max_secs,
MDL);
3246 return ISC_R_NOTFOUND;
3249 s -> partner.state,
MDL);
3252 s -> me.state,
MDL);
3255 s -> partner.stos,
MDL);
3263 s -> last_packet_sent,
MDL);
3266 s -> last_timestamp_received,
3272 s -> me.max_response_delay,
3276 s -> cur_unacked_updates,
MDL);
3279 if (h -> inner && h -> inner -> type -> get_value)
3280 return (*(h -> inner -> type -> get_value))
3281 (h -> inner, id, name, value);
3282 return ISC_R_NOTFOUND;
3286 const char *file,
int line)
3288 dhcp_failover_state_t *s;
3292 s = (dhcp_failover_state_t *)h;
3294 if (s -> link_to_peer)
3295 dhcp_failover_link_dereference (&s -> link_to_peer, file, line);
3298 s -> name = (
char *)0;
3300 if (s -> partner.address)
3302 if (s -> me.address)
3305 dfree (s -> hba, file, line);
3306 s -> hba = (u_int8_t *)0;
3308 if (s -> update_queue_head)
3309 lease_dereference (&s -> update_queue_head, file, line);
3310 if (s -> update_queue_tail)
3311 lease_dereference (&s -> update_queue_tail, file, line);
3312 if (s -> ack_queue_head)
3313 lease_dereference (&s -> ack_queue_head, file, line);
3314 if (s -> ack_queue_tail)
3315 lease_dereference (&s -> ack_queue_tail, file, line);
3316 if (s -> send_update_done)
3317 lease_dereference (&s -> send_update_done, file, line);
3318 if (s -> toack_queue_head)
3319 failover_message_dereference (&s -> toack_queue_head,
3321 if (s -> toack_queue_tail)
3322 failover_message_dereference (&s -> toack_queue_tail,
3324 return ISC_R_SUCCESS;
3336 dhcp_failover_state_t *s;
3337 isc_result_t status;
3344 s = (dhcp_failover_state_t *)h;
3347 if (status != ISC_R_SUCCESS)
3350 if (status != ISC_R_SUCCESS)
3354 if (status != ISC_R_SUCCESS)
3357 if (status != ISC_R_SUCCESS)
3360 sizeof s -> partner.address);
3361 if (status != ISC_R_SUCCESS)
3365 if (status != ISC_R_SUCCESS)
3368 if (status != ISC_R_SUCCESS)
3371 if (status != ISC_R_SUCCESS)
3375 if (status != ISC_R_SUCCESS)
3378 if (status != ISC_R_SUCCESS)
3381 sizeof s -> me.address);
3382 if (status != ISC_R_SUCCESS)
3386 if (status != ISC_R_SUCCESS)
3389 if (status != ISC_R_SUCCESS)
3392 if (status != ISC_R_SUCCESS)
3396 if (status != ISC_R_SUCCESS)
3399 if (status != ISC_R_SUCCESS)
3402 s -> me.max_flying_updates);
3403 if (status != ISC_R_SUCCESS)
3407 if (status != ISC_R_SUCCESS)
3410 if (status != ISC_R_SUCCESS)
3413 if (status != ISC_R_SUCCESS)
3417 if (status != ISC_R_SUCCESS)
3420 if (status != ISC_R_SUCCESS)
3423 (c, (u_int32_t)s -> load_balance_max_secs));
3424 if (status != ISC_R_SUCCESS)
3430 if (status != ISC_R_SUCCESS)
3433 if (status != ISC_R_SUCCESS)
3436 if (status != ISC_R_SUCCESS)
3441 if (status != ISC_R_SUCCESS)
3444 if (status != ISC_R_SUCCESS)
3447 if (status != ISC_R_SUCCESS)
3451 if (status != ISC_R_SUCCESS)
3454 if (status != ISC_R_SUCCESS)
3457 if (status != ISC_R_SUCCESS)
3461 if (status != ISC_R_SUCCESS)
3464 if (status != ISC_R_SUCCESS)
3467 (u_int32_t)s -> partner.stos);
3468 if (status != ISC_R_SUCCESS)
3472 if (status != ISC_R_SUCCESS)
3475 if (status != ISC_R_SUCCESS)
3478 if (status != ISC_R_SUCCESS)
3482 if (status != ISC_R_SUCCESS)
3485 if (status != ISC_R_SUCCESS)
3488 if (status != ISC_R_SUCCESS)
3492 if (status != ISC_R_SUCCESS)
3495 if (status != ISC_R_SUCCESS)
3498 (c, (u_int32_t)s -> last_packet_sent));
3499 if (status != ISC_R_SUCCESS)
3503 if (status != ISC_R_SUCCESS)
3506 if (status != ISC_R_SUCCESS)
3509 (c, (u_int32_t)s -> last_timestamp_received));
3510 if (status != ISC_R_SUCCESS)
3514 if (status != ISC_R_SUCCESS)
3517 if (status != ISC_R_SUCCESS)
3520 if (status != ISC_R_SUCCESS)
3524 if (status != ISC_R_SUCCESS)
3527 if (status != ISC_R_SUCCESS)
3530 (c, (u_int32_t)s -> me.max_response_delay));
3531 if (status != ISC_R_SUCCESS)
3535 if (status != ISC_R_SUCCESS)
3538 if (status != ISC_R_SUCCESS)
3541 (c, (u_int32_t)s -> cur_unacked_updates));
3542 if (status != ISC_R_SUCCESS)
3545 if (h -> inner && h -> inner -> type -> stuff_values)
3546 return (*(h -> inner -> type -> stuff_values)) (c,
id,
3548 return ISC_R_SUCCESS;
3556 isc_result_t status;
3557 dhcp_failover_state_t *s;
3564 if (status == ISC_R_SUCCESS) {
3568 if (status != ISC_R_SUCCESS)
3580 if (status == ISC_R_SUCCESS) {
3582 unsigned l = strlen (s -> name);
3583 if (l == tv -> value -> u.buffer.len &&
3585 tv -> value -> u.buffer.
value, l))
3598 return ISC_R_NOTFOUND;
3609 return ISC_R_SUCCESS;
3615 return ISC_R_NOTIMPLEMENTED;
3621 return ISC_R_NOTIMPLEMENTED;
3625 u_int8_t *addr,
unsigned addrlen)
3630 memset (&ds, 0,
sizeof ds);
3637 state -> partner.address,
MDL)) {
3638 for (i = 0; i + addrlen - 1 < ds.len; i += addrlen) {
3639 if (!memcmp (&ds.data [i],
3652 dhcp_failover_state_t *state;
3653 failover_option_t *name;
3655 if ((strlen(state->name) == name->count) &&
3656 (memcmp(state->name, name->data, name->count) == 0))
3664 static char resbuf[
sizeof(
"Undefined-255: This reason code is not defined "
3665 "in the protocol standard.")];
3667 if ((reason > 0xff) || (reason < 0))
3668 return "Reason code out of range.";
3671 case FTR_ILLEGAL_IP_ADDR:
3672 return "Illegal IP address (not part of any address pool).";
3674 case FTR_FATAL_CONFLICT:
3675 return "Fatal conflict exists: address in use by other client.";
3677 case FTR_MISSING_BINDINFO:
3678 return "Missing binding information.";
3680 case FTR_TIMEMISMATCH:
3681 return "Connection rejected, time mismatch too great.";
3683 case FTR_INVALID_MCLT:
3684 return "Connection rejected, invalid MCLT.";
3686 case FTR_MISC_REJECT:
3687 return "Connection rejected, unknown reason.";
3689 case FTR_DUP_CONNECTION:
3690 return "Connection rejected, duplicate connection.";
3692 case FTR_INVALID_PARTNER:
3693 return "Connection rejected, invalid failover partner.";
3695 case FTR_TLS_UNSUPPORTED:
3696 return "TLS not supported.";
3698 case FTR_TLS_UNCONFIGURED:
3699 return "TLS supported but not configured.";
3701 case FTR_TLS_REQUIRED:
3702 return "TLS required but not supported by partner.";
3704 case FTR_DIGEST_UNSUPPORTED:
3705 return "Message digest not supported.";
3707 case FTR_DIGEST_UNCONFIGURED:
3708 return "Message digest not configured.";
3710 case FTR_VERSION_MISMATCH:
3711 return "Protocol version mismatch.";
3713 case FTR_OUTDATED_BIND_INFO:
3714 return "Outdated binding information.";
3716 case FTR_LESS_CRIT_BIND_INFO:
3717 return "Less critical binding information.";
3719 case FTR_NO_TRAFFIC:
3720 return "No traffic within sufficient time.";
3722 case FTR_HBA_CONFLICT:
3723 return "Hash bucket assignment conflict.";
3725 case FTR_IP_NOT_RESERVED:
3726 return "IP not reserved on this server.";
3728 case FTR_IP_DIGEST_FAILURE:
3729 return "Message digest failed to compare.";
3731 case FTR_IP_MISSING_DIGEST:
3732 return "Missing message digest.";
3735 return "Unknown Error.";
3738 sprintf(resbuf,
"Undefined-%d: This reason code is not defined in the "
3739 "protocol standard.", reason);
3749 return "unknown-state";
3752 return "partner-down";
3758 return "conflict-done";
3761 return "communications-interrupted";
3764 return "resolution-interrupted";
3767 return "potential-conflict";
3773 return "recover-done";
3776 return "recover-wait";
3791 static char messbuf[
sizeof(
"unknown-message-255")];
3794 return "invalid-message";
3798 return "pool-request";
3801 return "pool-response";
3804 return "bind-update";
3812 case FTM_CONNECTACK:
3813 return "connect-ack";
3816 return "update-request";
3819 return "update-done";
3822 return "update-request-all";
3830 case FTM_DISCONNECT:
3831 return "disconnect";
3834 sprintf(messbuf,
"unknown-message-%u", type);
3841 static char optbuf[
sizeof(
"unknown-option-65535")];
3844 return "invalid-option";
3847 case FTO_ADDRESSES_TRANSFERRED:
3848 return "addresses-transferred";
3850 case FTO_ASSIGNED_IP_ADDRESS:
3851 return "assigned-ip-address";
3853 case FTO_BINDING_STATUS:
3854 return "binding-status";
3856 case FTO_CLIENT_IDENTIFIER:
3857 return "client-identifier";
3868 case FTO_DELAYED_SERVICE:
3869 return "delayed-service";
3877 case FTO_LEASE_EXPIRY:
3878 return "lease-expiry";
3880 case FTO_MAX_UNACKED:
3881 return "max-unacked";
3889 case FTO_MESSAGE_DIGEST:
3890 return "message-digest";
3892 case FTO_POTENTIAL_EXPIRY:
3893 return "potential-expiry";
3895 case FTO_PROTOCOL_VERSION:
3896 return "protocol-version";
3898 case FTO_RECEIVE_TIMER:
3899 return "receive-timer";
3901 case FTO_REJECT_REASON:
3902 return "reject-reason";
3904 case FTO_RELATIONSHIP_NAME:
3905 return "relationship-name";
3907 case FTO_REPLY_OPTIONS:
3908 return "reply-options";
3910 case FTO_REQUEST_OPTIONS:
3911 return "request-options";
3913 case FTO_SERVER_FLAGS:
3914 return "server-flags";
3916 case FTO_SERVER_STATE:
3917 return "server-state";
3925 case FTO_TLS_REQUEST:
3926 return "tls-request";
3928 case FTO_VENDOR_CLASS:
3929 return "vendor-class";
3931 case FTO_VENDOR_OPTIONS:
3932 return "vendor-options";
3935 sprintf(optbuf,
"unknown-option-%u", type);
3944 const char *fmt, ...)
3957 if (vsnprintf (tbuf,
sizeof tbuf, fmt, va) >=
sizeof tbuf)
3958 log_fatal (
"%s: vsnprintf would truncate",
3959 "dhcp_failover_make_option");
3963 strlen (tbuf), tbuf);
3967 char *obuf,
unsigned *obufix,
3968 unsigned obufmax, ...)
3971 struct failover_option_info *info;
3973 unsigned size, count;
3979 #if defined (DEBUG_FAILOVER_MESSAGES)
3987 failover_option_t
option, *op;
3991 if (code < 1 || code > FTO_MAX || ft_options [code].type == FT_UNDEF) {
3994 info = &ft_options [code];
3996 va_start (va, obufmax);
4000 if (info -> type == FT_DDNS || info -> type == FT_DDNS1) {
4001 count = info -> type == FT_DDNS ? 1 : 2;
4002 size = va_arg (va,
int) + count;
4005 if (info -> num_present)
4006 count = info -> num_present;
4008 count = va_arg (va,
int);
4011 switch (info -> type) {
4018 case FT_TEXT_OR_BYTES:
4020 txt = va_arg (va,
char *);
4025 ilen = va_arg (va,
unsigned);
4026 size = count * ilen;
4039 log_fatal (
"bogus type in failover_make_option: %d",
4048 option.count = size;
4059 #if defined (DEBUG_FAILOVER_MESSAGES)
4067 if (snprintf (tbuf,
sizeof tbuf,
" (%s<%d>", info -> name,
4068 option.count) >=
sizeof tbuf)
4069 log_fatal (
"dhcp_failover_make_option: tbuf overflow");
4074 switch (info -> type) {
4076 for (i = 0; i < count; i++) {
4077 val = va_arg (va,
unsigned);
4078 #if defined (DEBUG_FAILOVER_MESSAGES)
4080 sprintf (tbuf,
" %d", val);
4083 option.data [i + 4] = val;
4088 for (i = 0; i < count; i++) {
4089 iaddr = va_arg (va, u_int8_t *);
4092 log_error (
"IP addrlen=%d, should be 4.",
4098 #if defined (DEBUG_FAILOVER_MESSAGES)
4100 sprintf (tbuf,
" %u.%u.%u.%u",
4101 iaddr [0], iaddr [1], iaddr [2], iaddr [3]);
4104 memcpy (&option.data [4 + i * ilen], iaddr, ilen);
4109 for (i = 0; i < count; i++) {
4110 val = va_arg (va,
unsigned);
4111 #if defined (DEBUG_FAILOVER_MESSAGES)
4113 sprintf (tbuf,
" %d", val);
4116 putULong (&option.data [4 + i * 4], val);
4122 bval = va_arg (va, u_int8_t *);
4123 #if defined (DEBUG_FAILOVER_MESSAGES)
4124 for (i = 0; i < count; i++) {
4126 sprintf (tbuf,
" %d", bval [i]);
4130 memcpy (&option.data [4], bval, count);
4137 case FT_TEXT_OR_BYTES:
4139 #if defined (DEBUG_FAILOVER_MESSAGES)
4147 if (snprintf (tbuf,
sizeof tbuf,
"\"%s\"", txt) >=
sizeof tbuf)
4148 log_fatal (
"dhcp_failover_make_option: tbuf overflow");
4151 memcpy (&option.data [4], txt, count);
4156 option.data [4] = va_arg (va,
unsigned);
4158 option.data [5] = va_arg (va,
unsigned);
4159 bval = va_arg (va, u_int8_t *);
4160 memcpy (&option.data [4 + count], bval, size - count - 4);
4161 #if defined (DEBUG_FAILOVER_MESSAGES)
4162 for (i = 4; i < size; i++) {
4164 sprintf (tbuf,
" %d", option.data [i]);
4171 for (i = 0; i < count; i++) {
4172 val = va_arg (va, u_int32_t);
4173 #if defined (DEBUG_FAILOVER_MESSAGES)
4175 sprintf (tbuf,
" %d", val);
4178 putUShort (&option.data [4 + i * 2], val);
4187 #if defined DEBUG_FAILOVER_MESSAGES
4193 op =
dmalloc (
sizeof (failover_option_t),
MDL);
4207 int msg_type, u_int32_t xid, ...)
4213 failover_option_t *option;
4214 unsigned char *opbuf;
4215 isc_result_t status = ISC_R_SUCCESS;
4221 va_start (list, xid);
4222 while ((option = va_arg (list, failover_option_t *))) {
4224 size += option -> count;
4231 if (!bad_option && size) {
4234 status = ISC_R_NOMEMORY;
4236 opbuf = (
unsigned char *)0;
4238 va_start (list, xid);
4239 while ((option = va_arg (list, failover_option_t *))) {
4242 if (!bad_option && opbuf)
4243 memcpy (&opbuf [opix],
4244 option -> data, option -> count);
4247 opix += option -> count;
4261 if (status != ISC_R_SUCCESS)
4267 if (status != ISC_R_SUCCESS)
4273 if (status != ISC_R_SUCCESS)
4278 if (status != ISC_R_SUCCESS)
4283 if (status != ISC_R_SUCCESS)
4289 if (status != ISC_R_SUCCESS)
4293 if (link -> state_object &&
4294 link -> state_object -> link_to_peer == link) {
4295 #if defined (DEBUG_FAILOVER_CONTACT_TIMING)
4297 (
int)(link -> state_object ->
4298 partner.max_response_delay) / 3,
4299 "dhcp_failover_send_contact");
4302 (
int)(link -> state_object ->
4303 partner.max_response_delay) / 3;
4307 (
tvref_t)dhcp_failover_state_reference,
4308 (
tvunref_t)dhcp_failover_state_dereference);
4315 log_info (
"dhcp_failover_put_message: something went wrong.");
4322 dhcp_failover_state_t *state = vstate;
4323 dhcp_failover_link_t *link;
4325 #if defined (DEBUG_FAILOVER_TIMING)
4326 log_info (
"dhcp_failover_timeout");
4331 link = state -> link_to_peer;
4337 log_error (
"timeout waiting for failover peer %s", state -> name);
4346 dhcp_failover_state_t *state = vstate;
4347 dhcp_failover_link_t *link;
4348 isc_result_t status;
4350 #if defined(DEBUG_FAILOVER_MESSAGES) && \
4351 defined(DEBUG_FAILOVER_CONTACT_MESSAGES)
4353 unsigned obufix = 0;
4358 #if defined (DEBUG_FAILOVER_CONTACT_TIMING)
4359 log_info (
"dhcp_failover_send_contact");
4364 link = state -> link_to_peer;
4371 (link, link -> outer,
4372 FTM_CONTACT, link->xid++,
4373 (failover_option_t *)0));
4375 #if defined(DEBUG_FAILOVER_MESSAGES) && \
4376 defined(DEBUG_FAILOVER_CONTACT_MESSAGES)
4377 if (status != ISC_R_SUCCESS)
4391 dhcp_failover_link_t *link;
4392 isc_result_t status;
4394 #if defined (DEBUG_FAILOVER_MESSAGES)
4396 unsigned obufix = 0;
4398 # define FMA obuf, &obufix, sizeof obuf
4401 # define FMA (char *)0, (unsigned *)0, 0
4406 link = state -> link_to_peer;
4413 (link, link -> outer,
4414 FTM_STATE, link->xid++,
4417 ? state -> saved_state
4418 : state -> me.state)),
4420 (FTO_SERVER_FLAGS, FMA,
4422 ? FTF_SERVER_STARTUP : 0)),
4424 (failover_option_t *)0));
4426 #if defined (DEBUG_FAILOVER_MESSAGES)
4427 if (status != ISC_R_SUCCESS)
4436 return ISC_R_SUCCESS;
4443 dhcp_failover_link_t *link;
4444 dhcp_failover_state_t *state;
4445 isc_result_t status;
4446 #if defined (DEBUG_FAILOVER_MESSAGES)
4448 unsigned obufix = 0;
4450 # define FMA obuf, &obufix, sizeof obuf
4453 # define FMA (char *)0, (unsigned *)0, 0
4458 link = (dhcp_failover_link_t *)l;
4459 state = link -> state_object;
4466 FTM_CONNECT, link->xid++,
4468 strlen(state->name), state->name),
4470 state -> me.max_flying_updates),
4472 state -> me.max_response_delay),
4476 DHCP_FAILOVER_VERSION),
4484 (failover_option_t *)0));
4486 #if defined (DEBUG_FAILOVER_MESSAGES)
4487 if (status != ISC_R_SUCCESS)
4498 dhcp_failover_state_t *state,
4499 int reason,
const char *errmsg)
4501 dhcp_failover_link_t *link;
4502 isc_result_t status;
4503 #if defined (DEBUG_FAILOVER_MESSAGES)
4505 unsigned obufix = 0;
4507 # define FMA obuf, &obufix, sizeof obuf
4510 # define FMA (char *)0, (unsigned *)0, 0
4515 link = (dhcp_failover_link_t *)l;
4522 FTM_CONNECTACK, link->imsg->xid,
4525 strlen(state->name), state->name)
4526 : (link->imsg->options_present & FTB_RELATIONSHIP_NAME)
4528 link->imsg->relationship_name.count,
4529 link->imsg->relationship_name.data)
4530 : &skip_failover_option,
4533 state -> me.max_flying_updates)
4534 : &skip_failover_option,
4537 state -> me.max_response_delay)
4538 : &skip_failover_option,
4542 DHCP_FAILOVER_VERSION),
4543 (link->imsg->options_present & FTB_TLS_REQUEST)
4546 : &skip_failover_option,
4550 : &skip_failover_option,
4553 strlen (errmsg), errmsg)
4554 : &skip_failover_option,
4555 (failover_option_t *)0));
4557 #if defined (DEBUG_FAILOVER_MESSAGES)
4558 if (status != ISC_R_SUCCESS)
4570 const char *message)
4572 dhcp_failover_link_t *link;
4573 isc_result_t status;
4574 #if defined (DEBUG_FAILOVER_MESSAGES)
4576 unsigned obufix = 0;
4578 # define FMA obuf, &obufix, sizeof obuf
4581 # define FMA (char *)0, (unsigned *)0, 0
4586 link = (dhcp_failover_link_t *)l;
4590 if (!message && reason)
4595 FTM_DISCONNECT, link->xid++,
4600 strlen (message), message)
4601 : &skip_failover_option),
4602 (failover_option_t *)0));
4604 #if defined (DEBUG_FAILOVER_MESSAGES)
4605 if (status != ISC_R_SUCCESS)
4618 struct lease *lease)
4620 dhcp_failover_link_t *link;
4621 isc_result_t status;
4624 #if defined (DEBUG_FAILOVER_MESSAGES)
4626 unsigned obufix = 0;
4628 # define FMA obuf, &obufix, sizeof obuf
4631 # define FMA (char *)0, (unsigned *)0, 0
4634 if (!state -> link_to_peer ||
4637 link = (dhcp_failover_link_t *)state -> link_to_peer;
4649 if ((state->i_am == primary) && (transmit_state ==
FTS_FREE))
4651 else if ((state->i_am == secondary) &&
4655 flags |= FTF_IP_FLAG_RESERVE;
4658 flags |= FTF_IP_FLAG_BOOTP;
4698 (link, link -> outer,
4704 lease -> desired_binding_state),
4709 : &skip_failover_option,
4710 lease -> hardware_addr.hlen
4712 lease -> hardware_addr.hlen,
4713 lease -> hardware_addr.hbuf)
4714 : &skip_failover_option,
4721 (lease->
cltt != 0) ?
4723 &skip_failover_option,
4726 &skip_failover_option,
4727 &skip_failover_option,
4728 &skip_failover_option,
4729 &skip_failover_option,
4730 (failover_option_t *)0));
4732 #if defined (DEBUG_FAILOVER_MESSAGES)
4733 if (status != ISC_R_SUCCESS)
4746 failover_message_t *msg,
4747 int reason,
const char *message)
4749 dhcp_failover_link_t *link;
4750 isc_result_t status;
4751 #if defined (DEBUG_FAILOVER_MESSAGES)
4753 unsigned obufix = 0;
4755 # define FMA obuf, &obufix, sizeof obuf
4758 # define FMA (char *)0, (unsigned *)0, 0
4761 if (!state -> link_to_peer ||
4764 link = (dhcp_failover_link_t *)state -> link_to_peer;
4769 if (!message && reason)
4774 (link, link -> outer,
4775 FTM_BNDACK, msg->xid,
4777 sizeof msg -> assigned_addr,
4778 &msg -> assigned_addr),
4779 #ifdef DO_BNDACK_SHOULD_NOT
4781 msg -> binding_status),
4782 (msg -> options_present & FTB_CLIENT_IDENTIFIER)
4784 msg -> client_identifier.count,
4785 msg -> client_identifier.data)
4786 : &skip_failover_option,
4787 (msg -> options_present & FTB_CHADDR)
4789 msg -> chaddr.count,
4791 : &skip_failover_option,
4795 msg -> potential_expiry),
4798 (msg->options_present & FTB_CLTT) ?
4800 &skip_failover_option,
4801 ((msg->options_present & FTB_IP_FLAGS) && msg->ip_flags) ?
4804 : &skip_failover_option,
4808 : &skip_failover_option,
4811 strlen (message), message)
4812 : &skip_failover_option,
4813 #ifdef DO_BNDACK_SHOULD_NOT
4814 &skip_failover_option,
4815 &skip_failover_option,
4816 &skip_failover_option,
4818 (failover_option_t *)0));
4820 #if defined (DEBUG_FAILOVER_MESSAGES)
4821 if (status != ISC_R_SUCCESS)
4833 dhcp_failover_link_t *link;
4834 isc_result_t status;
4835 #if defined (DEBUG_FAILOVER_MESSAGES)
4837 unsigned obufix = 0;
4839 # define FMA obuf, &obufix, sizeof obuf
4842 # define FMA (char *)0, (unsigned *)0, 0
4845 if (!state -> link_to_peer ||
4848 link = (dhcp_failover_link_t *)state -> link_to_peer;
4854 (link, link -> outer,
4855 FTM_POOLREQ, link->xid++,
4856 (failover_option_t *)0));
4858 #if defined (DEBUG_FAILOVER_MESSAGES)
4859 if (status != ISC_R_SUCCESS)
4872 dhcp_failover_link_t *link;
4873 isc_result_t status;
4874 #if defined (DEBUG_FAILOVER_MESSAGES)
4876 unsigned obufix = 0;
4878 # define FMA obuf, &obufix, sizeof obuf
4881 # define FMA (char *)0, (unsigned *)0, 0
4884 if (!state -> link_to_peer ||
4887 link = (dhcp_failover_link_t *)state -> link_to_peer;
4893 (link, link -> outer,
4894 FTM_POOLRESP, link->imsg->xid,
4897 (failover_option_t *)0));
4899 #if defined (DEBUG_FAILOVER_MESSAGES)
4900 if (status != ISC_R_SUCCESS)
4912 dhcp_failover_link_t *link;
4913 isc_result_t status;
4914 #if defined (DEBUG_FAILOVER_MESSAGES)
4916 unsigned obufix = 0;
4918 # define FMA obuf, &obufix, sizeof obuf
4921 # define FMA (char *)0, (unsigned *)0, 0
4924 if (!state->link_to_peer ||
4927 link = (dhcp_failover_link_t *)state->link_to_peer;
4935 if (state->curUPD == FTM_UPDREQALL) {
4940 link->xid++, NULL));
4942 state->curUPD = FTM_UPDREQ;
4944 #if defined (DEBUG_FAILOVER_MESSAGES)
4945 if (status != ISC_R_SUCCESS)
4953 if (status == ISC_R_SUCCESS) {
4954 log_info(
"Sent update request message to %s", state->name);
4956 log_error(
"Failed to send update request all message to %s: %s",
4957 state->name, isc_result_totext(status));
4965 dhcp_failover_link_t *link;
4966 isc_result_t status;
4967 #if defined (DEBUG_FAILOVER_MESSAGES)
4969 unsigned obufix = 0;
4971 # define FMA obuf, &obufix, sizeof obuf
4974 # define FMA (char *)0, (unsigned *)0, 0
4977 if (!state->link_to_peer ||
4980 link = (dhcp_failover_link_t *)state->link_to_peer;
4990 link->xid++, NULL));
4992 state->curUPD = FTM_UPDREQALL;
4994 #if defined (DEBUG_FAILOVER_MESSAGES)
4995 if (status != ISC_R_SUCCESS)
5003 if (status == ISC_R_SUCCESS) {
5004 log_info(
"Sent update request all message to %s", state->name);
5006 log_error(
"Failed to send update request all message to %s: %s",
5007 state->name, isc_result_totext(status));
5014 dhcp_failover_link_t *link;
5015 isc_result_t status;
5016 #if defined (DEBUG_FAILOVER_MESSAGES)
5018 unsigned obufix = 0;
5020 # define FMA obuf, &obufix, sizeof obuf
5023 # define FMA (char *)0, (unsigned *)0, 0
5026 if (!state -> link_to_peer ||
5029 link = (dhcp_failover_link_t *)state -> link_to_peer;
5035 (link, link -> outer,
5036 FTM_UPDDONE, state->updxid,
5037 (failover_option_t *)0));
5039 #if defined (DEBUG_FAILOVER_MESSAGES)
5040 if (status != ISC_R_SUCCESS)
5048 log_info (
"Sent update done message to %s", state -> name);
5072 static isc_boolean_t
5073 failover_lease_is_better(dhcp_failover_state_t *state,
struct lease *lease,
5074 failover_message_t *msg)
5084 if ((msg->options_present & FTB_CLTT) != 0)
5085 msg_cltt = msg->cltt;
5089 switch(local_state) {
5092 if (msg_cltt < lease->cltt)
5094 else if (msg_cltt > lease->
cltt)
5096 else if (state->i_am == primary)
5113 else if (state->i_am == primary)
5129 failover_message_t *msg)
5131 struct lease *lt = NULL, *lease = NULL;
5133 int reason = FTR_MISC_REJECT;
5134 const char *message;
5135 int new_binding_state;
5136 int send_to_backup = 0;
5137 int required_options;
5138 isc_boolean_t chaddr_changed = ISC_FALSE;
5139 isc_boolean_t ident_changed = ISC_FALSE;
5142 required_options = FTB_ASSIGNED_IP_ADDRESS | FTB_BINDING_STATUS;
5143 if ((msg->options_present & required_options) != required_options) {
5144 message =
"binding update lacks required options";
5145 reason = FTR_MISSING_BINDINFO;
5149 ia.len =
sizeof msg -> assigned_addr;
5150 memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
5153 message =
"unknown IP address";
5154 reason = FTR_ILLEGAL_IP_ADDR;
5162 if ((lease->pool == NULL) || (lease->pool->failover_peer == NULL) ||
5163 (lease->pool->failover_peer != state)) {
5164 message =
"IP address is covered by a different failover "
5165 "relationship state";
5166 reason = FTR_ILLEGAL_IP_ADDR;
5180 if ((lease->flags & ON_ACK_QUEUE) != 0) {
5181 if (failover_lease_is_better(state, lease, msg)) {
5182 message =
"incoming update is less critical than "
5184 reason = FTR_LESS_CRIT_BIND_INFO;
5194 message =
"no memory";
5198 if (msg -> options_present & FTB_CHADDR) {
5200 message =
"BNDUPD to ABANDONED with a CHADDR";
5203 if (msg -> chaddr.count >
sizeof lt -> hardware_addr.hbuf) {
5204 message =
"chaddr too long";
5210 msg->chaddr.count) != 0))
5211 chaddr_changed = ISC_TRUE;
5213 lt -> hardware_addr.hlen = msg -> chaddr.count;
5214 memcpy (lt -> hardware_addr.hbuf, msg -> chaddr.data,
5215 msg -> chaddr.count);
5216 }
else if (msg->binding_status ==
FTS_ACTIVE ||
5219 message =
"BNDUPD without CHADDR";
5220 reason = FTR_MISSING_BINDINFO;
5223 chaddr_changed = ISC_TRUE;
5233 if (msg->options_present & FTB_CLIENT_IDENTIFIER) {
5235 message =
"BNDUPD to ABANDONED with client-id";
5239 if ((lt->
uid_len != msg->client_identifier.count) ||
5240 (lt->
uid == NULL) ||
5241 (memcmp(lt->
uid, msg->client_identifier.data,
5243 ident_changed = ISC_TRUE;
5245 lt->
uid_len = msg->client_identifier.count;
5260 message =
"no memory";
5269 msg -> client_identifier.data, lt -> uid_len);
5270 }
else if (lt->
uid && msg->binding_status !=
FTS_RESET &&
5273 ident_changed = ISC_TRUE;
5306 (chaddr_changed || ident_changed)) {
5307 #if defined (NSUPDATE)
5311 if (lease->scope != NULL)
5316 if (msg -> options_present & FTB_STOS) {
5317 lt -> starts = msg -> stos;
5319 if (msg -> options_present & FTB_LEASE_EXPIRY) {
5320 lt -> ends = msg -> expiry;
5322 if (msg->options_present & FTB_POTENTIAL_EXPIRY) {
5323 lt->
atsfp = lt->
tsfp = msg->potential_expiry;
5325 if (msg->options_present & FTB_IP_FLAGS) {
5326 if (msg->ip_flags & FTF_IP_FLAG_RESERVE) {
5327 if ((((state->i_am == primary) &&
5328 (lease->binding_state ==
FTS_FREE)) ||
5329 ((state->i_am == secondary) &&
5332 message =
"Address is not reserved.";
5333 reason = FTR_IP_NOT_RESERVED;
5341 if (msg->ip_flags & FTF_IP_FLAG_BOOTP) {
5342 if ((((state->i_am == primary) &&
5343 (lease->binding_state ==
FTS_FREE)) ||
5344 ((state->i_am == secondary) &&
5347 message =
"Address is not allocated to BOOTP.";
5354 if (msg->ip_flags & ~(FTF_IP_FLAG_RESERVE | FTF_IP_FLAG_BOOTP))
5355 log_info(
"Unknown IP-flags set in BNDUPD (0x%x).",
5360 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
5361 log_info (
"processing state transition for %s: %s to %s",
5369 if (state -> me.state ==
normal) {
5372 (lease, state, msg -> binding_status,
5373 msg -> potential_expiry));
5380 (lease, state, msg -> binding_status,
5381 msg -> potential_expiry));
5383 if (new_binding_state != msg -> binding_status) {
5386 if (snprintf (outbuf,
sizeof outbuf,
5387 "%s: invalid state transition: %s to %s",
5392 log_fatal (
"%s: impossible outbuf overflow",
5393 "dhcp_failover_process_bind_update");
5403 lt -> next_binding_state =
FTS_FREE;
5410 if ((state->i_am == primary) &&
5414 lt -> next_binding_state = new_binding_state;
5416 msg -> binding_status = lt -> next_binding_state;
5427 message =
"database update failed";
5438 if (send_to_backup && secondary_not_hoarding(state, lease->pool)) {
5445 log_error(
"can't commit lease %s for mac addr "
5446 "affinity",
piaddr(lease->ip_addr));
5453 lease_dereference (<,
MDL);
5455 lease_dereference (&lease,
MDL);
5457 return ISC_R_SUCCESS;
5466 secondary_not_hoarding(dhcp_failover_state_t *state,
struct pool *p) {
5474 hold = ((total * state->max_lease_ownership) + 50) / 100;
5485 return(lts > -hold);
5489 failover_message_t *msg)
5491 struct lease *lt = (
struct lease *)0;
5492 struct lease *lease = (
struct lease *)0;
5494 const char *message =
"no memory";
5495 u_int32_t pot_expire;
5496 int send_to_backup = ISC_FALSE;
5499 ia.len =
sizeof msg -> assigned_addr;
5500 memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
5503 message =
"no such lease";
5508 if (msg -> options_present & FTB_REJECT_REASON) {
5509 log_error (
"bind update on %s from %s rejected: %.*s",
5510 piaddr (ia), state -> name,
5511 (
int)((msg -> options_present & FTB_MESSAGE)
5512 ? msg -> message.count
5514 (msg -> reject_reason))),
5515 (msg -> options_present & FTB_MESSAGE)
5516 ? (
const char *)(msg -> message.data)
5518 (msg -> reject_reason)));
5529 message =
"xid mismatch";
5534 if (msg->options_present & FTO_POTENTIAL_EXPIRY)
5535 pot_expire = msg->potential_expiry;
5537 pot_expire = lease->
tstp;
5557 lease->
atsfp = lease->
tsfp = pot_expire;
5558 if ((state->i_am == secondary) &&
5580 if (state->i_am == primary &&
5583 send_to_backup = ISC_TRUE;
5585 if (!send_to_backup && state->me.state ==
normal)
5591 lease->
atsfp = lease->
tsfp = pot_expire;
5613 if (state -> send_update_done == lease) {
5614 lease_dereference (&state -> send_update_done,
MDL);
5621 if (send_to_backup && secondary_not_hoarding(state, lease->
pool)) {
5630 if (state->me.state ==
normal)
5639 lease_dereference (&lease,
MDL);
5641 lease_dereference (<,
MDL);
5643 return ISC_R_SUCCESS;
5646 log_info (
"bind update on %s got ack from %s: %s.",
5647 piaddr (ia), state -> name, message);
5658 #define FREE_LEASES 0
5659 #define ACTIVE_LEASES 1
5660 #define EXPIRED_LEASES 2
5661 #define ABANDONED_LEASES 3
5662 #define BACKUP_LEASES 4
5663 #define RESERVED_LEASES 5
5669 for (p = s ->
pools; p; p = p ->
next) {
5681 for (l = *(lptr [i]); l; l = l ->
next) {
5693 return ISC_R_SUCCESS;
5698 failover_message_t *msg)
5700 if (state->send_update_done) {
5701 log_info(
"Received update request while old update still "
5702 "flying! Silently discarding old request.");
5703 lease_dereference(&state->send_update_done,
MDL);
5709 state->updxid = msg->xid;
5714 if (state -> update_queue_tail) {
5715 lease_reference (&state -> send_update_done,
5716 state -> update_queue_tail,
MDL);
5718 log_info (
"Update request from %s: sending update",
5724 log_info (
"Update request from %s: nothing pending",
5728 return ISC_R_SUCCESS;
5733 failover_message_t *msg)
5735 if (state->send_update_done) {
5736 log_info(
"Received update request while old update still "
5737 "flying! Silently discarding old request.");
5738 lease_dereference(&state->send_update_done,
MDL);
5744 state->updxid = msg->xid;
5746 if (state -> update_queue_tail) {
5747 lease_reference (&state -> send_update_done,
5748 state -> update_queue_tail,
MDL);
5750 log_info (
"Update request all from %s: sending update",
5756 log_info (
"Update request all from %s: nothing pending",
5760 return ISC_R_SUCCESS;
5765 failover_message_t *msg)
5769 log_info (
"failover peer %s: peer update completed.",
5772 state -> curUPD = 0;
5774 switch (state -> me.state) {
5790 if (state->i_am == secondary) {
5793 log_error(
"Secondary is in conflict_done "
5794 "state after conflict resolution, "
5795 "this is illegal.");
5799 if (state->i_am == primary)
5802 log_error(
"Spurious update-done message.");
5808 log_error(
"Spurious update-done message.");
5817 if (state -> me.stos + state -> mclt >
cur_time &&
5818 state -> partner.state !=
recover &&
5821 #if defined (DEBUG_FAILOVER_TIMING)
5824 state -> me.stos + state -> mclt),
5825 "dhcp_failover_recover_done");
5827 tv . tv_sec = (
int)(state -> me.stos + state -> mclt);
5832 (
tvref_t)omapi_object_reference,
5839 return ISC_R_SUCCESS;
5844 dhcp_failover_state_t *state = sp;
5846 #if defined (DEBUG_FAILOVER_TIMING)
5847 log_info (
"dhcp_failover_recover_done");
5853 #if defined (DEBUG_FAILOVER_MESSAGES)
5860 unsigned *obufix,
unsigned obufmax,
const char *s)
5862 int len = strlen (s);
5864 while (len + *obufix + 1 >= obufmax) {
5873 strcpy (&obuf [*obufix], s);
5880 unsigned char loadb_mx_tbl[256] = {
5881 251, 175, 119, 215, 81, 14, 79, 191, 103, 49,
5882 181, 143, 186, 157, 0, 232, 31, 32, 55, 60,
5883 152, 58, 17, 237, 174, 70, 160, 144, 220, 90,
5884 57, 223, 59, 3, 18, 140, 111, 166, 203, 196,
5885 134, 243, 124, 95, 222, 179, 197, 65, 180, 48,
5886 36, 15, 107, 46, 233, 130, 165, 30, 123, 161,
5887 209, 23, 97, 16, 40, 91, 219, 61, 100, 10,
5888 210, 109, 250, 127, 22, 138, 29, 108, 244, 67,
5889 207, 9, 178, 204, 74, 98, 126, 249, 167, 116,
5890 34, 77, 193, 200, 121, 5, 20, 113, 71, 35,
5891 128, 13, 182, 94, 25, 226, 227, 199, 75, 27,
5892 41, 245, 230, 224, 43, 225, 177, 26, 155, 150,
5893 212, 142, 218, 115, 241, 73, 88, 105, 39, 114,
5894 62, 255, 192, 201, 145, 214, 168, 158, 221, 148,
5895 154, 122, 12, 84, 82, 163, 44, 139, 228, 236,
5896 205, 242, 217, 11, 187, 146, 159, 64, 86, 239,
5897 195, 42, 106, 198, 118, 112, 184, 172, 87, 2,
5898 173, 117, 176, 229, 247, 253, 137, 185, 99, 164,
5899 102, 147, 45, 66, 231, 52, 141, 211, 194, 206,
5900 246, 238, 56, 110, 78, 248, 63, 240, 189, 93,
5901 92, 51, 53, 183, 19, 171, 72, 50, 33, 104,
5902 101, 69, 8, 252, 83, 120, 76, 135, 85, 54,
5903 202, 125, 188, 213, 96, 235, 136, 208, 162, 129,
5904 190, 132, 156, 38, 47, 1, 7, 254, 24, 4,
5905 216, 131, 89, 21, 28, 133, 37, 153, 149, 80,
5906 170, 68, 6, 169, 234, 151 };
5908 static unsigned char loadb_p_hash (
const unsigned char *,
unsigned);
5909 static unsigned char loadb_p_hash (
const unsigned char *key,
unsigned len)
5911 unsigned char hash = len;
5913 for(i = len; i > 0; )
5914 hash = loadb_mx_tbl [hash ^ (key [--i])];
5922 unsigned char hbaix;
5926 ec = ntohs(packet->
raw->
secs);
5928 #if defined(SECS_BYTEORDER)
5935 if ((ec > 255) && ((ec & 0xff) == 0)) {
5936 ec = (ec >> 8) | (ec << 8);
5940 if (state->load_balance_max_secs < ec) {
5954 memset(&ds, 0,
sizeof ds);
5959 hbaix = loadb_p_hash(ds.data, ds.len);
5963 hbaix = loadb_p_hash(packet->
raw->
chaddr,
5967 hm = state->hba[(hbaix >> 3) & 0x1F] & (1 << (hbaix & 0x07));
5969 if (state->i_am == primary)
5983 dhcp_failover_state_t *state;
5984 unsigned char hbaix;
5992 if (!state || !state->hba)
6009 hm = state->hba[(hbaix >> 3) & 0x1F] & (1 << (hbaix & 0x07));
6011 if (state->i_am == primary)
6025 dhcp_failover_state_t *state,
6032 if (binding_state == lease -> binding_state)
6033 return binding_state;
6035 switch (lease -> binding_state) {
6038 switch (binding_state) {
6049 if (state -> i_am == secondary)
6050 return binding_state;
6058 new_state = binding_state;
6068 if (state -> i_am == primary) {
6072 return binding_state;
6073 new_state = lease -> binding_state;
6078 switch (binding_state) {
6084 new_state = lease -> binding_state;
6087 return binding_state;
6095 if (lease -> ends - 65 >
cur_time) {
6096 new_state = lease -> binding_state;
6104 return binding_state;
6112 switch (binding_state) {
6118 new_state = lease -> binding_state;
6121 return binding_state;
6128 return binding_state;
6135 switch (binding_state) {
6146 return binding_state;
6153 switch (binding_state) {
6159 new_state = lease -> binding_state;
6162 return binding_state;
6169 return binding_state;
6176 switch (binding_state) {
6185 if (state -> i_am == primary)
6186 return binding_state;
6192 return binding_state;
6195 new_state = lease -> binding_state;
6215 dhcp_failover_state_t *state,
6222 if (binding_state == lease -> binding_state)
6223 new_state = binding_state;
6225 switch (lease -> binding_state) {
6235 new_state = binding_state;
6242 switch (binding_state) {
6245 new_state = lease -> binding_state;
6257 new_state = binding_state;
6268 new_state = binding_state;
6303 dhcp_failover_state_t *peer;
6305 if (lease && lease->
pool &&
6329 if (peer -> i_am == primary)
6333 ((lease->
tsfp < peer->me.stos) ?
6334 (peer->me.stos + peer->mclt <
cur_time) :
6353 if ((peer->i_am == primary) &&
6356 if ((peer->i_am == secondary) &&
6387 if (peer->i_am == secondary)
6391 ((lease->
tsfp < peer->me.stos) ?
6392 (peer->me.stos + peer->mclt <
cur_time) :
6409 static isc_result_t failover_message_reference (failover_message_t **mp,
6410 failover_message_t *m,
6411 const char *file,
int line)
6415 return ISC_R_SUCCESS;
6418 static isc_result_t failover_message_dereference (failover_message_t **mp,
6419 const char *file,
int line)
6421 failover_message_t *m;
6424 if (m -> refcnt == 0) {
6426 failover_message_dereference (&m -> next,
6428 if (m -> chaddr.data)
6429 dfree (m -> chaddr.data, file, line);
6430 if (m -> client_identifier.data)
6431 dfree (m -> client_identifier.data, file, line);
6433 dfree (m -> hba.data, file, line);
6434 if (m -> message.data)
6435 dfree (m -> message.data, file, line);
6436 if (m -> relationship_name.data)
6437 dfree (m -> relationship_name.data, file, line);
6438 if (m -> reply_options.data)
6439 dfree (m -> reply_options.data, file, line);
6440 if (m -> request_options.data)
6441 dfree (m -> request_options.data, file, line);
6442 if (m -> vendor_class.data)
6443 dfree (m -> vendor_class.data, file, line);
6444 if (m -> vendor_options.data)
6445 dfree (m -> vendor_options.data, file, line);
6448 dfree (*mp, file, line);
6451 return ISC_R_SUCCESS;
isc_result_t dhcp_failover_state_signal(omapi_object_t *, const char *, va_list)
int supersede_lease(struct lease *, struct lease *, int, int, int, int)
isc_result_t dhcp_failover_send_poolreq(dhcp_failover_state_t *)
isc_result_t dhcp_failover_state_stuff(omapi_object_t *, omapi_object_t *, omapi_object_t *)
isc_result_t dhcp_failover_send_connectack(omapi_object_t *, dhcp_failover_state_t *, int, const char *)
isc_result_t dhcp_failover_link_get_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **)
struct binding_scope * global_scope
int write_failover_state(dhcp_failover_state_t *)
isc_result_t dhcp_failover_listener_set_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *)
int dhcp_failover_state_match_by_name(dhcp_failover_state_t *, failover_option_t *)
failover_option_t failover_option_t * dhcp_failover_make_option(unsigned, char *, unsigned *, unsigned,...)
omapi_object_type_t * omapi_type_connection
isc_result_t dhcp_failover_send_connect(omapi_object_t *)
isc_result_t omapi_make_int_value(omapi_value_t **, omapi_data_string_t *, int, const char *, int)
isc_result_t omapi_object_reference(omapi_object_t **, omapi_object_t *, const char *, int)
const char * piaddr(const struct iaddr addr)
omapi_object_type_t * dhcp_type_failover_link
#define DHCP_R_PROTOCOLERROR
struct shared_network * shared_networks
#define DHO_PXE_CLIENT_ID
void * dmalloc(unsigned, const char *, int)
struct lease_state * state
int option_cache_dereference(struct option_cache **ptr, const char *file, int line)
isc_result_t omapi_connection_copyin(omapi_object_t *, const unsigned char *, unsigned)
void dhcp_failover_pool_check(struct pool *)
struct iaddr ip_addr(struct iaddr subnet, struct iaddr mask, u_int32_t host_address)
void cancel_timeout(void(*)(void *) where, void *what)
isc_result_t dhcp_failover_register(omapi_object_t *)
isc_result_t dhcp_failover_link_initiate(omapi_object_t *)
#define DHCP_R_INVALIDARG
omapi_typed_data_t * value
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
struct lease * next_pending
isc_result_t dhcp_failover_state_create(omapi_object_t **, omapi_object_t *)
isc_result_t omapi_signal_in(omapi_object_t *, const char *,...)
isc_result_t dhcp_failover_listener_stuff(omapi_object_t *, omapi_object_t *, omapi_object_t *)
struct universe dhcp_universe
void dhcp_failover_keepalive(void *)
void data_string_forget(struct data_string *data, const char *file, int line)
isc_result_t dhcp_failover_send_update_request(dhcp_failover_state_t *)
omapi_object_type_t * dhcp_type_failover_state
int option_cache_reference(struct option_cache **ptr, struct option_cache *src, const char *file, int line)
const char * dhcp_failover_option_name(unsigned)
int log_error(const char *,...) __attribute__((__format__(__printf__
int binding_scope_dereference(struct binding_scope **ptr, const char *file, int line)
failover_option_t * dhcp_failover_option_printf(unsigned, char *, unsigned *, unsigned, const char *,...) __attribute__((__format__(__printf__
void add_timeout(struct timeval *when, void(*)(void *) where, void *what, tvref_t ref, tvunref_t unref)
void(* tvunref_t)(void *, const char *, int)
dhcp_failover_state_t * failover_peer
#define OMAPI_OBJECT_ALLOC(name, stype, type)
void dhcp_failover_recover_done(void *)
failover_option_t null_failover_option
isc_result_t omapi_listen_addr(omapi_object_t *, omapi_addr_t *, int)
#define DHCP_R_KEYCONFLICT
void(* tvref_t)(void *, void *, const char *, int)
const char * binding_state_print(enum failover_state state)
struct option_state * options
isc_result_t dhcp_failover_send_bind_ack(dhcp_failover_state_t *, failover_message_t *, int, const char *)
void log_fatal(const char *,...) __attribute__((__format__(__printf__
isc_result_t dhcp_failover_send_poolresp(dhcp_failover_state_t *, int)
const char * dhcp_flink_state_names[]
isc_result_t dhcp_failover_link_destroy(omapi_object_t *, const char *, int)
const char * dhcp_failover_message_name(unsigned)
isc_result_t dhcp_failover_state_transition(dhcp_failover_state_t *, const char *)
isc_result_t dhcp_failover_state_destroy(omapi_object_t *, const char *, int)
struct hardware hardware_addr
isc_result_t omapi_connection_put_uint32(omapi_object_t *, u_int32_t)
omapi_object_type_t * omapi_type_protocol
omapi_object_type_t * dhcp_type_failover_listener
failover_option_t skip_failover_option
isc_result_t omapi_make_uint_value(omapi_value_t **, omapi_data_string_t *, unsigned int, const char *, int)
isc_result_t dhcp_failover_listen(omapi_object_t *)
isc_result_t dhcp_failover_state_remove(omapi_object_t *, omapi_object_t *)
int evaluate_option_cache(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
isc_result_t dhcp_failover_set_state(dhcp_failover_state_t *, enum failover_state)
isc_result_t omapi_get_value_str(omapi_object_t *, omapi_object_t *, const char *, omapi_value_t **)
isc_result_t omapi_connection_require(omapi_object_t *, unsigned)
isc_result_t dhcp_failover_process_bind_ack(dhcp_failover_state_t *, failover_message_t *)
isc_result_t dhcp_failover_state_set_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *)
#define DHCPD_FAILOVER_POOL_DOBALANCE_START()
void dhcp_failover_pool_rebalance(void *)
isc_result_t dhcp_failover_generate_update_queue(dhcp_failover_state_t *, int)
binding_state_t binding_state
isc_result_t dhcp_failover_put_message(dhcp_failover_link_t *, omapi_object_t *, int, u_int32_t,...)
isc_result_t dhcp_failover_state_get_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **)
void dhcp_failover_rescind_updates(dhcp_failover_state_t *)
void dhcp_failover_listener_restart(void *)
isc_result_t dhcp_failover_process_update_request_all(dhcp_failover_state_t *, failover_message_t *)
isc_result_t dhcp_failover_send_disconnect(omapi_object_t *, int, const char *)
isc_result_t dhcp_failover_peer_state_changed(dhcp_failover_state_t *, failover_message_t *)
int write_lease(struct lease *lease)
void putULong(unsigned char *, u_int32_t)
isc_result_t dhcp_failover_process_update_request(dhcp_failover_state_t *, failover_message_t *)
isc_result_t omapi_object_dereference(omapi_object_t **, const char *, int)
void commit_leases_timeout(void *)
isc_result_t omapi_signal(omapi_object_t *, const char *,...)
int dhcp_failover_queue_ack(dhcp_failover_state_t *, failover_message_t *msg)
isc_result_t dhcp_failover_link_signal(omapi_object_t *, const char *, va_list)
const char * dhcp_failover_state_name_print(enum failover_state)
isc_result_t omapi_get_int_value(unsigned long *, omapi_typed_data_t *)
binding_state_t normal_binding_state_transition_check(struct lease *, dhcp_failover_state_t *, binding_state_t, u_int32_t)
void dfree(void *, const char *, int)
isc_result_t dhcp_failover_link_stuff_values(omapi_object_t *, omapi_object_t *, omapi_object_t *)
isc_result_t omapi_handle_td_lookup(omapi_object_t **, omapi_typed_data_t *)
dhcp_failover_state_t * failover_states
int load_balance_mine(struct packet *, dhcp_failover_state_t *)
isc_result_t omapi_connection_get_uint32(omapi_object_t *, u_int32_t *)
isc_result_t omapi_addr_list_dereference(omapi_addr_list_t **, const char *, int)
void dhcp_failover_link_startup_timeout(void *)
struct option_cache * lookup_option(struct universe *universe, struct option_state *options, unsigned code)
#define DHCPD_FAILOVER_SET_STATE_START(arg1, arg2)
int int log_info(const char *,...) __attribute__((__format__(__printf__
isc_result_t find_failover_peer(dhcp_failover_state_t **, const char *, const char *, int)
#define DHCPD_FAILOVER_SET_STATE_DONE()
isc_result_t omapi_connection_put_string(omapi_object_t *, const char *)
isc_result_t enter_failover_peer(dhcp_failover_state_t *)
void dhcp_failover_reconnect(void *)
isc_result_t omapi_listen(omapi_object_t *, unsigned, int)
void dhcp_failover_startup(void)
isc_result_t omapi_value_dereference(omapi_value_t **, const char *, int)
isc_result_t dhcp_failover_send_update_done(dhcp_failover_state_t *)
isc_result_t ddns_removals(struct lease *, struct iasubopt *, struct dhcp_ddns_cb *, isc_boolean_t)
binding_state_t rewind_binding_state
int peer_wants_lease(struct lease *)
void dhcp_failover_ack_queue_remove(dhcp_failover_state_t *, struct lease *)
isc_result_t dhcp_failover_set_service_state(dhcp_failover_state_t *state)
unsigned char address[16]
void failover_print(char *, unsigned *, unsigned, const char *)
int dhcp_failover_queue_update(struct lease *, int)
int omapi_ds_strcmp(omapi_data_string_t *, const char *)
struct failover_option_info ft_options[]
isc_result_t omapi_connection_put_uint16(omapi_object_t *, u_int32_t)
binding_state_t desired_binding_state
int dhcp_failover_write_all_states(void)
isc_result_t dhcp_failover_listener_destroy(omapi_object_t *, const char *, int)
isc_result_t dhcp_failover_send_bind_update(dhcp_failover_state_t *, struct lease *)
isc_result_t dhcp_failover_send_state(dhcp_failover_state_t *)
void dhcp_failover_timeout(void *)
int dhcp_failover_state_match(dhcp_failover_state_t *, u_int8_t *, unsigned)
void dhcp_failover_toack_queue_timeout(void *)
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
isc_result_t omapi_connection_copyout(unsigned char *, omapi_object_t *, unsigned)
isc_result_t omapi_connect_list(omapi_object_t *, omapi_addr_list_t *, omapi_addr_t *)
struct ipv6_pool ** pools
isc_result_t omapi_make_const_value(omapi_value_t **, omapi_data_string_t *, const unsigned char *, unsigned, const char *, int)
isc_result_t dhcp_failover_listener_signal(omapi_object_t *, const char *, va_list)
struct shared_network * next
#define DHCP_R_INCOMPLETE
#define DHO_DHCP_CLIENT_IDENTIFIER
isc_result_t omapi_connection_get_uint16(omapi_object_t *, u_int16_t *)
isc_result_t omapi_connection_put_name(omapi_object_t *, const char *)
void putUShort(unsigned char *, u_int32_t)
const char * dhcp_failover_reject_reason_print(int)
int dhcp_failover_send_acks(dhcp_failover_state_t *)
isc_result_t dhcp_failover_send_updates(dhcp_failover_state_t *)
isc_result_t omapi_disconnect(omapi_object_t *, int)
void dhcp_failover_startup_timeout(void *)
isc_result_t dhcp_failover_send_update_request_all(dhcp_failover_state_t *)
struct binding_scope * scope
void data_string_copy(struct data_string *dest, const struct data_string *src, const char *file, int line)
struct iaddr server_identifier
binding_state_t conflict_binding_state_transition_check(struct lease *, dhcp_failover_state_t *, binding_state_t, u_int32_t)
#define DHCPD_FAILOVER_POOL_DOBALANCE_DONE()
isc_result_t dhcp_failover_state_lookup(omapi_object_t **, omapi_object_t *, omapi_object_t *)
int find_lease_by_ip_addr(struct lease **, struct iaddr, const char *, int)
isc_result_t dhcp_failover_listener_get_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **)
binding_state_t next_binding_state
isc_result_t dhcp_failover_link_set_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *)
int dhcp_failover_state_pool_check(dhcp_failover_state_t *)
isc_result_t dhcp_failover_process_bind_update(dhcp_failover_state_t *, failover_message_t *)
isc_result_t dhcp_failover_process_update_done(dhcp_failover_state_t *, failover_message_t *)
int lease_mine_to_reallocate(struct lease *)
isc_result_t omapi_make_string_value(omapi_value_t **, omapi_data_string_t *, const char *, const char *, int)
isc_result_t omapi_addr_list_new(omapi_addr_list_t **, unsigned, const char *, int)
void dhcp_failover_send_contact(void *)
int lease_copy(struct lease **, struct lease *, const char *, int)
void dhcp_failover_auto_partner_down(void *vs)