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)
1948 #if defined (BINARY_LEASES)
1949 long int tiebreaker = 0;
1955 l->
tsfp = state->me.stos + state->mclt;
1963 if (tiebreaker != LONG_MAX)
1973 #if defined (DEBUG_FAILOVER_TIMING)
1995 return ISC_R_SUCCESS;
1999 failover_message_t *msg)
2005 new_state = msg -> server_state;
2006 startupp = (msg -> server_flags & FTF_SERVER_STARTUP) ? 1 : 0;
2008 if (state -> partner.state == new_state && state -> me.state) {
2009 switch (state -> me.state) {
2022 state->saved_state);
2023 return ISC_R_SUCCESS;
2032 return ISC_R_SUCCESS;
2049 state -> partner.state = new_state;
2052 log_info (
"failover peer %s: peer moves from %s to %s",
2058 if ((state->me.state ==
normal) && (state->partner.state ==
normal))
2059 log_info(
"failover peer %s: Both servers normal", state->name);
2065 log_error (
"Unable to record current failover state for %s",
2072 switch (new_state) {
2089 log_error(
"failover peer %s: Invalid state: %d", state->name,
2092 return ISC_R_SUCCESS;
2098 switch (state -> me.state ==
startup ?
2099 state -> saved_state : state -> me.state) {
2101 switch (new_state) {
2107 if (state -> me.state ==
startup)
2118 log_error(
"Peer %s: Invalid state transition %s "
2119 "to %s.", state->name,
2144 switch (new_state) {
2146 log_info (
"failover peer %s: requesting %s",
2147 state -> name,
"full update from peer");
2151 if (state -> me.state ==
recover)
2177 if (state -> me.state ==
recover)
2198 switch (new_state) {
2201 log_error(
"Peer %s moves to normal during conflict "
2202 "resolution - panic, shutting down.",
2211 log_error(
"Peer %s: Unexpected move to "
2212 "conflict-done.", state->name);
2239 switch (new_state) {
2257 log_fatal(
"Peer %s: Invalid attempt to move from %s "
2258 "to %s while local state is conflict-done.",
2270 switch (new_state) {
2296 switch (new_state) {
2336 switch (new_state) {
2364 switch (new_state) {
2366 log_error(
"Both servers have entered recover-done!");
2407 if (state -> me.state ==
startup && state -> saved_state !=
startup)
2414 return ISC_R_SUCCESS;
2423 dhcp_failover_pool_balance(dhcp_failover_state_t *state)
2427 state->sched_balance = 0;
2429 dhcp_failover_pool_dobalance(state, NULL);
2440 dhcp_failover_state_t *state;
2441 isc_boolean_t sendreq = ISC_FALSE;
2443 state = (dhcp_failover_state_t *)failover_state;
2446 state->sched_balance = 0;
2448 if (dhcp_failover_pool_dobalance(state, &sendreq))
2460 dhcp_failover_pool_reqbalance(dhcp_failover_state_t *state)
2466 state->sched_balance = 0;
2468 queued = dhcp_failover_pool_dobalance(state, NULL);
2475 log_info(
"peer %s: Got POOLREQ, answering negatively! "
2476 "Peer may be out of leases or database inconsistent.",
2488 dhcp_failover_pool_dobalance(dhcp_failover_state_t *state,
2489 isc_boolean_t *sendreq)
2491 int lts, total, thresh, hold, panic, pass;
2492 int leases_queued = 0;
2493 struct lease *lp = NULL;
2495 struct lease *ltemp = NULL;
2502 int (*log_func)(
const char *, ...);
2503 const char *result, *reqlog;
2505 if (state -> me.state !=
normal)
2537 thresh = ((total * state->max_lease_misbalance) + 50) / 100;
2538 hold = ((total * state->max_lease_ownership) + 50) / 100;
2553 panic = thresh * -2;
2558 if ((sendreq != NULL) && (lts < panic)) {
2559 reqlog =
" (requesting peer rebalance!)";
2560 *sendreq = ISC_TRUE;
2564 log_info(
"balancing pool %lx %s total %d free %d "
2565 "backup %d lts %d max-own (+/-)%d%s",
2567 (p->shared_network ?
2569 p->free_leases, p->backup_leases, lts, hold,
2589 lease_dereference(&next,
MDL);
2592 lease_reference(&next, ltemp,
MDL);
2619 }
else if (lts <= -hold)
2635 lease_dereference(&lp,
MDL);
2637 lease_reference(&lp, next,
MDL);
2645 lease_dereference(&next,
MDL);
2647 lease_dereference(&lp,
MDL);
2650 result =
"IMBALANCED";
2653 result =
"balanced";
2657 log_func(
"%s pool %lx %s total %d free %d backup %d "
2658 "lts %d max-misbal %d", result, (
unsigned long)p,
2659 (p->shared_network ?
2660 p->shared_network->name :
""), p->lease_count,
2661 p->free_leases, p->backup_leases, lts, thresh);
2673 return leases_queued;
2683 dhcp_failover_state_t *peer;
2686 struct lease *ltemp;
2690 if(!peer || peer->me.state !=
normal)
2719 est1 = ((est1 * peer->max_lease_misbalance) + 50) / 100;
2720 est2 = ((est2 * peer->max_lease_misbalance) + 50) / 100;
2725 if(peer->i_am == primary)
2735 if(est1 > peer->max_balance)
2736 est1 = peer->max_balance;
2742 est2 = peer->last_balance + peer->min_balance;
2743 if(peer->last_balance && (est1 < est2))
2747 est1 += random() % 5;
2750 if(peer->sched_balance) {
2751 if (est1 >= peer->sched_balance)
2761 peer->sched_balance = est1;
2763 #if defined(DEBUG_FAILOVER_TIMING)
2764 log_info(
"add_timeout +%d dhcp_failover_pool_rebalance",
2770 (
tvref_t)dhcp_failover_state_reference,
2771 (
tvunref_t)dhcp_failover_state_dereference);
2780 for (p = s ->
pools; p; p = p ->
next) {
2792 isc_result_t status;
2795 if (!state -> link_to_peer)
2796 return ISC_R_SUCCESS;
2801 if (state->toack_queue_head != NULL)
2804 while ((state -> partner.max_flying_updates >
2805 state -> cur_unacked_updates) && state -> update_queue_head) {
2807 lease_reference (&lp, state -> update_queue_head,
MDL);
2811 if (status != ISC_R_SUCCESS) {
2812 lease_dereference (&lp,
MDL);
2819 lease_dereference (&state -> update_queue_head,
MDL);
2821 lease_reference (&state -> update_queue_head,
2825 lease_dereference (&state -> update_queue_tail,
MDL);
2828 if (state -> ack_queue_head) {
2832 lease_dereference (&state -> ack_queue_tail,
MDL);
2834 lease_reference (&state -> ack_queue_head, lp,
MDL);
2836 #if defined (POINTER_DEBUG)
2838 log_error (
"ack_queue_tail: lp -> next_pending");
2842 lease_reference (&state -> ack_queue_tail, lp,
MDL);
2844 lease_dereference (&lp,
MDL);
2847 state -> cur_unacked_updates++;
2849 return ISC_R_SUCCESS;
2858 dhcp_failover_state_t *
state;
2860 if (!lease -> pool ||
2861 !lease -> pool -> failover_peer)
2869 state = lease -> pool -> failover_peer;
2875 if (state -> update_queue_head) {
2876 lease_reference (&state -> update_queue_tail ->
next_pending,
2878 lease_dereference (&state -> update_queue_tail,
MDL);
2880 lease_reference (&state -> update_queue_head, lease,
MDL);
2882 #if defined (POINTER_DEBUG)
2884 log_error (
"next pending on update queue lease.");
2885 #if defined (DEBUG_RC_HISTORY)
2886 dump_rc_history (lease);
2891 lease_reference (&state -> update_queue_tail, lease,
MDL);
2900 failover_message_t *msg = (failover_message_t *)0;
2906 while (state -> toack_queue_head) {
2907 failover_message_reference
2908 (&msg, state -> toack_queue_head,
MDL);
2909 failover_message_dereference
2910 (&state -> toack_queue_head,
MDL);
2912 failover_message_reference
2913 (&state -> toack_queue_head, msg -> next,
MDL);
2918 failover_message_dereference (&msg,
MDL);
2921 if (state -> toack_queue_tail)
2922 failover_message_dereference (&state -> toack_queue_tail,
MDL);
2923 state -> pending_acks = 0;
2930 dhcp_failover_state_t *state = vs;
2932 #if defined (DEBUG_FAILOVER_TIMING)
2933 log_info (
"dhcp_failover_toack_queue_timeout");
2943 failover_message_t *msg)
2947 if (state -> toack_queue_head) {
2948 failover_message_reference
2949 (&state -> toack_queue_tail -> next, msg,
MDL);
2950 failover_message_dereference (&state -> toack_queue_tail,
MDL);
2952 failover_message_reference (&state -> toack_queue_head,
2955 failover_message_reference (&state -> toack_queue_tail, msg,
MDL);
2957 state -> pending_acks++;
2961 if (state -> pending_acks >= state -> partner.max_flying_updates / 2) {
2966 if (state -> pending_acks > 0) {
2967 #if defined (DEBUG_FAILOVER_TIMING)
2969 "dhcp_failover_toack_queue_timeout");
2975 (
tvref_t)dhcp_failover_state_reference,
2976 (
tvunref_t)dhcp_failover_state_dereference);
2983 struct lease *lease)
2987 if (!(lease ->
flags & ON_ACK_QUEUE))
2990 if (state -> ack_queue_head == lease) {
2991 lease_dereference (&state -> ack_queue_head,
MDL);
2993 lease_reference (&state -> ack_queue_head,
2997 lease_dereference (&state -> ack_queue_tail,
MDL);
3000 for (lp = state -> ack_queue_head;
3014 lease_dereference (&state -> ack_queue_tail,
MDL);
3019 lease_reference (&state -> ack_queue_tail, lp,
MDL);
3023 lease ->
flags &= ~ON_ACK_QUEUE;
3030 state -> cur_unacked_updates--;
3037 if (state -> cur_unacked_updates == 0) {
3047 isc_result_t status;
3057 return ISC_R_SUCCESS;
3059 return ISC_R_SUCCESS;
3061 return ISC_R_SUCCESS;
3063 return ISC_R_SUCCESS;
3065 return ISC_R_SUCCESS;
3067 return ISC_R_SUCCESS;
3069 return ISC_R_SUCCESS;
3071 return ISC_R_SUCCESS;
3073 return ISC_R_SUCCESS;
3075 return ISC_R_SUCCESS;
3079 if (status != ISC_R_SUCCESS)
3083 return ISC_R_SUCCESS;
3085 return ISC_R_SUCCESS;
3087 return ISC_R_SUCCESS;
3089 return ISC_R_SUCCESS;
3091 return ISC_R_SUCCESS;
3093 return ISC_R_SUCCESS;
3095 return ISC_R_SUCCESS;
3097 return ISC_R_SUCCESS;
3100 if (h -> inner && h -> inner -> type -> set_value)
3101 return (*(h -> inner -> type -> set_value))
3102 (h -> inner, id, name, value);
3103 return ISC_R_NOTFOUND;
3112 dhcp_failover_state_t *state = vs;
3113 isc_result_t status;
3116 #if defined (DEBUG_FAILOVER_TIMING)
3117 log_info (
"dhcp_failover_reconnect");
3121 if (state -> link_to_peer)
3126 log_info (
"failover peer %s: %s", state -> name,
3127 isc_result_totext (status));
3128 #if defined (DEBUG_FAILOVER_TIMING)
3129 log_info(
"add_timeout +90 dhcp_failover_reconnect");
3134 (
tvref_t)dhcp_failover_state_reference,
3135 (
tvunref_t)dhcp_failover_state_dereference);
3141 dhcp_failover_state_t *state = vs;
3143 #if defined (DEBUG_FAILOVER_TIMING)
3144 log_info (
"dhcp_failover_startup_timeout");
3152 dhcp_failover_link_t *link = vl;
3157 for (; p; p = p -> outer)
3161 log_info (
"failover: link startup timeout");
3168 dhcp_failover_state_t *state = vs;
3169 isc_result_t status;
3172 #if defined (DEBUG_FAILOVER_TIMING)
3173 log_info (
"dhcp_failover_listener_restart");
3177 if (status != ISC_R_SUCCESS) {
3178 log_info (
"failover peer %s: %s", state -> name,
3179 isc_result_totext (status));
3180 #if defined (DEBUG_FAILOVER_TIMING)
3182 "dhcp_failover_listener_restart");
3188 (
tvref_t)dhcp_failover_state_reference,
3189 (
tvunref_t)dhcp_failover_state_dereference);
3196 dhcp_failover_state_t *state = vs;
3198 #if defined (DEBUG_FAILOVER_TIMING)
3199 log_info(
"dhcp_failover_auto_partner_down");
3210 dhcp_failover_state_t *s;
3213 isc_result_t status;
3217 s = (dhcp_failover_state_t *)h;
3222 name, s -> name,
MDL);
3223 return ISC_R_NOTFOUND;
3225 oc = s -> partner.address;
3227 memset (&ds, 0,
sizeof ds);
3234 return ISC_R_NOTFOUND;
3237 name, ds.data, ds.
len,
MDL);
3244 oc = s -> me.address;
3248 s -> partner.port,
MDL);
3251 name, s -> me.port,
MDL);
3254 s -> me.max_flying_updates,
3260 s -> load_balance_max_secs,
MDL);
3265 return ISC_R_NOTFOUND;
3268 s -> partner.state,
MDL);
3271 s -> me.state,
MDL);
3274 s -> partner.stos,
MDL);
3282 s -> last_packet_sent,
MDL);
3285 s -> last_timestamp_received,
3291 s -> me.max_response_delay,
3295 s -> cur_unacked_updates,
MDL);
3298 if (h -> inner && h -> inner -> type -> get_value)
3299 return (*(h -> inner -> type -> get_value))
3300 (h -> inner, id, name, value);
3301 return ISC_R_NOTFOUND;
3305 const char *file,
int line)
3307 dhcp_failover_state_t *s;
3311 s = (dhcp_failover_state_t *)h;
3313 if (s -> link_to_peer)
3314 dhcp_failover_link_dereference (&s -> link_to_peer, file, line);
3317 s -> name = (
char *)0;
3319 if (s -> partner.address)
3321 if (s -> me.address)
3324 dfree (s -> hba, file, line);
3325 s -> hba = (u_int8_t *)0;
3327 if (s -> update_queue_head)
3328 lease_dereference (&s -> update_queue_head, file, line);
3329 if (s -> update_queue_tail)
3330 lease_dereference (&s -> update_queue_tail, file, line);
3331 if (s -> ack_queue_head)
3332 lease_dereference (&s -> ack_queue_head, file, line);
3333 if (s -> ack_queue_tail)
3334 lease_dereference (&s -> ack_queue_tail, file, line);
3335 if (s -> send_update_done)
3336 lease_dereference (&s -> send_update_done, file, line);
3337 if (s -> toack_queue_head)
3338 failover_message_dereference (&s -> toack_queue_head,
3340 if (s -> toack_queue_tail)
3341 failover_message_dereference (&s -> toack_queue_tail,
3343 return ISC_R_SUCCESS;
3355 dhcp_failover_state_t *s;
3356 isc_result_t status;
3363 s = (dhcp_failover_state_t *)h;
3366 if (status != ISC_R_SUCCESS)
3369 if (status != ISC_R_SUCCESS)
3373 if (status != ISC_R_SUCCESS)
3376 if (status != ISC_R_SUCCESS)
3379 sizeof s -> partner.address);
3380 if (status != ISC_R_SUCCESS)
3384 if (status != ISC_R_SUCCESS)
3387 if (status != ISC_R_SUCCESS)
3390 if (status != ISC_R_SUCCESS)
3394 if (status != ISC_R_SUCCESS)
3397 if (status != ISC_R_SUCCESS)
3400 sizeof s -> me.address);
3401 if (status != ISC_R_SUCCESS)
3405 if (status != ISC_R_SUCCESS)
3408 if (status != ISC_R_SUCCESS)
3411 if (status != ISC_R_SUCCESS)
3415 if (status != ISC_R_SUCCESS)
3418 if (status != ISC_R_SUCCESS)
3421 s -> me.max_flying_updates);
3422 if (status != ISC_R_SUCCESS)
3426 if (status != ISC_R_SUCCESS)
3429 if (status != ISC_R_SUCCESS)
3432 if (status != ISC_R_SUCCESS)
3436 if (status != ISC_R_SUCCESS)
3439 if (status != ISC_R_SUCCESS)
3442 (c, (u_int32_t)s -> load_balance_max_secs));
3443 if (status != ISC_R_SUCCESS)
3449 if (status != ISC_R_SUCCESS)
3452 if (status != ISC_R_SUCCESS)
3455 if (status != ISC_R_SUCCESS)
3460 if (status != ISC_R_SUCCESS)
3463 if (status != ISC_R_SUCCESS)
3466 if (status != ISC_R_SUCCESS)
3470 if (status != ISC_R_SUCCESS)
3473 if (status != ISC_R_SUCCESS)
3476 if (status != ISC_R_SUCCESS)
3480 if (status != ISC_R_SUCCESS)
3483 if (status != ISC_R_SUCCESS)
3486 (u_int32_t)s -> partner.stos);
3487 if (status != ISC_R_SUCCESS)
3491 if (status != ISC_R_SUCCESS)
3494 if (status != ISC_R_SUCCESS)
3497 if (status != ISC_R_SUCCESS)
3501 if (status != ISC_R_SUCCESS)
3504 if (status != ISC_R_SUCCESS)
3507 if (status != ISC_R_SUCCESS)
3511 if (status != ISC_R_SUCCESS)
3514 if (status != ISC_R_SUCCESS)
3517 (c, (u_int32_t)s -> last_packet_sent));
3518 if (status != ISC_R_SUCCESS)
3522 if (status != ISC_R_SUCCESS)
3525 if (status != ISC_R_SUCCESS)
3528 (c, (u_int32_t)s -> last_timestamp_received));
3529 if (status != ISC_R_SUCCESS)
3533 if (status != ISC_R_SUCCESS)
3536 if (status != ISC_R_SUCCESS)
3539 if (status != ISC_R_SUCCESS)
3543 if (status != ISC_R_SUCCESS)
3546 if (status != ISC_R_SUCCESS)
3549 (c, (u_int32_t)s -> me.max_response_delay));
3550 if (status != ISC_R_SUCCESS)
3554 if (status != ISC_R_SUCCESS)
3557 if (status != ISC_R_SUCCESS)
3560 (c, (u_int32_t)s -> cur_unacked_updates));
3561 if (status != ISC_R_SUCCESS)
3564 if (h -> inner && h -> inner -> type -> stuff_values)
3565 return (*(h -> inner -> type -> stuff_values)) (c,
id,
3567 return ISC_R_SUCCESS;
3575 isc_result_t status;
3576 dhcp_failover_state_t *s;
3583 if (status == ISC_R_SUCCESS) {
3587 if (status != ISC_R_SUCCESS)
3599 if (status == ISC_R_SUCCESS) {
3601 unsigned l = strlen (s -> name);
3602 if (l == tv -> value -> u.buffer.len &&
3604 tv -> value -> u.buffer.
value, l))
3617 return ISC_R_NOTFOUND;
3628 return ISC_R_SUCCESS;
3634 return ISC_R_NOTIMPLEMENTED;
3640 return ISC_R_NOTIMPLEMENTED;
3644 u_int8_t *addr,
unsigned addrlen)
3649 memset (&ds, 0,
sizeof ds);
3656 state -> partner.address,
MDL)) {
3657 for (i = 0; i + addrlen - 1 < ds.len; i += addrlen) {
3658 if (!memcmp (&ds.data [i],
3671 dhcp_failover_state_t *state;
3672 failover_option_t *name;
3674 if ((strlen(state->name) == name->count) &&
3675 (memcmp(state->name, name->data, name->count) == 0))
3683 static char resbuf[
sizeof(
"Undefined-255: This reason code is not defined "
3684 "in the protocol standard.")];
3686 if ((reason > 0xff) || (reason < 0))
3687 return "Reason code out of range.";
3690 case FTR_ILLEGAL_IP_ADDR:
3691 return "Illegal IP address (not part of any address pool).";
3693 case FTR_FATAL_CONFLICT:
3694 return "Fatal conflict exists: address in use by other client.";
3696 case FTR_MISSING_BINDINFO:
3697 return "Missing binding information.";
3699 case FTR_TIMEMISMATCH:
3700 return "Connection rejected, time mismatch too great.";
3702 case FTR_INVALID_MCLT:
3703 return "Connection rejected, invalid MCLT.";
3705 case FTR_MISC_REJECT:
3706 return "Connection rejected, unknown reason.";
3708 case FTR_DUP_CONNECTION:
3709 return "Connection rejected, duplicate connection.";
3711 case FTR_INVALID_PARTNER:
3712 return "Connection rejected, invalid failover partner.";
3714 case FTR_TLS_UNSUPPORTED:
3715 return "TLS not supported.";
3717 case FTR_TLS_UNCONFIGURED:
3718 return "TLS supported but not configured.";
3720 case FTR_TLS_REQUIRED:
3721 return "TLS required but not supported by partner.";
3723 case FTR_DIGEST_UNSUPPORTED:
3724 return "Message digest not supported.";
3726 case FTR_DIGEST_UNCONFIGURED:
3727 return "Message digest not configured.";
3729 case FTR_VERSION_MISMATCH:
3730 return "Protocol version mismatch.";
3732 case FTR_OUTDATED_BIND_INFO:
3733 return "Outdated binding information.";
3735 case FTR_LESS_CRIT_BIND_INFO:
3736 return "Less critical binding information.";
3738 case FTR_NO_TRAFFIC:
3739 return "No traffic within sufficient time.";
3741 case FTR_HBA_CONFLICT:
3742 return "Hash bucket assignment conflict.";
3744 case FTR_IP_NOT_RESERVED:
3745 return "IP not reserved on this server.";
3747 case FTR_IP_DIGEST_FAILURE:
3748 return "Message digest failed to compare.";
3750 case FTR_IP_MISSING_DIGEST:
3751 return "Missing message digest.";
3754 return "Unknown Error.";
3757 sprintf(resbuf,
"Undefined-%d: This reason code is not defined in the "
3758 "protocol standard.", reason);
3768 return "unknown-state";
3771 return "partner-down";
3777 return "conflict-done";
3780 return "communications-interrupted";
3783 return "resolution-interrupted";
3786 return "potential-conflict";
3792 return "recover-done";
3795 return "recover-wait";
3810 static char messbuf[
sizeof(
"unknown-message-255")];
3813 return "invalid-message";
3817 return "pool-request";
3820 return "pool-response";
3823 return "bind-update";
3831 case FTM_CONNECTACK:
3832 return "connect-ack";
3835 return "update-request";
3838 return "update-done";
3841 return "update-request-all";
3849 case FTM_DISCONNECT:
3850 return "disconnect";
3853 sprintf(messbuf,
"unknown-message-%u", type);
3860 static char optbuf[
sizeof(
"unknown-option-65535")];
3863 return "invalid-option";
3866 case FTO_ADDRESSES_TRANSFERRED:
3867 return "addresses-transferred";
3869 case FTO_ASSIGNED_IP_ADDRESS:
3870 return "assigned-ip-address";
3872 case FTO_BINDING_STATUS:
3873 return "binding-status";
3875 case FTO_CLIENT_IDENTIFIER:
3876 return "client-identifier";
3887 case FTO_DELAYED_SERVICE:
3888 return "delayed-service";
3896 case FTO_LEASE_EXPIRY:
3897 return "lease-expiry";
3899 case FTO_MAX_UNACKED:
3900 return "max-unacked";
3908 case FTO_MESSAGE_DIGEST:
3909 return "message-digest";
3911 case FTO_POTENTIAL_EXPIRY:
3912 return "potential-expiry";
3914 case FTO_PROTOCOL_VERSION:
3915 return "protocol-version";
3917 case FTO_RECEIVE_TIMER:
3918 return "receive-timer";
3920 case FTO_REJECT_REASON:
3921 return "reject-reason";
3923 case FTO_RELATIONSHIP_NAME:
3924 return "relationship-name";
3926 case FTO_REPLY_OPTIONS:
3927 return "reply-options";
3929 case FTO_REQUEST_OPTIONS:
3930 return "request-options";
3932 case FTO_SERVER_FLAGS:
3933 return "server-flags";
3935 case FTO_SERVER_STATE:
3936 return "server-state";
3944 case FTO_TLS_REQUEST:
3945 return "tls-request";
3947 case FTO_VENDOR_CLASS:
3948 return "vendor-class";
3950 case FTO_VENDOR_OPTIONS:
3951 return "vendor-options";
3954 sprintf(optbuf,
"unknown-option-%u", type);
3963 const char *fmt, ...)
3976 if (vsnprintf (tbuf,
sizeof tbuf, fmt, va) >=
sizeof tbuf)
3977 log_fatal (
"%s: vsnprintf would truncate",
3978 "dhcp_failover_make_option");
3982 strlen (tbuf), tbuf);
3986 char *obuf,
unsigned *obufix,
3987 unsigned obufmax, ...)
3990 struct failover_option_info *info;
3992 unsigned size, count;
3998 #if defined (DEBUG_FAILOVER_MESSAGES)
4006 failover_option_t
option, *op;
4010 if (code < 1 || code > FTO_MAX || ft_options [code].type == FT_UNDEF) {
4013 info = &ft_options [code];
4015 va_start (va, obufmax);
4019 if (info -> type == FT_DDNS || info -> type == FT_DDNS1) {
4020 count = info -> type == FT_DDNS ? 1 : 2;
4021 size = va_arg (va,
int) + count;
4024 if (info -> num_present)
4025 count = info -> num_present;
4027 count = va_arg (va,
int);
4030 switch (info -> type) {
4037 case FT_TEXT_OR_BYTES:
4039 txt = va_arg (va,
char *);
4044 ilen = va_arg (va,
unsigned);
4045 size = count * ilen;
4058 log_fatal (
"bogus type in failover_make_option: %d",
4067 option.count = size;
4078 #if defined (DEBUG_FAILOVER_MESSAGES)
4086 if (snprintf (tbuf,
sizeof tbuf,
" (%s<%d>", info -> name,
4087 option.count) >=
sizeof tbuf)
4088 log_fatal (
"dhcp_failover_make_option: tbuf overflow");
4093 switch (info -> type) {
4095 for (i = 0; i < count; i++) {
4096 val = va_arg (va,
unsigned);
4097 #if defined (DEBUG_FAILOVER_MESSAGES)
4099 sprintf (tbuf,
" %d", val);
4102 option.data [i + 4] = val;
4107 for (i = 0; i < count; i++) {
4108 iaddr = va_arg (va, u_int8_t *);
4111 log_error (
"IP addrlen=%d, should be 4.",
4117 #if defined (DEBUG_FAILOVER_MESSAGES)
4119 sprintf (tbuf,
" %u.%u.%u.%u",
4120 iaddr [0], iaddr [1], iaddr [2], iaddr [3]);
4123 memcpy (&option.data [4 + i * ilen], iaddr, ilen);
4128 for (i = 0; i < count; i++) {
4129 val = va_arg (va,
unsigned);
4130 #if defined (DEBUG_FAILOVER_MESSAGES)
4132 sprintf (tbuf,
" %d", val);
4135 putULong (&option.data [4 + i * 4], val);
4141 bval = va_arg (va, u_int8_t *);
4142 #if defined (DEBUG_FAILOVER_MESSAGES)
4143 for (i = 0; i < count; i++) {
4145 sprintf (tbuf,
" %d", bval [i]);
4149 memcpy (&option.data [4], bval, count);
4156 case FT_TEXT_OR_BYTES:
4158 #if defined (DEBUG_FAILOVER_MESSAGES)
4166 if (snprintf (tbuf,
sizeof tbuf,
"\"%s\"", txt) >=
sizeof tbuf)
4167 log_fatal (
"dhcp_failover_make_option: tbuf overflow");
4170 memcpy (&option.data [4], txt, count);
4175 option.data [4] = va_arg (va,
unsigned);
4177 option.data [5] = va_arg (va,
unsigned);
4178 bval = va_arg (va, u_int8_t *);
4179 memcpy (&option.data [4 + count], bval, size - count - 4);
4180 #if defined (DEBUG_FAILOVER_MESSAGES)
4181 for (i = 4; i < size; i++) {
4183 sprintf (tbuf,
" %d", option.data [i]);
4190 for (i = 0; i < count; i++) {
4191 val = va_arg (va, u_int32_t);
4192 #if defined (DEBUG_FAILOVER_MESSAGES)
4194 sprintf (tbuf,
" %d", val);
4197 putUShort (&option.data [4 + i * 2], val);
4206 #if defined DEBUG_FAILOVER_MESSAGES
4212 op =
dmalloc (
sizeof (failover_option_t),
MDL);
4226 int msg_type, u_int32_t xid, ...)
4232 failover_option_t *option;
4233 unsigned char *opbuf;
4234 isc_result_t status = ISC_R_SUCCESS;
4240 va_start (list, xid);
4241 while ((option = va_arg (list, failover_option_t *))) {
4243 size += option -> count;
4250 if (!bad_option && size) {
4253 status = ISC_R_NOMEMORY;
4255 opbuf = (
unsigned char *)0;
4257 va_start (list, xid);
4258 while ((option = va_arg (list, failover_option_t *))) {
4261 if (!bad_option && opbuf)
4262 memcpy (&opbuf [opix],
4263 option -> data, option -> count);
4266 opix += option -> count;
4280 if (status != ISC_R_SUCCESS)
4286 if (status != ISC_R_SUCCESS)
4292 if (status != ISC_R_SUCCESS)
4297 if (status != ISC_R_SUCCESS)
4302 if (status != ISC_R_SUCCESS)
4308 if (status != ISC_R_SUCCESS)
4312 if (link -> state_object &&
4313 link -> state_object -> link_to_peer == link) {
4314 #if defined (DEBUG_FAILOVER_CONTACT_TIMING)
4316 (
int)(link -> state_object ->
4317 partner.max_response_delay) / 3,
4318 "dhcp_failover_send_contact");
4321 (
int)(link -> state_object ->
4322 partner.max_response_delay) / 3;
4326 (
tvref_t)dhcp_failover_state_reference,
4327 (
tvunref_t)dhcp_failover_state_dereference);
4334 log_info (
"dhcp_failover_put_message: something went wrong.");
4341 dhcp_failover_state_t *state = vstate;
4342 dhcp_failover_link_t *link;
4344 #if defined (DEBUG_FAILOVER_TIMING)
4345 log_info (
"dhcp_failover_timeout");
4350 link = state -> link_to_peer;
4356 log_error (
"timeout waiting for failover peer %s", state -> name);
4365 dhcp_failover_state_t *state = vstate;
4366 dhcp_failover_link_t *link;
4367 isc_result_t status;
4369 #if defined(DEBUG_FAILOVER_MESSAGES) && \
4370 defined(DEBUG_FAILOVER_CONTACT_MESSAGES)
4372 unsigned obufix = 0;
4377 #if defined (DEBUG_FAILOVER_CONTACT_TIMING)
4378 log_info (
"dhcp_failover_send_contact");
4383 link = state -> link_to_peer;
4390 (link, link -> outer,
4391 FTM_CONTACT, link->xid++,
4392 (failover_option_t *)0));
4394 #if defined(DEBUG_FAILOVER_MESSAGES) && \
4395 defined(DEBUG_FAILOVER_CONTACT_MESSAGES)
4396 if (status != ISC_R_SUCCESS)
4410 dhcp_failover_link_t *link;
4411 isc_result_t status;
4413 #if defined (DEBUG_FAILOVER_MESSAGES)
4415 unsigned obufix = 0;
4417 # define FMA obuf, &obufix, sizeof obuf
4420 # define FMA (char *)0, (unsigned *)0, 0
4425 link = state -> link_to_peer;
4432 (link, link -> outer,
4433 FTM_STATE, link->xid++,
4436 ? state -> saved_state
4437 : state -> me.state)),
4439 (FTO_SERVER_FLAGS, FMA,
4441 ? FTF_SERVER_STARTUP : 0)),
4443 (failover_option_t *)0));
4445 #if defined (DEBUG_FAILOVER_MESSAGES)
4446 if (status != ISC_R_SUCCESS)
4455 return ISC_R_SUCCESS;
4462 dhcp_failover_link_t *link;
4463 dhcp_failover_state_t *state;
4464 isc_result_t status;
4465 #if defined (DEBUG_FAILOVER_MESSAGES)
4467 unsigned obufix = 0;
4469 # define FMA obuf, &obufix, sizeof obuf
4472 # define FMA (char *)0, (unsigned *)0, 0
4477 link = (dhcp_failover_link_t *)l;
4478 state = link -> state_object;
4485 FTM_CONNECT, link->xid++,
4487 strlen(state->name), state->name),
4489 state -> me.max_flying_updates),
4491 state -> me.max_response_delay),
4495 DHCP_FAILOVER_VERSION),
4503 (failover_option_t *)0));
4505 #if defined (DEBUG_FAILOVER_MESSAGES)
4506 if (status != ISC_R_SUCCESS)
4517 dhcp_failover_state_t *state,
4518 int reason,
const char *errmsg)
4520 dhcp_failover_link_t *link;
4521 isc_result_t status;
4522 #if defined (DEBUG_FAILOVER_MESSAGES)
4524 unsigned obufix = 0;
4526 # define FMA obuf, &obufix, sizeof obuf
4529 # define FMA (char *)0, (unsigned *)0, 0
4534 link = (dhcp_failover_link_t *)l;
4541 FTM_CONNECTACK, link->imsg->xid,
4544 strlen(state->name), state->name)
4545 : (link->imsg->options_present & FTB_RELATIONSHIP_NAME)
4547 link->imsg->relationship_name.count,
4548 link->imsg->relationship_name.data)
4549 : &skip_failover_option,
4552 state -> me.max_flying_updates)
4553 : &skip_failover_option,
4556 state -> me.max_response_delay)
4557 : &skip_failover_option,
4561 DHCP_FAILOVER_VERSION),
4562 (link->imsg->options_present & FTB_TLS_REQUEST)
4565 : &skip_failover_option,
4569 : &skip_failover_option,
4572 strlen (errmsg), errmsg)
4573 : &skip_failover_option,
4574 (failover_option_t *)0));
4576 #if defined (DEBUG_FAILOVER_MESSAGES)
4577 if (status != ISC_R_SUCCESS)
4589 const char *message)
4591 dhcp_failover_link_t *link;
4592 isc_result_t status;
4593 #if defined (DEBUG_FAILOVER_MESSAGES)
4595 unsigned obufix = 0;
4597 # define FMA obuf, &obufix, sizeof obuf
4600 # define FMA (char *)0, (unsigned *)0, 0
4605 link = (dhcp_failover_link_t *)l;
4609 if (!message && reason)
4614 FTM_DISCONNECT, link->xid++,
4619 strlen (message), message)
4620 : &skip_failover_option),
4621 (failover_option_t *)0));
4623 #if defined (DEBUG_FAILOVER_MESSAGES)
4624 if (status != ISC_R_SUCCESS)
4637 struct lease *lease)
4639 dhcp_failover_link_t *link;
4640 isc_result_t status;
4643 #if defined (DEBUG_FAILOVER_MESSAGES)
4645 unsigned obufix = 0;
4647 # define FMA obuf, &obufix, sizeof obuf
4650 # define FMA (char *)0, (unsigned *)0, 0
4653 if (!state -> link_to_peer ||
4656 link = (dhcp_failover_link_t *)state -> link_to_peer;
4668 if ((state->i_am == primary) && (transmit_state ==
FTS_FREE))
4670 else if ((state->i_am == secondary) &&
4674 flags |= FTF_IP_FLAG_RESERVE;
4677 flags |= FTF_IP_FLAG_BOOTP;
4717 (link, link -> outer,
4723 lease -> desired_binding_state),
4728 : &skip_failover_option,
4729 lease -> hardware_addr.hlen
4731 lease -> hardware_addr.hlen,
4732 lease -> hardware_addr.hbuf)
4733 : &skip_failover_option,
4740 (lease->
cltt != 0) ?
4742 &skip_failover_option,
4745 &skip_failover_option,
4746 &skip_failover_option,
4747 &skip_failover_option,
4748 &skip_failover_option,
4749 (failover_option_t *)0));
4751 #if defined (DEBUG_FAILOVER_MESSAGES)
4752 if (status != ISC_R_SUCCESS)
4765 failover_message_t *msg,
4766 int reason,
const char *message)
4768 dhcp_failover_link_t *link;
4769 isc_result_t status;
4770 #if defined (DEBUG_FAILOVER_MESSAGES)
4772 unsigned obufix = 0;
4774 # define FMA obuf, &obufix, sizeof obuf
4777 # define FMA (char *)0, (unsigned *)0, 0
4780 if (!state -> link_to_peer ||
4783 link = (dhcp_failover_link_t *)state -> link_to_peer;
4788 if (!message && reason)
4793 (link, link -> outer,
4794 FTM_BNDACK, msg->xid,
4796 sizeof msg -> assigned_addr,
4797 &msg -> assigned_addr),
4798 #ifdef DO_BNDACK_SHOULD_NOT
4800 msg -> binding_status),
4801 (msg -> options_present & FTB_CLIENT_IDENTIFIER)
4803 msg -> client_identifier.count,
4804 msg -> client_identifier.data)
4805 : &skip_failover_option,
4806 (msg -> options_present & FTB_CHADDR)
4808 msg -> chaddr.count,
4810 : &skip_failover_option,
4814 msg -> potential_expiry),
4817 (msg->options_present & FTB_CLTT) ?
4819 &skip_failover_option,
4820 ((msg->options_present & FTB_IP_FLAGS) && msg->ip_flags) ?
4823 : &skip_failover_option,
4827 : &skip_failover_option,
4830 strlen (message), message)
4831 : &skip_failover_option,
4832 #ifdef DO_BNDACK_SHOULD_NOT
4833 &skip_failover_option,
4834 &skip_failover_option,
4835 &skip_failover_option,
4837 (failover_option_t *)0));
4839 #if defined (DEBUG_FAILOVER_MESSAGES)
4840 if (status != ISC_R_SUCCESS)
4852 dhcp_failover_link_t *link;
4853 isc_result_t status;
4854 #if defined (DEBUG_FAILOVER_MESSAGES)
4856 unsigned obufix = 0;
4858 # define FMA obuf, &obufix, sizeof obuf
4861 # define FMA (char *)0, (unsigned *)0, 0
4864 if (!state -> link_to_peer ||
4867 link = (dhcp_failover_link_t *)state -> link_to_peer;
4873 (link, link -> outer,
4874 FTM_POOLREQ, link->xid++,
4875 (failover_option_t *)0));
4877 #if defined (DEBUG_FAILOVER_MESSAGES)
4878 if (status != ISC_R_SUCCESS)
4891 dhcp_failover_link_t *link;
4892 isc_result_t status;
4893 #if defined (DEBUG_FAILOVER_MESSAGES)
4895 unsigned obufix = 0;
4897 # define FMA obuf, &obufix, sizeof obuf
4900 # define FMA (char *)0, (unsigned *)0, 0
4903 if (!state -> link_to_peer ||
4906 link = (dhcp_failover_link_t *)state -> link_to_peer;
4912 (link, link -> outer,
4913 FTM_POOLRESP, link->imsg->xid,
4916 (failover_option_t *)0));
4918 #if defined (DEBUG_FAILOVER_MESSAGES)
4919 if (status != ISC_R_SUCCESS)
4931 dhcp_failover_link_t *link;
4932 isc_result_t status;
4933 #if defined (DEBUG_FAILOVER_MESSAGES)
4935 unsigned obufix = 0;
4937 # define FMA obuf, &obufix, sizeof obuf
4940 # define FMA (char *)0, (unsigned *)0, 0
4943 if (!state->link_to_peer ||
4946 link = (dhcp_failover_link_t *)state->link_to_peer;
4954 if (state->curUPD == FTM_UPDREQALL) {
4959 link->xid++, NULL));
4961 state->curUPD = FTM_UPDREQ;
4963 #if defined (DEBUG_FAILOVER_MESSAGES)
4964 if (status != ISC_R_SUCCESS)
4972 if (status == ISC_R_SUCCESS) {
4973 log_info(
"Sent update request message to %s", state->name);
4975 log_error(
"Failed to send update request all message to %s: %s",
4976 state->name, isc_result_totext(status));
4984 dhcp_failover_link_t *link;
4985 isc_result_t status;
4986 #if defined (DEBUG_FAILOVER_MESSAGES)
4988 unsigned obufix = 0;
4990 # define FMA obuf, &obufix, sizeof obuf
4993 # define FMA (char *)0, (unsigned *)0, 0
4996 if (!state->link_to_peer ||
4999 link = (dhcp_failover_link_t *)state->link_to_peer;
5009 link->xid++, NULL));
5011 state->curUPD = FTM_UPDREQALL;
5013 #if defined (DEBUG_FAILOVER_MESSAGES)
5014 if (status != ISC_R_SUCCESS)
5022 if (status == ISC_R_SUCCESS) {
5023 log_info(
"Sent update request all message to %s", state->name);
5025 log_error(
"Failed to send update request all message to %s: %s",
5026 state->name, isc_result_totext(status));
5033 dhcp_failover_link_t *link;
5034 isc_result_t status;
5035 #if defined (DEBUG_FAILOVER_MESSAGES)
5037 unsigned obufix = 0;
5039 # define FMA obuf, &obufix, sizeof obuf
5042 # define FMA (char *)0, (unsigned *)0, 0
5045 if (!state -> link_to_peer ||
5048 link = (dhcp_failover_link_t *)state -> link_to_peer;
5054 (link, link -> outer,
5055 FTM_UPDDONE, state->updxid,
5056 (failover_option_t *)0));
5058 #if defined (DEBUG_FAILOVER_MESSAGES)
5059 if (status != ISC_R_SUCCESS)
5067 log_info (
"Sent update done message to %s", state -> name);
5091 static isc_boolean_t
5092 failover_lease_is_better(dhcp_failover_state_t *state,
struct lease *lease,
5093 failover_message_t *msg)
5103 if ((msg->options_present & FTB_CLTT) != 0)
5104 msg_cltt = msg->cltt;
5108 switch(local_state) {
5111 if (msg_cltt < lease->cltt)
5113 else if (msg_cltt > lease->
cltt)
5115 else if (state->i_am == primary)
5132 else if (state->i_am == primary)
5148 failover_message_t *msg)
5150 struct lease *lt = NULL, *lease = NULL;
5152 int reason = FTR_MISC_REJECT;
5153 const char *message;
5154 int new_binding_state;
5155 int send_to_backup = 0;
5156 int required_options;
5157 isc_boolean_t chaddr_changed = ISC_FALSE;
5158 isc_boolean_t ident_changed = ISC_FALSE;
5161 required_options = FTB_ASSIGNED_IP_ADDRESS | FTB_BINDING_STATUS;
5162 if ((msg->options_present & required_options) != required_options) {
5163 message =
"binding update lacks required options";
5164 reason = FTR_MISSING_BINDINFO;
5168 ia.len =
sizeof msg -> assigned_addr;
5169 memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
5172 message =
"unknown IP address";
5173 reason = FTR_ILLEGAL_IP_ADDR;
5181 if ((lease->pool == NULL) || (lease->pool->failover_peer == NULL) ||
5182 (lease->pool->failover_peer != state)) {
5183 message =
"IP address is covered by a different failover "
5184 "relationship state";
5185 reason = FTR_ILLEGAL_IP_ADDR;
5199 if ((lease->flags & ON_ACK_QUEUE) != 0) {
5200 if (failover_lease_is_better(state, lease, msg)) {
5201 message =
"incoming update is less critical than "
5203 reason = FTR_LESS_CRIT_BIND_INFO;
5213 message =
"no memory";
5217 if (msg -> options_present & FTB_CHADDR) {
5219 message =
"BNDUPD to ABANDONED with a CHADDR";
5222 if (msg -> chaddr.count >
sizeof lt -> hardware_addr.hbuf) {
5223 message =
"chaddr too long";
5229 msg->chaddr.count) != 0))
5230 chaddr_changed = ISC_TRUE;
5232 lt -> hardware_addr.hlen = msg -> chaddr.count;
5233 memcpy (lt -> hardware_addr.hbuf, msg -> chaddr.data,
5234 msg -> chaddr.count);
5235 }
else if (msg->binding_status ==
FTS_ACTIVE ||
5238 message =
"BNDUPD without CHADDR";
5239 reason = FTR_MISSING_BINDINFO;
5242 chaddr_changed = ISC_TRUE;
5252 if (msg->options_present & FTB_CLIENT_IDENTIFIER) {
5254 message =
"BNDUPD to ABANDONED with client-id";
5258 if ((lt->
uid_len != msg->client_identifier.count) ||
5259 (lt->
uid == NULL) ||
5260 (memcmp(lt->
uid, msg->client_identifier.data,
5262 ident_changed = ISC_TRUE;
5264 lt->
uid_len = msg->client_identifier.count;
5279 message =
"no memory";
5288 msg -> client_identifier.data, lt -> uid_len);
5289 }
else if (lt->
uid && msg->binding_status !=
FTS_RESET &&
5292 ident_changed = ISC_TRUE;
5325 (chaddr_changed || ident_changed)) {
5326 #if defined (NSUPDATE)
5330 if (lease->scope != NULL)
5335 if (msg -> options_present & FTB_STOS) {
5336 lt -> starts = msg -> stos;
5338 if (msg -> options_present & FTB_LEASE_EXPIRY) {
5339 lt -> ends = msg -> expiry;
5341 if (msg->options_present & FTB_POTENTIAL_EXPIRY) {
5342 lt->
atsfp = lt->
tsfp = msg->potential_expiry;
5344 if (msg->options_present & FTB_IP_FLAGS) {
5345 if (msg->ip_flags & FTF_IP_FLAG_RESERVE) {
5346 if ((((state->i_am == primary) &&
5347 (lease->binding_state ==
FTS_FREE)) ||
5348 ((state->i_am == secondary) &&
5351 message =
"Address is not reserved.";
5352 reason = FTR_IP_NOT_RESERVED;
5360 if (msg->ip_flags & FTF_IP_FLAG_BOOTP) {
5361 if ((((state->i_am == primary) &&
5362 (lease->binding_state ==
FTS_FREE)) ||
5363 ((state->i_am == secondary) &&
5366 message =
"Address is not allocated to BOOTP.";
5373 if (msg->ip_flags & ~(FTF_IP_FLAG_RESERVE | FTF_IP_FLAG_BOOTP))
5374 log_info(
"Unknown IP-flags set in BNDUPD (0x%x).",
5379 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
5380 log_info (
"processing state transition for %s: %s to %s",
5388 if (state -> me.state ==
normal) {
5391 (lease, state, msg -> binding_status,
5392 msg -> potential_expiry));
5399 (lease, state, msg -> binding_status,
5400 msg -> potential_expiry));
5402 if (new_binding_state != msg -> binding_status) {
5405 if (snprintf (outbuf,
sizeof outbuf,
5406 "%s: invalid state transition: %s to %s",
5411 log_fatal (
"%s: impossible outbuf overflow",
5412 "dhcp_failover_process_bind_update");
5422 lt -> next_binding_state =
FTS_FREE;
5429 if ((state->i_am == primary) &&
5433 lt -> next_binding_state = new_binding_state;
5435 msg -> binding_status = lt -> next_binding_state;
5446 message =
"database update failed";
5457 if (send_to_backup && secondary_not_hoarding(state, lease->pool)) {
5464 log_error(
"can't commit lease %s for mac addr "
5465 "affinity",
piaddr(lease->ip_addr));
5472 lease_dereference (<,
MDL);
5474 lease_dereference (&lease,
MDL);
5476 return ISC_R_SUCCESS;
5485 secondary_not_hoarding(dhcp_failover_state_t *state,
struct pool *p) {
5493 hold = ((total * state->max_lease_ownership) + 50) / 100;
5504 return(lts > -hold);
5508 failover_message_t *msg)
5510 struct lease *lt = (
struct lease *)0;
5511 struct lease *lease = (
struct lease *)0;
5513 const char *message =
"no memory";
5514 u_int32_t pot_expire;
5515 int send_to_backup = ISC_FALSE;
5518 ia.len =
sizeof msg -> assigned_addr;
5519 memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
5522 message =
"no such lease";
5527 if (msg -> options_present & FTB_REJECT_REASON) {
5528 log_error (
"bind update on %s from %s rejected: %.*s",
5529 piaddr (ia), state -> name,
5530 (
int)((msg -> options_present & FTB_MESSAGE)
5531 ? msg -> message.count
5533 (msg -> reject_reason))),
5534 (msg -> options_present & FTB_MESSAGE)
5535 ? (
const char *)(msg -> message.data)
5537 (msg -> reject_reason)));
5548 message =
"xid mismatch";
5553 if (msg->options_present & FTO_POTENTIAL_EXPIRY)
5554 pot_expire = msg->potential_expiry;
5556 pot_expire = lease->
tstp;
5576 lease->
atsfp = lease->
tsfp = pot_expire;
5577 if ((state->i_am == secondary) &&
5599 if (state->i_am == primary &&
5602 send_to_backup = ISC_TRUE;
5604 if (!send_to_backup && state->me.state ==
normal)
5610 lease->
atsfp = lease->
tsfp = pot_expire;
5632 if (state -> send_update_done == lease) {
5633 lease_dereference (&state -> send_update_done,
MDL);
5640 if (send_to_backup && secondary_not_hoarding(state, lease->
pool)) {
5649 if (state->me.state ==
normal)
5658 lease_dereference (&lease,
MDL);
5660 lease_dereference (<,
MDL);
5662 return ISC_R_SUCCESS;
5665 log_info (
"bind update on %s got ack from %s: %s.",
5666 piaddr (ia), state -> name, message);
5677 #define FREE_LEASES 0
5678 #define ACTIVE_LEASES 1
5679 #define EXPIRED_LEASES 2
5680 #define ABANDONED_LEASES 3
5681 #define BACKUP_LEASES 4
5682 #define RESERVED_LEASES 5
5688 for (p = s ->
pools; p; p = p ->
next) {
5714 return ISC_R_SUCCESS;
5719 failover_message_t *msg)
5721 if (state->send_update_done) {
5722 log_info(
"Received update request while old update still "
5723 "flying! Silently discarding old request.");
5724 lease_dereference(&state->send_update_done,
MDL);
5730 state->updxid = msg->xid;
5735 if (state -> update_queue_tail) {
5736 lease_reference (&state -> send_update_done,
5737 state -> update_queue_tail,
MDL);
5739 log_info (
"Update request from %s: sending update",
5745 log_info (
"Update request from %s: nothing pending",
5749 return ISC_R_SUCCESS;
5754 failover_message_t *msg)
5756 if (state->send_update_done) {
5757 log_info(
"Received update request while old update still "
5758 "flying! Silently discarding old request.");
5759 lease_dereference(&state->send_update_done,
MDL);
5765 state->updxid = msg->xid;
5767 if (state -> update_queue_tail) {
5768 lease_reference (&state -> send_update_done,
5769 state -> update_queue_tail,
MDL);
5771 log_info (
"Update request all from %s: sending update",
5777 log_info (
"Update request all from %s: nothing pending",
5781 return ISC_R_SUCCESS;
5786 failover_message_t *msg)
5790 log_info (
"failover peer %s: peer update completed.",
5793 state -> curUPD = 0;
5795 switch (state -> me.state) {
5811 if (state->i_am == secondary) {
5814 log_error(
"Secondary is in conflict_done "
5815 "state after conflict resolution, "
5816 "this is illegal.");
5820 if (state->i_am == primary)
5823 log_error(
"Spurious update-done message.");
5829 log_error(
"Spurious update-done message.");
5838 if (state -> me.stos + state -> mclt >
cur_time &&
5839 state -> partner.state !=
recover &&
5842 #if defined (DEBUG_FAILOVER_TIMING)
5845 state -> me.stos + state -> mclt),
5846 "dhcp_failover_recover_done");
5848 tv . tv_sec = (
int)(state -> me.stos + state -> mclt);
5853 (
tvref_t)omapi_object_reference,
5860 return ISC_R_SUCCESS;
5865 dhcp_failover_state_t *state = sp;
5867 #if defined (DEBUG_FAILOVER_TIMING)
5868 log_info (
"dhcp_failover_recover_done");
5874 #if defined (DEBUG_FAILOVER_MESSAGES)
5881 unsigned *obufix,
unsigned obufmax,
const char *s)
5883 int len = strlen (s);
5885 while (len + *obufix + 1 >= obufmax) {
5894 strcpy (&obuf [*obufix], s);
5901 unsigned char loadb_mx_tbl[256] = {
5902 251, 175, 119, 215, 81, 14, 79, 191, 103, 49,
5903 181, 143, 186, 157, 0, 232, 31, 32, 55, 60,
5904 152, 58, 17, 237, 174, 70, 160, 144, 220, 90,
5905 57, 223, 59, 3, 18, 140, 111, 166, 203, 196,
5906 134, 243, 124, 95, 222, 179, 197, 65, 180, 48,
5907 36, 15, 107, 46, 233, 130, 165, 30, 123, 161,
5908 209, 23, 97, 16, 40, 91, 219, 61, 100, 10,
5909 210, 109, 250, 127, 22, 138, 29, 108, 244, 67,
5910 207, 9, 178, 204, 74, 98, 126, 249, 167, 116,
5911 34, 77, 193, 200, 121, 5, 20, 113, 71, 35,
5912 128, 13, 182, 94, 25, 226, 227, 199, 75, 27,
5913 41, 245, 230, 224, 43, 225, 177, 26, 155, 150,
5914 212, 142, 218, 115, 241, 73, 88, 105, 39, 114,
5915 62, 255, 192, 201, 145, 214, 168, 158, 221, 148,
5916 154, 122, 12, 84, 82, 163, 44, 139, 228, 236,
5917 205, 242, 217, 11, 187, 146, 159, 64, 86, 239,
5918 195, 42, 106, 198, 118, 112, 184, 172, 87, 2,
5919 173, 117, 176, 229, 247, 253, 137, 185, 99, 164,
5920 102, 147, 45, 66, 231, 52, 141, 211, 194, 206,
5921 246, 238, 56, 110, 78, 248, 63, 240, 189, 93,
5922 92, 51, 53, 183, 19, 171, 72, 50, 33, 104,
5923 101, 69, 8, 252, 83, 120, 76, 135, 85, 54,
5924 202, 125, 188, 213, 96, 235, 136, 208, 162, 129,
5925 190, 132, 156, 38, 47, 1, 7, 254, 24, 4,
5926 216, 131, 89, 21, 28, 133, 37, 153, 149, 80,
5927 170, 68, 6, 169, 234, 151 };
5929 static unsigned char loadb_p_hash (
const unsigned char *,
unsigned);
5930 static unsigned char loadb_p_hash (
const unsigned char *key,
unsigned len)
5932 unsigned char hash = len;
5934 for(i = len; i > 0; )
5935 hash = loadb_mx_tbl [hash ^ (key [--i])];
5943 unsigned char hbaix;
5947 ec = ntohs(packet->
raw->
secs);
5949 #if defined(SECS_BYTEORDER)
5956 if ((ec > 255) && ((ec & 0xff) == 0)) {
5957 ec = (ec >> 8) | (ec << 8);
5961 if (state->load_balance_max_secs < ec) {
5975 memset(&ds, 0,
sizeof ds);
5980 hbaix = loadb_p_hash(ds.data, ds.len);
5984 hbaix = loadb_p_hash(packet->
raw->
chaddr,
5988 hm = state->hba[(hbaix >> 3) & 0x1F] & (1 << (hbaix & 0x07));
5990 if (state->i_am == primary)
6004 dhcp_failover_state_t *state;
6005 unsigned char hbaix;
6013 if (!state || !state->hba)
6030 hm = state->hba[(hbaix >> 3) & 0x1F] & (1 << (hbaix & 0x07));
6032 if (state->i_am == primary)
6046 dhcp_failover_state_t *state,
6053 if (binding_state == lease -> binding_state)
6054 return binding_state;
6056 switch (lease -> binding_state) {
6059 switch (binding_state) {
6070 if (state -> i_am == secondary)
6071 return binding_state;
6079 new_state = binding_state;
6089 if (state -> i_am == primary) {
6093 return binding_state;
6094 new_state = lease -> binding_state;
6099 switch (binding_state) {
6105 new_state = lease -> binding_state;
6108 return binding_state;
6116 if (lease -> ends - 65 >
cur_time) {
6117 new_state = lease -> binding_state;
6125 return binding_state;
6133 switch (binding_state) {
6139 new_state = lease -> binding_state;
6142 return binding_state;
6149 return binding_state;
6156 switch (binding_state) {
6167 return binding_state;
6174 switch (binding_state) {
6180 new_state = lease -> binding_state;
6183 return binding_state;
6190 return binding_state;
6197 switch (binding_state) {
6206 if (state -> i_am == primary)
6207 return binding_state;
6213 return binding_state;
6216 new_state = lease -> binding_state;
6236 dhcp_failover_state_t *state,
6243 if (binding_state == lease -> binding_state)
6244 new_state = binding_state;
6246 switch (lease -> binding_state) {
6256 new_state = binding_state;
6263 switch (binding_state) {
6266 new_state = lease -> binding_state;
6278 new_state = binding_state;
6289 new_state = binding_state;
6324 dhcp_failover_state_t *peer;
6326 if (lease && lease->
pool &&
6350 if (peer -> i_am == primary)
6354 ((lease->
tsfp < peer->me.stos) ?
6355 (peer->me.stos + peer->mclt <
cur_time) :
6374 if ((peer->i_am == primary) &&
6377 if ((peer->i_am == secondary) &&
6408 if (peer->i_am == secondary)
6412 ((lease->
tsfp < peer->me.stos) ?
6413 (peer->me.stos + peer->mclt <
cur_time) :
6430 static isc_result_t failover_message_reference (failover_message_t **mp,
6431 failover_message_t *m,
6432 const char *file,
int line)
6436 return ISC_R_SUCCESS;
6439 static isc_result_t failover_message_dereference (failover_message_t **mp,
6440 const char *file,
int line)
6442 failover_message_t *m;
6445 if (m -> refcnt == 0) {
6447 failover_message_dereference (&m -> next,
6449 if (m -> chaddr.data)
6450 dfree (m -> chaddr.data, file, line);
6451 if (m -> client_identifier.data)
6452 dfree (m -> client_identifier.data, file, line);
6454 dfree (m -> hba.data, file, line);
6455 if (m -> message.data)
6456 dfree (m -> message.data, file, line);
6457 if (m -> relationship_name.data)
6458 dfree (m -> relationship_name.data, file, line);
6459 if (m -> reply_options.data)
6460 dfree (m -> reply_options.data, file, line);
6461 if (m -> request_options.data)
6462 dfree (m -> request_options.data, file, line);
6463 if (m -> vendor_class.data)
6464 dfree (m -> vendor_class.data, file, line);
6465 if (m -> vendor_options.data)
6466 dfree (m -> vendor_options.data, file, line);
6469 dfree (*mp, file, line);
6472 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)
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
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)
void(* tvref_t)(void *, void *, const char *, int)
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(* tvunref_t)(void *, const char *, int)
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)
#define LEASE_GET_FIRST(LQ)
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)
#define LEASE_GET_FIRSTP(LQ)
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 *)
#define LEASE_GET_NEXTP(LQ, LEASE)
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 **)
#define LEASE_GET_NEXT(LQ, LEASE)
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)