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.");
633 link -> imsg_count += 2;
635 if (link -> imsg_count + 2 > link -> imsg_len) {
636 log_error (
"FAILOVER: message overflow at length.");
642 link -> imsg_count += 2;
644 if (link -> imsg_count + option_len > link -> imsg_len) {
645 log_error (
"FAILOVER: message overflow at data.");
650 if ((option_code > FTO_MAX) ||
652 #if defined (DEBUG_FAILOVER_MESSAGES) 653 log_debug (
" option code %d (%s) len %d (not recognized)",
659 link -> imsg_count += option_len;
660 return ISC_R_SUCCESS;
664 if (
ft_options [option_code].type == FT_DIGEST) {
665 link -> imsg_count += option_len;
666 if (link -> imsg_count != link -> imsg_len) {
667 log_error (
"FAILOVER: digest not at end of message");
670 #if defined (DEBUG_FAILOVER_MESSAGES) 676 return ISC_R_SUCCESS;
680 if (link -> imsg -> options_present &
ft_options [option_code].bit) {
681 log_error (
"FAILOVER: duplicate option %s",
696 link -> imsg_count += option_len;
697 return ISC_R_SUCCESS;
707 op = ((
unsigned char *)link -> imsg) +
710 op_count = ft_options [option_code].num_present;
712 if (option_len != op_size * op_count) {
713 log_error (
"FAILOVER: option size (%d:%d), option %s",
715 (
ft_sizes [ft_options [option_code].type] *
716 ft_options [option_code].num_present),
717 ft_options [option_code].name);
721 failover_option_t *fo;
725 if (ft_options [option_code].type == FT_DDNS1 ||
726 ft_options [option_code].type == FT_DDNS1) {
729 (((
char *)link -> imsg) +
730 ft_options [option_code].offset));
732 op_count = (ft_options [option_code].type == FT_DDNS1
737 link -> imsg_count += op_count;
739 ddns -> codes [1] = 0;
741 op_count = option_len - op_count;
743 ddns -> length = op_count;
746 log_error (
"FAILOVER: no memory getting%s(%d)",
747 " DNS data ", op_count);
762 op_size =
ft_sizes [ft_options [option_code].type];
766 if (op_size > 1 && option_len % op_size) {
767 log_error (
"FAILOVER: option_len %d not %s%d",
768 option_len,
"multiple of ", op_size);
772 op_count = option_len / op_size;
774 fo = ((failover_option_t *)
775 (((
char *)link -> imsg) +
776 ft_options [option_code].offset));
778 fo -> count = op_count;
781 log_error (
"FAILOVER: no memory getting %s (%d)",
782 "option data", op_count);
791 if (op_size == 1 || ft_options [option_code].type == FT_IPADDR) {
793 link -> imsg_count += option_len;
816 if ((option_code == 11) && (option_len > 9) &&
817 (strncmp((
const char *)op,
"isc-V3.0.", 9) == 0)) {
818 log_error(
"WARNING: failover as of versions 3.1.0 and " 819 "on are not reverse compatible with " 828 for (i = 0; i < op_count; i++) {
829 switch (ft_options [option_code].type) {
833 link -> imsg_count += 4;
839 link -> imsg_count += 2;
845 log_error (
"FAILOVER: option %s: bad type %d",
846 ft_options [option_code].name,
847 ft_options [option_code].type);
853 link -> imsg -> options_present |= ft_options [option_code].bit;
854 return ISC_R_SUCCESS;
871 if (h -> inner && h -> inner -> type -> set_value)
872 return (*(h -> inner -> type -> set_value))
873 (h -> inner, id, name, value);
874 return ISC_R_NOTFOUND;
882 dhcp_failover_link_t *link;
886 link = (dhcp_failover_link_t *)h;
890 (
int)link -> peer_port,
MDL);
892 if (link -> state >= dhcp_flink_state_max)
894 "invalid link state",
901 if (h -> inner && h -> inner -> type -> get_value)
902 return (*(h -> inner -> type -> get_value))
903 (h -> inner, id, name, value);
904 return ISC_R_NOTFOUND;
908 const char *file,
int line)
910 dhcp_failover_link_t *link;
913 link = (dhcp_failover_link_t *)h;
915 if (link -> peer_address)
918 failover_message_dereference (&link -> imsg, file, line);
919 if (link -> state_object)
920 dhcp_failover_state_dereference (&link -> state_object,
922 return ISC_R_SUCCESS;
932 dhcp_failover_link_t *link;
937 link = (dhcp_failover_link_t *)l;
940 if (status != ISC_R_SUCCESS)
943 if (status != ISC_R_SUCCESS)
946 if (status != ISC_R_SUCCESS)
950 if (status != ISC_R_SUCCESS)
952 if (link -> state >= dhcp_flink_state_max)
957 if (status != ISC_R_SUCCESS)
960 if (link -> inner && link -> inner -> type -> stuff_values)
961 return (*(link -> inner -> type -> stuff_values)) (c,
id,
963 return ISC_R_SUCCESS;
978 "local-port", &value);
979 if (status != ISC_R_SUCCESS)
981 if (!value -> value) {
988 if (status != ISC_R_SUCCESS)
990 local_addr.
port = port;
993 "local-address", &value);
994 if (status != ISC_R_SUCCESS)
996 if (!value -> value) {
1003 value -> value -> u.buffer.len != sizeof (
struct in_addr))
1006 memcpy (local_addr.
address, value -> value -> u.buffer.
value,
1007 value -> value -> u.buffer.len);
1008 local_addr.
addrlen = value -> value -> u.buffer.len;
1014 for (l = failover_listeners; l; l = l -> next) {
1015 if (l -> address.port == local_addr.
port &&
1016 l -> address.addrtype == local_addr.
addrtype &&
1017 l -> address.addrlen == local_addr.
addrlen &&
1018 !memcmp (l -> address.address, local_addr.
address,
1024 return ISC_R_SUCCESS;
1027 status = dhcp_failover_listener_allocate (&obj,
MDL);
1028 if (status != ISC_R_SUCCESS)
1030 obj -> address = local_addr;
1033 if (status != ISC_R_SUCCESS)
1038 if (status != ISC_R_SUCCESS) {
1039 dhcp_failover_listener_dereference (&obj,
MDL);
1043 if (status != ISC_R_SUCCESS) {
1044 dhcp_failover_listener_dereference (&obj,
MDL);
1049 if (failover_listeners) {
1050 dhcp_failover_listener_reference (&obj -> next,
1051 failover_listeners,
MDL);
1052 dhcp_failover_listener_dereference (&failover_listeners,
MDL);
1054 dhcp_failover_listener_reference (&failover_listeners, obj,
MDL);
1056 return dhcp_failover_listener_dereference (&obj,
MDL);
1063 const char *name, va_list ap)
1065 isc_result_t status;
1067 dhcp_failover_link_t *obj;
1069 dhcp_failover_state_t *s, *state = (dhcp_failover_state_t *)0;
1076 if (strcmp (name,
"connect")) {
1077 if (p -> inner && p -> inner -> type -> signal_handler)
1078 return (*(p -> inner -> type -> signal_handler))
1079 (p -> inner, name, ap);
1080 return ISC_R_NOTFOUND;
1091 (s, (u_int8_t *)&c -> remote_addr.sin_addr,
1092 sizeof c -> remote_addr.sin_addr)) {
1098 log_info (
"failover: listener: no matching state");
1100 return(ISC_R_NOTFOUND);
1103 obj = (dhcp_failover_link_t *)0;
1104 status = dhcp_failover_link_allocate (&obj,
MDL);
1105 if (status != ISC_R_SUCCESS)
1107 obj -> peer_port = ntohs (c -> remote_addr.sin_port);
1111 if (status != ISC_R_SUCCESS) {
1113 dhcp_failover_link_dereference (&obj,
MDL);
1114 log_info (
"failover: listener: picayune failure.");
1121 if (status != ISC_R_SUCCESS)
1124 status = dhcp_failover_state_reference (&obj -> state_object,
1126 if (status != ISC_R_SUCCESS)
1131 return dhcp_failover_link_dereference (&obj,
MDL);
1142 if (h -> inner && h -> inner -> type -> set_value)
1143 return (*(h -> inner -> type -> set_value))
1144 (h -> inner, id, name, value);
1145 return ISC_R_NOTFOUND;
1156 if (h -> inner && h -> inner -> type -> get_value)
1157 return (*(h -> inner -> type -> get_value))
1158 (h -> inner, id, name, value);
1159 return ISC_R_NOTFOUND;
1163 const char *file,
int line)
1171 dhcp_failover_listener_dereference (&l -> next, file, line);
1173 return ISC_R_SUCCESS;
1186 if (p -> inner && p -> inner -> type -> stuff_values)
1187 return (*(p -> inner -> type -> stuff_values)) (c, id,
1189 return ISC_R_SUCCESS;
1196 isc_result_t status;
1197 dhcp_failover_state_t *obj;
1202 "local-port", &value);
1203 if (status != ISC_R_SUCCESS)
1205 if (!value -> value) {
1212 if (status != ISC_R_SUCCESS)
1215 obj = (dhcp_failover_state_t *)0;
1216 dhcp_failover_state_allocate (&obj,
MDL);
1217 obj -> me.port = port;
1220 if (status != ISC_R_SUCCESS) {
1221 dhcp_failover_state_dereference (&obj,
MDL);
1227 if (status != ISC_R_SUCCESS) {
1228 dhcp_failover_state_dereference (&obj,
MDL);
1232 dhcp_failover_state_dereference (&obj,
MDL);
1239 const char *name, va_list ap)
1241 isc_result_t status;
1242 dhcp_failover_state_t *state;
1243 dhcp_failover_link_t *link;
1248 state = (dhcp_failover_state_t *)o;
1251 if (strcmp (name,
"disconnect") &&
1252 strcmp (name,
"message")) {
1253 if (state -> inner && state -> inner -> type -> signal_handler)
1254 return (*(state -> inner -> type -> signal_handler))
1255 (state -> inner, name, ap);
1256 return ISC_R_NOTFOUND;
1261 if (!strcmp (name,
"disconnect")) {
1262 link = va_arg (ap, dhcp_failover_link_t *);
1264 dhcp_failover_link_dereference (&state -> link_to_peer,
MDL);
1266 if (state -> i_am == primary) {
1267 #if defined (DEBUG_FAILOVER_TIMING) 1269 "dhcp_failover_reconnect");
1275 (
tvref_t)dhcp_failover_state_reference,
1277 dhcp_failover_state_dereference);
1279 }
else if (!strcmp (name,
"message")) {
1280 link = va_arg (ap, dhcp_failover_link_t *);
1282 if (link -> imsg -> type == FTM_CONNECT) {
1288 if (state -> link_to_peer) {
1292 "already connected");
1294 return ISC_R_SUCCESS;
1296 if (!(link -> imsg -> options_present & FTB_MCLT)) {
1300 "no MCLT provided");
1302 return ISC_R_SUCCESS;
1305 dhcp_failover_link_reference (&state -> link_to_peer,
1309 if (status != ISC_R_SUCCESS) {
1310 dhcp_failover_link_dereference
1311 (&state -> link_to_peer,
MDL);
1312 log_info (
"dhcp_failover_send_connectack: %s",
1313 isc_result_totext (status));
1315 return ISC_R_SUCCESS;
1317 if (link -> imsg -> options_present & FTB_MAX_UNACKED)
1318 state -> partner.max_flying_updates =
1319 link -> imsg -> max_unacked;
1320 if (link -> imsg -> options_present & FTB_RECEIVE_TIMER)
1321 state -> partner.max_response_delay =
1322 link -> imsg -> receive_timer;
1323 state -> mclt = link -> imsg -> mclt;
1327 }
else if (link -> imsg -> type == FTM_CONNECTACK) {
1335 if (!(link->imsg->options_present &
1336 FTB_RELATIONSHIP_NAME)) {
1337 errmsg =
"missing relationship-name";
1338 reason = FTR_INVALID_PARTNER;
1342 if (link->imsg->options_present & FTB_REJECT_REASON) {
1344 log_error (
"Failover CONNECT to %s rejected: %s",
1345 state ? state->name :
"unknown",
1347 (link -> imsg -> reject_reason)));
1350 return ISC_R_SUCCESS;
1354 &link->imsg->relationship_name)) {
1356 snprintf(errbuf,
sizeof(errbuf),
"remote failover " 1357 "relationship name %.*s does not match",
1358 (
int)link->imsg->relationship_name.count,
1359 link->imsg->relationship_name.data);
1361 reason = FTR_INVALID_PARTNER;
1363 log_error(
"Failover CONNECTACK from %s: %s",
1364 state->name, errmsg);
1368 return ISC_R_SUCCESS;
1371 if (state -> link_to_peer) {
1372 errmsg =
"already connected";
1373 reason = FTR_DUP_CONNECTION;
1377 if ((
cur_time > link -> imsg -> time &&
1378 cur_time - link -> imsg -> time > 60) ||
1379 (cur_time < link -> imsg -> time &&
1380 link -> imsg -> time -
cur_time > 60)) {
1381 errmsg =
"time offset too large";
1382 reason = FTR_TIMEMISMATCH;
1386 dhcp_failover_link_reference (&state -> link_to_peer,
1393 if (state -> me.state ==
startup)
1395 state -> saved_state);
1400 if (link -> imsg -> options_present & FTB_MAX_UNACKED)
1401 state -> partner.max_flying_updates =
1402 link -> imsg -> max_unacked;
1403 if (link -> imsg -> options_present & FTB_RECEIVE_TIMER)
1404 state -> partner.max_response_delay =
1405 link -> imsg -> receive_timer;
1406 #if defined (DEBUG_FAILOVER_CONTACT_TIMING) 1408 (
int)state -> partner.max_response_delay / 3,
1409 "dhcp_failover_send_contact");
1412 (
int)state -> partner.max_response_delay / 3;
1416 (
tvref_t)dhcp_failover_state_reference,
1417 (
tvunref_t)dhcp_failover_state_dereference);
1418 #if defined (DEBUG_FAILOVER_CONTACT_TIMING) 1420 (
int)state -> me.max_response_delay,
1421 "dhcp_failover_timeout");
1424 (
int)state -> me.max_response_delay;
1428 (
tvref_t)dhcp_failover_state_reference,
1429 (
tvunref_t)dhcp_failover_state_dereference);
1430 }
else if (link -> imsg -> type == FTM_DISCONNECT) {
1431 if (link -> imsg -> reject_reason) {
1432 log_error (
"Failover DISCONNECT from %s: %s",
1433 state ? state->name :
"unknown",
1435 (link -> imsg -> reject_reason)));
1438 }
else if (link -> imsg -> type == FTM_BNDUPD) {
1441 }
else if (link -> imsg -> type == FTM_BNDACK) {
1443 }
else if (link -> imsg -> type == FTM_UPDREQ) {
1446 }
else if (link -> imsg -> type == FTM_UPDREQALL) {
1448 (state, link -> imsg);
1449 }
else if (link -> imsg -> type == FTM_UPDDONE) {
1452 }
else if (link -> imsg -> type == FTM_POOLREQ) {
1453 dhcp_failover_pool_reqbalance(state);
1454 }
else if (link -> imsg -> type == FTM_POOLRESP) {
1455 log_info (
"pool response: %ld leases",
1457 link -> imsg -> addresses_transferred);
1458 }
else if (link -> imsg -> type == FTM_STATE) {
1467 if (state -> link_to_peer &&
1468 state -> link_to_peer == link &&
1469 state -> link_to_peer -> state != dhcp_flink_disconnected)
1471 #if defined (DEBUG_FAILOVER_CONTACT_TIMING) 1473 (
int)state -> me.max_response_delay,
1474 "dhcp_failover_timeout");
1477 (
int)state -> me.max_response_delay;
1481 (
tvref_t)dhcp_failover_state_reference,
1482 (
tvunref_t)dhcp_failover_state_dereference);
1488 return ISC_R_SUCCESS;
1494 isc_result_t status;
1497 if (!strcmp (name,
"disconnect")) {
1498 if (state -> link_to_peer) {
1499 log_info (
"peer %s: disconnected", state -> name);
1500 if (state -> link_to_peer -> state_object)
1501 dhcp_failover_state_dereference
1502 (&state -> link_to_peer -> state_object,
MDL);
1503 dhcp_failover_link_dereference (&state -> link_to_peer,
1510 switch (state -> me.state ==
startup ?
1511 state -> saved_state : state -> me.state) {
1525 if (state -> me.state ==
startup)
1527 (state, state -> saved_state));
1528 return ISC_R_SUCCESS;
1546 }
else if (!strcmp (name,
"connect")) {
1547 switch (state -> me.state) {
1574 }
else if (!strcmp (name,
"startup")) {
1576 return ISC_R_SUCCESS;
1577 }
else if (!strcmp (name,
"connect-timeout")) {
1578 switch (state -> me.state) {
1586 return ISC_R_SUCCESS;
1610 switch (state -> me.state) {
1613 state -> nrr =
" (my state unknown)";
1635 state -> nrr =
" (resolving conflicts)";
1640 state -> nrr =
" (recovering)";
1645 state -> nrr =
" (shut down)";
1650 state -> nrr =
" (paused)";
1655 state -> nrr =
" (recover wait)";
1660 state -> nrr =
" (recover done)";
1665 state -> nrr =
" (startup)";
1677 switch (state -> partner.state) {
1680 state -> nrr =
" (peer demands: recovering)";
1687 state -> nrr =
" (peer demands: resolving conflicts)";
1696 return ISC_R_SUCCESS;
1715 switch (state -> me.state) {
1719 if (state -> ack_queue_tail) {
1723 for (lp = state -> ack_queue_head; lp; lp = lp ->
next_pending)
1729 if (state -> update_queue_head) {
1730 lease_reference (&state -> ack_queue_tail ->
next_pending,
1731 state -> update_queue_head,
MDL);
1732 lease_dereference (&state -> update_queue_head,
MDL);
1734 lease_reference (&state -> update_queue_head,
1735 state -> ack_queue_head,
MDL);
1736 if (!state -> update_queue_tail) {
1737 #if defined (POINTER_DEBUG) 1739 log_error (
"next pending on ack queue tail.");
1743 lease_reference (&state -> update_queue_tail,
1744 state -> ack_queue_tail,
MDL);
1746 lease_dereference (&state -> ack_queue_tail,
MDL);
1747 lease_dereference (&state -> ack_queue_head,
MDL);
1748 state -> cur_unacked_updates = 0;
1759 saved_state = state -> me.state;
1760 saved_stos = state -> me.stos;
1775 !state -> update_queue_head && !state -> ack_queue_head)
1776 state -> me.stos =
cur_time - state -> mclt;
1778 state -> me.state = new_state;
1780 state -> saved_state = saved_state;
1784 log_error (
"Unable to record current failover state for %s",
1786 state -> me.state = saved_state;
1787 state -> me.stos = saved_stos;
1788 return ISC_R_IOERROR;
1791 log_info (
"failover peer %s: I move from %s to %s",
1796 if ((state->me.state ==
normal) && (state->partner.state ==
normal))
1797 log_info(
"failover peer %s: Both servers normal", state->name);
1813 if (state -> link_to_peer)
1816 switch (new_state) {
1826 if (state->auto_partner_down == 0)
1829 #if defined (DEBUG_FAILOVER_TIMING) 1830 log_info(
"add_timeout +%lu dhcp_failover_auto_partner_down",
1831 (
unsigned long)state->auto_partner_down);
1833 tv.tv_sec =
cur_time + state->auto_partner_down;
1846 dhcp_failover_pool_balance(state);
1849 if (state->update_queue_tail != NULL) {
1851 log_info(
"Sending updates to %s.", state->name);
1857 if (state -> i_am == primary)
1862 #if defined (DEBUG_FAILOVER_TIMING) 1864 "dhcp_failover_startup_timeout");
1871 (
tvref_t)omapi_object_reference,
1879 if (state -> me.stos + state -> mclt >
cur_time) {
1880 #if defined (DEBUG_FAILOVER_TIMING) 1883 state -> me.stos + state -> mclt),
1884 "dhcp_failover_startup_timeout");
1886 tv . tv_sec = (
int)(state -> me.stos + state -> mclt);
1891 (
tvref_t)omapi_object_reference,
1903 if (state -> link_to_peer)
1910 for (p = s ->
pools; p; p = p ->
next) {
1911 if (p -> failover_peer == state) {
1913 l->
tsfp = state->me.stos + state->mclt;
1921 #if defined (DEBUG_FAILOVER_TIMING) 1944 return ISC_R_SUCCESS;
1948 failover_message_t *msg)
1954 new_state = msg -> server_state;
1955 startupp = (msg -> server_flags & FTF_SERVER_STARTUP) ? 1 : 0;
1957 if (state -> partner.state == new_state && state -> me.state) {
1958 switch (state -> me.state) {
1961 return ISC_R_SUCCESS;
1970 return ISC_R_SUCCESS;
1987 state -> partner.state = new_state;
1989 log_info (
"failover peer %s: peer moves from %s to %s",
1995 if ((state->me.state ==
normal) && (state->partner.state ==
normal))
1996 log_info(
"failover peer %s: Both servers normal", state->name);
2002 log_error (
"Unable to record current failover state for %s",
2009 switch (new_state) {
2026 log_error(
"failover peer %s: Invalid state: %d", state->name,
2029 return ISC_R_SUCCESS;
2035 switch (state -> me.state ==
startup ?
2036 state -> saved_state : state -> me.state) {
2038 switch (new_state) {
2044 if (state -> me.state ==
startup)
2055 log_error(
"Peer %s: Invalid state transition %s " 2056 "to %s.", state->name,
2081 switch (new_state) {
2083 log_info (
"failover peer %s: requesting %s",
2084 state -> name,
"full update from peer");
2088 if (state -> me.state ==
recover)
2114 if (state -> me.state ==
recover)
2135 switch (new_state) {
2138 log_error(
"Peer %s moves to normal during conflict " 2139 "resolution - panic, shutting down.",
2148 log_error(
"Peer %s: Unexpected move to " 2149 "conflict-done.", state->name);
2176 switch (new_state) {
2183 log_fatal(
"Peer %s: Invalid attempt to move from %s " 2184 "to %s while local state is conflict-done.",
2196 switch (new_state) {
2222 switch (new_state) {
2262 switch (new_state) {
2290 switch (new_state) {
2292 log_error(
"Both servers have entered recover-done!");
2331 if (state -> me.state ==
startup && state -> saved_state !=
startup)
2338 return ISC_R_SUCCESS;
2347 dhcp_failover_pool_balance(dhcp_failover_state_t *state)
2351 state->sched_balance = 0;
2353 dhcp_failover_pool_dobalance(state, NULL);
2364 dhcp_failover_state_t *
state;
2365 isc_boolean_t sendreq = ISC_FALSE;
2367 state = (dhcp_failover_state_t *)failover_state;
2370 state->sched_balance = 0;
2372 if (dhcp_failover_pool_dobalance(state, &sendreq))
2384 dhcp_failover_pool_reqbalance(dhcp_failover_state_t *state)
2390 state->sched_balance = 0;
2392 queued = dhcp_failover_pool_dobalance(state, NULL);
2399 log_info(
"peer %s: Got POOLREQ, answering negatively! " 2400 "Peer may be out of leases or database inconsistent.",
2412 dhcp_failover_pool_dobalance(dhcp_failover_state_t *state,
2413 isc_boolean_t *sendreq)
2415 int lts, total, thresh, hold, panic, pass;
2416 int leases_queued = 0;
2425 int (*log_func)(
const char *, ...);
2426 const char *result, *reqlog;
2428 if (state -> me.state !=
normal)
2460 thresh = ((total * state->max_lease_misbalance) + 50) / 100;
2461 hold = ((total * state->max_lease_ownership) + 50) / 100;
2476 panic = thresh * -2;
2481 if ((sendreq != NULL) && (lts < panic)) {
2482 reqlog =
" (requesting peer rebalance!)";
2483 *sendreq = ISC_TRUE;
2487 log_info(
"balancing pool %lx %s total %d free %d " 2488 "backup %d lts %d max-own (+/-)%d%s",
2490 (p->shared_network ?
2492 p->free_leases, p->backup_leases, lts, hold,
2508 lease_reference(&lp, *lq,
MDL);
2512 lease_dereference(&next,
MDL);
2514 lease_reference(&next, lp->
next,
MDL);
2541 }
else if (lts <= -hold)
2557 lease_dereference(&lp,
MDL);
2559 lease_reference(&lp, next,
MDL);
2562 lease_reference(&lp, *lq,
MDL);
2567 lease_dereference(&next,
MDL);
2569 lease_dereference(&lp,
MDL);
2572 result =
"IMBALANCED";
2575 result =
"balanced";
2579 log_func(
"%s pool %lx %s total %d free %d backup %d " 2580 "lts %d max-misbal %d", result, (
unsigned long)p,
2581 (p->shared_network ?
2582 p->shared_network->name :
""), p->lease_count,
2583 p->free_leases, p->backup_leases, lts, thresh);
2595 return leases_queued;
2605 dhcp_failover_state_t *peer;
2611 if(!peer || peer->me.state !=
normal)
2638 est1 = ((est1 * peer->max_lease_misbalance) + 50) / 100;
2639 est2 = ((est2 * peer->max_lease_misbalance) + 50) / 100;
2644 if(peer->i_am == primary)
2654 if(est1 > peer->max_balance)
2655 est1 = peer->max_balance;
2661 est2 = peer->last_balance + peer->min_balance;
2662 if(peer->last_balance && (est1 < est2))
2666 est1 += random() % 5;
2669 if(peer->sched_balance) {
2670 if (est1 >= peer->sched_balance)
2680 peer->sched_balance = est1;
2682 #if defined(DEBUG_FAILOVER_TIMING) 2683 log_info(
"add_timeout +%d dhcp_failover_pool_rebalance",
2689 (
tvref_t)dhcp_failover_state_reference,
2690 (
tvunref_t)dhcp_failover_state_dereference);
2699 for (p = s ->
pools; p; p = p ->
next) {
2711 isc_result_t status;
2714 if (!state -> link_to_peer)
2715 return ISC_R_SUCCESS;
2720 if (state->toack_queue_head != NULL)
2723 while ((state -> partner.max_flying_updates >
2724 state -> cur_unacked_updates) && state -> update_queue_head) {
2726 lease_reference (&lp, state -> update_queue_head,
MDL);
2730 if (status != ISC_R_SUCCESS) {
2731 lease_dereference (&lp,
MDL);
2738 lease_dereference (&state -> update_queue_head,
MDL);
2740 lease_reference (&state -> update_queue_head,
2744 lease_dereference (&state -> update_queue_tail,
MDL);
2747 if (state -> ack_queue_head) {
2751 lease_dereference (&state -> ack_queue_tail,
MDL);
2753 lease_reference (&state -> ack_queue_head, lp,
MDL);
2755 #if defined (POINTER_DEBUG) 2757 log_error (
"ack_queue_tail: lp -> next_pending");
2761 lease_reference (&state -> ack_queue_tail, lp,
MDL);
2763 lease_dereference (&lp,
MDL);
2766 state -> cur_unacked_updates++;
2768 return ISC_R_SUCCESS;
2777 dhcp_failover_state_t *
state;
2779 if (!lease -> pool ||
2780 !lease -> pool -> failover_peer)
2788 state = lease -> pool -> failover_peer;
2794 if (state -> update_queue_head) {
2795 lease_reference (&state -> update_queue_tail ->
next_pending,
2797 lease_dereference (&state -> update_queue_tail,
MDL);
2799 lease_reference (&state -> update_queue_head, lease,
MDL);
2801 #if defined (POINTER_DEBUG) 2803 log_error (
"next pending on update queue lease.");
2804 #if defined (DEBUG_RC_HISTORY) 2805 dump_rc_history (lease);
2810 lease_reference (&state -> update_queue_tail, lease,
MDL);
2819 failover_message_t *msg = (failover_message_t *)0;
2825 while (state -> toack_queue_head) {
2826 failover_message_reference
2827 (&msg, state -> toack_queue_head,
MDL);
2828 failover_message_dereference
2829 (&state -> toack_queue_head,
MDL);
2831 failover_message_reference
2832 (&state -> toack_queue_head, msg -> next,
MDL);
2837 failover_message_dereference (&msg,
MDL);
2840 if (state -> toack_queue_tail)
2841 failover_message_dereference (&state -> toack_queue_tail,
MDL);
2842 state -> pending_acks = 0;
2849 dhcp_failover_state_t *state = vs;
2851 #if defined (DEBUG_FAILOVER_TIMING) 2852 log_info (
"dhcp_failover_toack_queue_timeout");
2862 failover_message_t *msg)
2866 if (state -> toack_queue_head) {
2867 failover_message_reference
2868 (&state -> toack_queue_tail -> next, msg,
MDL);
2869 failover_message_dereference (&state -> toack_queue_tail,
MDL);
2871 failover_message_reference (&state -> toack_queue_head,
2874 failover_message_reference (&state -> toack_queue_tail, msg,
MDL);
2876 state -> pending_acks++;
2880 if (state -> pending_acks >= state -> partner.max_flying_updates / 2) {
2885 if (state -> pending_acks > 0) {
2886 #if defined (DEBUG_FAILOVER_TIMING) 2888 "dhcp_failover_toack_queue_timeout");
2894 (
tvref_t)dhcp_failover_state_reference,
2895 (
tvunref_t)dhcp_failover_state_dereference);
2902 struct lease *lease)
2906 if (!(lease ->
flags & ON_ACK_QUEUE))
2909 if (state -> ack_queue_head == lease) {
2910 lease_dereference (&state -> ack_queue_head,
MDL);
2912 lease_reference (&state -> ack_queue_head,
2916 lease_dereference (&state -> ack_queue_tail,
MDL);
2919 for (lp = state -> ack_queue_head;
2933 lease_dereference (&state -> ack_queue_tail,
MDL);
2938 lease_reference (&state -> ack_queue_tail, lp,
MDL);
2942 lease ->
flags &= ~ON_ACK_QUEUE;
2949 state -> cur_unacked_updates--;
2956 if (state -> cur_unacked_updates == 0) {
2966 isc_result_t status;
2976 return ISC_R_SUCCESS;
2978 return ISC_R_SUCCESS;
2980 return ISC_R_SUCCESS;
2982 return ISC_R_SUCCESS;
2984 return ISC_R_SUCCESS;
2986 return ISC_R_SUCCESS;
2988 return ISC_R_SUCCESS;
2990 return ISC_R_SUCCESS;
2992 return ISC_R_SUCCESS;
2994 return ISC_R_SUCCESS;
2998 if (status != ISC_R_SUCCESS)
3002 return ISC_R_SUCCESS;
3004 return ISC_R_SUCCESS;
3006 return ISC_R_SUCCESS;
3008 return ISC_R_SUCCESS;
3010 return ISC_R_SUCCESS;
3012 return ISC_R_SUCCESS;
3014 return ISC_R_SUCCESS;
3016 return ISC_R_SUCCESS;
3019 if (h -> inner && h -> inner -> type -> set_value)
3020 return (*(h -> inner -> type -> set_value))
3021 (h -> inner, id, name, value);
3022 return ISC_R_NOTFOUND;
3031 dhcp_failover_state_t *state = vs;
3032 isc_result_t status;
3035 #if defined (DEBUG_FAILOVER_TIMING) 3036 log_info (
"dhcp_failover_reconnect");
3040 if (state -> link_to_peer)
3045 log_info (
"failover peer %s: %s", state -> name,
3046 isc_result_totext (status));
3047 #if defined (DEBUG_FAILOVER_TIMING) 3048 log_info(
"add_timeout +90 dhcp_failover_reconnect");
3053 (
tvref_t)dhcp_failover_state_reference,
3054 (
tvunref_t)dhcp_failover_state_dereference);
3060 dhcp_failover_state_t *state = vs;
3062 #if defined (DEBUG_FAILOVER_TIMING) 3063 log_info (
"dhcp_failover_startup_timeout");
3071 dhcp_failover_link_t *link = vl;
3076 for (; p; p = p -> outer)
3080 log_info (
"failover: link startup timeout");
3087 dhcp_failover_state_t *state = vs;
3088 isc_result_t status;
3091 #if defined (DEBUG_FAILOVER_TIMING) 3092 log_info (
"dhcp_failover_listener_restart");
3096 if (status != ISC_R_SUCCESS) {
3097 log_info (
"failover peer %s: %s", state -> name,
3098 isc_result_totext (status));
3099 #if defined (DEBUG_FAILOVER_TIMING) 3101 "dhcp_failover_listener_restart");
3107 (
tvref_t)dhcp_failover_state_reference,
3108 (
tvunref_t)dhcp_failover_state_dereference);
3115 dhcp_failover_state_t *state = vs;
3117 #if defined (DEBUG_FAILOVER_TIMING) 3118 log_info(
"dhcp_failover_auto_partner_down");
3129 dhcp_failover_state_t *s;
3132 isc_result_t status;
3136 s = (dhcp_failover_state_t *)h;
3141 name, s -> name,
MDL);
3142 return ISC_R_NOTFOUND;
3144 oc = s -> partner.address;
3146 memset (&ds, 0,
sizeof ds);
3153 return ISC_R_NOTFOUND;
3156 name, ds.data, ds.
len,
MDL);
3163 oc = s -> me.address;
3167 s -> partner.port,
MDL);
3170 name, s -> me.port,
MDL);
3173 s -> me.max_flying_updates,
3179 s -> load_balance_max_secs,
MDL);
3184 return ISC_R_NOTFOUND;
3187 s -> partner.state,
MDL);
3190 s -> me.state,
MDL);
3193 s -> partner.stos,
MDL);
3201 s -> last_packet_sent,
MDL);
3204 s -> last_timestamp_received,
3210 s -> me.max_response_delay,
3214 s -> cur_unacked_updates,
MDL);
3217 if (h -> inner && h -> inner -> type -> get_value)
3218 return (*(h -> inner -> type -> get_value))
3219 (h -> inner, id, name, value);
3220 return ISC_R_NOTFOUND;
3224 const char *file,
int line)
3226 dhcp_failover_state_t *s;
3230 s = (dhcp_failover_state_t *)h;
3232 if (s -> link_to_peer)
3233 dhcp_failover_link_dereference (&s -> link_to_peer, file, line);
3236 s -> name = (
char *)0;
3238 if (s -> partner.address)
3240 if (s -> me.address)
3243 dfree (s -> hba, file, line);
3244 s -> hba = (u_int8_t *)0;
3246 if (s -> update_queue_head)
3247 lease_dereference (&s -> update_queue_head, file, line);
3248 if (s -> update_queue_tail)
3249 lease_dereference (&s -> update_queue_tail, file, line);
3250 if (s -> ack_queue_head)
3251 lease_dereference (&s -> ack_queue_head, file, line);
3252 if (s -> ack_queue_tail)
3253 lease_dereference (&s -> ack_queue_tail, file, line);
3254 if (s -> send_update_done)
3255 lease_dereference (&s -> send_update_done, file, line);
3256 if (s -> toack_queue_head)
3257 failover_message_dereference (&s -> toack_queue_head,
3259 if (s -> toack_queue_tail)
3260 failover_message_dereference (&s -> toack_queue_tail,
3262 return ISC_R_SUCCESS;
3274 dhcp_failover_state_t *s;
3275 isc_result_t status;
3282 s = (dhcp_failover_state_t *)h;
3285 if (status != ISC_R_SUCCESS)
3288 if (status != ISC_R_SUCCESS)
3292 if (status != ISC_R_SUCCESS)
3295 if (status != ISC_R_SUCCESS)
3298 sizeof s -> partner.address);
3299 if (status != ISC_R_SUCCESS)
3303 if (status != ISC_R_SUCCESS)
3306 if (status != ISC_R_SUCCESS)
3309 if (status != ISC_R_SUCCESS)
3313 if (status != ISC_R_SUCCESS)
3316 if (status != ISC_R_SUCCESS)
3319 sizeof s -> me.address);
3320 if (status != ISC_R_SUCCESS)
3324 if (status != ISC_R_SUCCESS)
3327 if (status != ISC_R_SUCCESS)
3330 if (status != ISC_R_SUCCESS)
3334 if (status != ISC_R_SUCCESS)
3337 if (status != ISC_R_SUCCESS)
3340 s -> me.max_flying_updates);
3341 if (status != ISC_R_SUCCESS)
3345 if (status != ISC_R_SUCCESS)
3348 if (status != ISC_R_SUCCESS)
3351 if (status != ISC_R_SUCCESS)
3355 if (status != ISC_R_SUCCESS)
3358 if (status != ISC_R_SUCCESS)
3361 (c, (u_int32_t)s -> load_balance_max_secs));
3362 if (status != ISC_R_SUCCESS)
3368 if (status != ISC_R_SUCCESS)
3371 if (status != ISC_R_SUCCESS)
3374 if (status != ISC_R_SUCCESS)
3379 if (status != ISC_R_SUCCESS)
3382 if (status != ISC_R_SUCCESS)
3385 if (status != ISC_R_SUCCESS)
3389 if (status != ISC_R_SUCCESS)
3392 if (status != ISC_R_SUCCESS)
3395 if (status != ISC_R_SUCCESS)
3399 if (status != ISC_R_SUCCESS)
3402 if (status != ISC_R_SUCCESS)
3405 (u_int32_t)s -> partner.stos);
3406 if (status != ISC_R_SUCCESS)
3410 if (status != ISC_R_SUCCESS)
3413 if (status != ISC_R_SUCCESS)
3416 if (status != ISC_R_SUCCESS)
3420 if (status != ISC_R_SUCCESS)
3423 if (status != ISC_R_SUCCESS)
3426 if (status != ISC_R_SUCCESS)
3430 if (status != ISC_R_SUCCESS)
3433 if (status != ISC_R_SUCCESS)
3436 (c, (u_int32_t)s -> last_packet_sent));
3437 if (status != ISC_R_SUCCESS)
3441 if (status != ISC_R_SUCCESS)
3444 if (status != ISC_R_SUCCESS)
3447 (c, (u_int32_t)s -> last_timestamp_received));
3448 if (status != ISC_R_SUCCESS)
3452 if (status != ISC_R_SUCCESS)
3455 if (status != ISC_R_SUCCESS)
3458 if (status != ISC_R_SUCCESS)
3462 if (status != ISC_R_SUCCESS)
3465 if (status != ISC_R_SUCCESS)
3468 (c, (u_int32_t)s -> me.max_response_delay));
3469 if (status != ISC_R_SUCCESS)
3473 if (status != ISC_R_SUCCESS)
3476 if (status != ISC_R_SUCCESS)
3479 (c, (u_int32_t)s -> cur_unacked_updates));
3480 if (status != ISC_R_SUCCESS)
3483 if (h -> inner && h -> inner -> type -> stuff_values)
3484 return (*(h -> inner -> type -> stuff_values)) (c,
id,
3486 return ISC_R_SUCCESS;
3494 isc_result_t status;
3495 dhcp_failover_state_t *s;
3502 if (status == ISC_R_SUCCESS) {
3506 if (status != ISC_R_SUCCESS)
3518 if (status == ISC_R_SUCCESS) {
3520 unsigned l = strlen (s -> name);
3521 if (l == tv -> value -> u.buffer.len &&
3523 tv -> value -> u.buffer.
value, l))
3536 return ISC_R_NOTFOUND;
3547 return ISC_R_SUCCESS;
3553 return ISC_R_NOTIMPLEMENTED;
3559 return ISC_R_NOTIMPLEMENTED;
3563 u_int8_t *addr,
unsigned addrlen)
3568 memset (&ds, 0,
sizeof ds);
3575 state -> partner.address,
MDL)) {
3576 for (i = 0; i + addrlen - 1 < ds.len; i += addrlen) {
3577 if (!memcmp (&ds.data [i],
3590 dhcp_failover_state_t *state;
3591 failover_option_t *name;
3593 if ((strlen(state->name) == name->count) &&
3594 (memcmp(state->name, name->data, name->count) == 0))
3602 static char resbuf[
sizeof(
"Undefined-255: This reason code is not defined " 3603 "in the protocol standard.")];
3605 if ((reason > 0xff) || (reason < 0))
3606 return "Reason code out of range.";
3609 case FTR_ILLEGAL_IP_ADDR:
3610 return "Illegal IP address (not part of any address pool).";
3612 case FTR_FATAL_CONFLICT:
3613 return "Fatal conflict exists: address in use by other client.";
3615 case FTR_MISSING_BINDINFO:
3616 return "Missing binding information.";
3618 case FTR_TIMEMISMATCH:
3619 return "Connection rejected, time mismatch too great.";
3621 case FTR_INVALID_MCLT:
3622 return "Connection rejected, invalid MCLT.";
3624 case FTR_MISC_REJECT:
3625 return "Connection rejected, unknown reason.";
3627 case FTR_DUP_CONNECTION:
3628 return "Connection rejected, duplicate connection.";
3630 case FTR_INVALID_PARTNER:
3631 return "Connection rejected, invalid failover partner.";
3633 case FTR_TLS_UNSUPPORTED:
3634 return "TLS not supported.";
3636 case FTR_TLS_UNCONFIGURED:
3637 return "TLS supported but not configured.";
3639 case FTR_TLS_REQUIRED:
3640 return "TLS required but not supported by partner.";
3642 case FTR_DIGEST_UNSUPPORTED:
3643 return "Message digest not supported.";
3645 case FTR_DIGEST_UNCONFIGURED:
3646 return "Message digest not configured.";
3648 case FTR_VERSION_MISMATCH:
3649 return "Protocol version mismatch.";
3651 case FTR_OUTDATED_BIND_INFO:
3652 return "Outdated binding information.";
3654 case FTR_LESS_CRIT_BIND_INFO:
3655 return "Less critical binding information.";
3657 case FTR_NO_TRAFFIC:
3658 return "No traffic within sufficient time.";
3660 case FTR_HBA_CONFLICT:
3661 return "Hash bucket assignment conflict.";
3663 case FTR_IP_NOT_RESERVED:
3664 return "IP not reserved on this server.";
3666 case FTR_IP_DIGEST_FAILURE:
3667 return "Message digest failed to compare.";
3669 case FTR_IP_MISSING_DIGEST:
3670 return "Missing message digest.";
3673 return "Unknown Error.";
3676 sprintf(resbuf,
"Undefined-%d: This reason code is not defined in the " 3677 "protocol standard.", reason);
3687 return "unknown-state";
3690 return "partner-down";
3696 return "conflict-done";
3699 return "communications-interrupted";
3702 return "resolution-interrupted";
3705 return "potential-conflict";
3711 return "recover-done";
3714 return "recover-wait";
3729 static char messbuf[
sizeof(
"unknown-message-255")];
3732 return "invalid-message";
3736 return "pool-request";
3739 return "pool-response";
3742 return "bind-update";
3750 case FTM_CONNECTACK:
3751 return "connect-ack";
3754 return "update-request";
3757 return "update-done";
3760 return "update-request-all";
3768 case FTM_DISCONNECT:
3769 return "disconnect";
3772 sprintf(messbuf,
"unknown-message-%u", type);
3779 static char optbuf[
sizeof(
"unknown-option-65535")];
3782 return "invalid-option";
3785 case FTO_ADDRESSES_TRANSFERRED:
3786 return "addresses-transferred";
3788 case FTO_ASSIGNED_IP_ADDRESS:
3789 return "assigned-ip-address";
3791 case FTO_BINDING_STATUS:
3792 return "binding-status";
3794 case FTO_CLIENT_IDENTIFIER:
3795 return "client-identifier";
3806 case FTO_DELAYED_SERVICE:
3807 return "delayed-service";
3815 case FTO_LEASE_EXPIRY:
3816 return "lease-expiry";
3818 case FTO_MAX_UNACKED:
3819 return "max-unacked";
3827 case FTO_MESSAGE_DIGEST:
3828 return "message-digest";
3830 case FTO_POTENTIAL_EXPIRY:
3831 return "potential-expiry";
3833 case FTO_PROTOCOL_VERSION:
3834 return "protocol-version";
3836 case FTO_RECEIVE_TIMER:
3837 return "receive-timer";
3839 case FTO_REJECT_REASON:
3840 return "reject-reason";
3842 case FTO_RELATIONSHIP_NAME:
3843 return "relationship-name";
3845 case FTO_REPLY_OPTIONS:
3846 return "reply-options";
3848 case FTO_REQUEST_OPTIONS:
3849 return "request-options";
3851 case FTO_SERVER_FLAGS:
3852 return "server-flags";
3854 case FTO_SERVER_STATE:
3855 return "server-state";
3863 case FTO_TLS_REQUEST:
3864 return "tls-request";
3866 case FTO_VENDOR_CLASS:
3867 return "vendor-class";
3869 case FTO_VENDOR_OPTIONS:
3870 return "vendor-options";
3873 sprintf(optbuf,
"unknown-option-%u", type);
3882 const char *fmt, ...)
3895 if (vsnprintf (tbuf,
sizeof tbuf, fmt, va) >=
sizeof tbuf)
3896 log_fatal (
"%s: vsnprintf would truncate",
3897 "dhcp_failover_make_option");
3901 strlen (tbuf), tbuf);
3905 char *obuf,
unsigned *obufix,
3906 unsigned obufmax, ...)
3909 struct failover_option_info *info;
3911 unsigned size, count;
3917 #if defined (DEBUG_FAILOVER_MESSAGES) 3925 failover_option_t
option, *op;
3929 if (code < 1 || code > FTO_MAX || ft_options [code].type == FT_UNDEF) {
3932 info = &ft_options [code];
3934 va_start (va, obufmax);
3938 if (info -> type == FT_DDNS || info -> type == FT_DDNS1) {
3939 count = info -> type == FT_DDNS ? 1 : 2;
3940 size = va_arg (va,
int) + count;
3943 if (info -> num_present)
3944 count = info -> num_present;
3946 count = va_arg (va,
int);
3949 switch (info -> type) {
3956 case FT_TEXT_OR_BYTES:
3958 txt = va_arg (va,
char *);
3963 ilen = va_arg (va,
unsigned);
3964 size = count * ilen;
3977 log_fatal (
"bogus type in failover_make_option: %d",
3986 option.count = size;
3997 #if defined (DEBUG_FAILOVER_MESSAGES) 4005 if (snprintf (tbuf,
sizeof tbuf,
" (%s<%d>", info -> name,
4006 option.count) >=
sizeof tbuf)
4007 log_fatal (
"dhcp_failover_make_option: tbuf overflow");
4012 switch (info -> type) {
4014 for (i = 0; i < count; i++) {
4015 val = va_arg (va,
unsigned);
4016 #if defined (DEBUG_FAILOVER_MESSAGES) 4018 sprintf (tbuf,
" %d", val);
4021 option.data [i + 4] = val;
4026 for (i = 0; i < count; i++) {
4027 iaddr = va_arg (va, u_int8_t *);
4030 log_error (
"IP addrlen=%d, should be 4.",
4036 #if defined (DEBUG_FAILOVER_MESSAGES) 4038 sprintf (tbuf,
" %u.%u.%u.%u",
4039 iaddr [0], iaddr [1], iaddr [2], iaddr [3]);
4042 memcpy (&option.data [4 + i * ilen], iaddr, ilen);
4047 for (i = 0; i < count; i++) {
4048 val = va_arg (va,
unsigned);
4049 #if defined (DEBUG_FAILOVER_MESSAGES) 4051 sprintf (tbuf,
" %d", val);
4054 putULong (&option.data [4 + i * 4], val);
4060 bval = va_arg (va, u_int8_t *);
4061 #if defined (DEBUG_FAILOVER_MESSAGES) 4062 for (i = 0; i < count; i++) {
4064 sprintf (tbuf,
" %d", bval [i]);
4068 memcpy (&option.data [4], bval, count);
4075 case FT_TEXT_OR_BYTES:
4077 #if defined (DEBUG_FAILOVER_MESSAGES) 4085 if (snprintf (tbuf,
sizeof tbuf,
"\"%s\"", txt) >=
sizeof tbuf)
4086 log_fatal (
"dhcp_failover_make_option: tbuf overflow");
4089 memcpy (&option.data [4], txt, count);
4094 option.data [4] = va_arg (va,
unsigned);
4096 option.data [5] = va_arg (va,
unsigned);
4097 bval = va_arg (va, u_int8_t *);
4098 memcpy (&option.data [4 + count], bval, size - count - 4);
4099 #if defined (DEBUG_FAILOVER_MESSAGES) 4100 for (i = 4; i < size; i++) {
4102 sprintf (tbuf,
" %d", option.data [i]);
4109 for (i = 0; i < count; i++) {
4110 val = va_arg (va, u_int32_t);
4111 #if defined (DEBUG_FAILOVER_MESSAGES) 4113 sprintf (tbuf,
" %d", val);
4116 putUShort (&option.data [4 + i * 2], val);
4125 #if defined DEBUG_FAILOVER_MESSAGES 4131 op =
dmalloc (
sizeof (failover_option_t),
MDL);
4145 int msg_type, u_int32_t xid, ...)
4151 failover_option_t *option;
4152 unsigned char *opbuf;
4153 isc_result_t status = ISC_R_SUCCESS;
4159 va_start (list, xid);
4160 while ((option = va_arg (list, failover_option_t *))) {
4162 size += option -> count;
4169 if (!bad_option && size) {
4172 status = ISC_R_NOMEMORY;
4174 opbuf = (
unsigned char *)0;
4176 va_start (list, xid);
4177 while ((option = va_arg (list, failover_option_t *))) {
4180 if (!bad_option && opbuf)
4181 memcpy (&opbuf [opix],
4182 option -> data, option -> count);
4185 opix += option -> count;
4199 if (status != ISC_R_SUCCESS)
4205 if (status != ISC_R_SUCCESS)
4211 if (status != ISC_R_SUCCESS)
4216 if (status != ISC_R_SUCCESS)
4221 if (status != ISC_R_SUCCESS)
4227 if (status != ISC_R_SUCCESS)
4231 if (link -> state_object &&
4232 link -> state_object -> link_to_peer == link) {
4233 #if defined (DEBUG_FAILOVER_CONTACT_TIMING) 4235 (
int)(link -> state_object ->
4236 partner.max_response_delay) / 3,
4237 "dhcp_failover_send_contact");
4240 (
int)(link -> state_object ->
4241 partner.max_response_delay) / 3;
4245 (
tvref_t)dhcp_failover_state_reference,
4246 (
tvunref_t)dhcp_failover_state_dereference);
4253 log_info (
"dhcp_failover_put_message: something went wrong.");
4260 dhcp_failover_state_t *state = vstate;
4261 dhcp_failover_link_t *link;
4263 #if defined (DEBUG_FAILOVER_TIMING) 4264 log_info (
"dhcp_failover_timeout");
4269 link = state -> link_to_peer;
4275 log_error (
"timeout waiting for failover peer %s", state -> name);
4284 dhcp_failover_state_t *state = vstate;
4285 dhcp_failover_link_t *link;
4286 isc_result_t status;
4288 #if defined(DEBUG_FAILOVER_MESSAGES) && \ 4289 defined(DEBUG_FAILOVER_CONTACT_MESSAGES) 4291 unsigned obufix = 0;
4296 #if defined (DEBUG_FAILOVER_CONTACT_TIMING) 4297 log_info (
"dhcp_failover_send_contact");
4302 link = state -> link_to_peer;
4309 (link, link -> outer,
4310 FTM_CONTACT, link->xid++,
4311 (failover_option_t *)0));
4313 #if defined(DEBUG_FAILOVER_MESSAGES) && \ 4314 defined(DEBUG_FAILOVER_CONTACT_MESSAGES) 4315 if (status != ISC_R_SUCCESS)
4329 dhcp_failover_link_t *link;
4330 isc_result_t status;
4332 #if defined (DEBUG_FAILOVER_MESSAGES) 4334 unsigned obufix = 0;
4336 # define FMA obuf, &obufix, sizeof obuf 4339 # define FMA (char *)0, (unsigned *)0, 0 4344 link = state -> link_to_peer;
4351 (link, link -> outer,
4352 FTM_STATE, link->xid++,
4355 ? state -> saved_state
4356 : state -> me.state)),
4358 (FTO_SERVER_FLAGS, FMA,
4360 ? FTF_SERVER_STARTUP : 0)),
4362 (failover_option_t *)0));
4364 #if defined (DEBUG_FAILOVER_MESSAGES) 4365 if (status != ISC_R_SUCCESS)
4374 return ISC_R_SUCCESS;
4381 dhcp_failover_link_t *link;
4382 dhcp_failover_state_t *state;
4383 isc_result_t status;
4384 #if defined (DEBUG_FAILOVER_MESSAGES) 4386 unsigned obufix = 0;
4388 # define FMA obuf, &obufix, sizeof obuf 4391 # define FMA (char *)0, (unsigned *)0, 0 4396 link = (dhcp_failover_link_t *)l;
4397 state = link -> state_object;
4404 FTM_CONNECT, link->xid++,
4406 strlen(state->name), state->name),
4408 state -> me.max_flying_updates),
4410 state -> me.max_response_delay),
4414 DHCP_FAILOVER_VERSION),
4422 (failover_option_t *)0));
4424 #if defined (DEBUG_FAILOVER_MESSAGES) 4425 if (status != ISC_R_SUCCESS)
4436 dhcp_failover_state_t *state,
4437 int reason,
const char *errmsg)
4439 dhcp_failover_link_t *link;
4440 isc_result_t status;
4441 #if defined (DEBUG_FAILOVER_MESSAGES) 4443 unsigned obufix = 0;
4445 # define FMA obuf, &obufix, sizeof obuf 4448 # define FMA (char *)0, (unsigned *)0, 0 4453 link = (dhcp_failover_link_t *)l;
4460 FTM_CONNECTACK, link->imsg->xid,
4463 strlen(state->name), state->name)
4464 : (link->imsg->options_present & FTB_RELATIONSHIP_NAME)
4466 link->imsg->relationship_name.count,
4467 link->imsg->relationship_name.data)
4468 : &skip_failover_option,
4471 state -> me.max_flying_updates)
4472 : &skip_failover_option,
4475 state -> me.max_response_delay)
4476 : &skip_failover_option,
4480 DHCP_FAILOVER_VERSION),
4481 (link->imsg->options_present & FTB_TLS_REQUEST)
4484 : &skip_failover_option,
4488 : &skip_failover_option,
4491 strlen (errmsg), errmsg)
4492 : &skip_failover_option,
4493 (failover_option_t *)0));
4495 #if defined (DEBUG_FAILOVER_MESSAGES) 4496 if (status != ISC_R_SUCCESS)
4508 const char *message)
4510 dhcp_failover_link_t *link;
4511 isc_result_t status;
4512 #if defined (DEBUG_FAILOVER_MESSAGES) 4514 unsigned obufix = 0;
4516 # define FMA obuf, &obufix, sizeof obuf 4519 # define FMA (char *)0, (unsigned *)0, 0 4524 link = (dhcp_failover_link_t *)l;
4528 if (!message && reason)
4533 FTM_DISCONNECT, link->xid++,
4538 strlen (message), message)
4539 : &skip_failover_option),
4540 (failover_option_t *)0));
4542 #if defined (DEBUG_FAILOVER_MESSAGES) 4543 if (status != ISC_R_SUCCESS)
4556 struct lease *lease)
4558 dhcp_failover_link_t *link;
4559 isc_result_t status;
4562 #if defined (DEBUG_FAILOVER_MESSAGES) 4564 unsigned obufix = 0;
4566 # define FMA obuf, &obufix, sizeof obuf 4569 # define FMA (char *)0, (unsigned *)0, 0 4572 if (!state -> link_to_peer ||
4575 link = (dhcp_failover_link_t *)state -> link_to_peer;
4587 if ((state->i_am == primary) && (transmit_state ==
FTS_FREE))
4589 else if ((state->i_am == secondary) &&
4593 flags |= FTF_IP_FLAG_RESERVE;
4596 flags |= FTF_IP_FLAG_BOOTP;
4636 (link, link -> outer,
4642 lease -> desired_binding_state),
4647 : &skip_failover_option,
4648 lease -> hardware_addr.hlen
4650 lease -> hardware_addr.hlen,
4651 lease -> hardware_addr.hbuf)
4652 : &skip_failover_option,
4659 (lease->
cltt != 0) ?
4661 &skip_failover_option,
4664 &skip_failover_option,
4665 &skip_failover_option,
4666 &skip_failover_option,
4667 &skip_failover_option,
4668 (failover_option_t *)0));
4670 #if defined (DEBUG_FAILOVER_MESSAGES) 4671 if (status != ISC_R_SUCCESS)
4684 failover_message_t *msg,
4685 int reason,
const char *message)
4687 dhcp_failover_link_t *link;
4688 isc_result_t status;
4689 #if defined (DEBUG_FAILOVER_MESSAGES) 4691 unsigned obufix = 0;
4693 # define FMA obuf, &obufix, sizeof obuf 4696 # define FMA (char *)0, (unsigned *)0, 0 4699 if (!state -> link_to_peer ||
4702 link = (dhcp_failover_link_t *)state -> link_to_peer;
4707 if (!message && reason)
4712 (link, link -> outer,
4713 FTM_BNDACK, msg->xid,
4715 sizeof msg -> assigned_addr,
4716 &msg -> assigned_addr),
4717 #ifdef DO_BNDACK_SHOULD_NOT
4719 msg -> binding_status),
4720 (msg -> options_present & FTB_CLIENT_IDENTIFIER)
4722 msg -> client_identifier.count,
4723 msg -> client_identifier.data)
4724 : &skip_failover_option,
4725 (msg -> options_present & FTB_CHADDR)
4727 msg -> chaddr.count,
4729 : &skip_failover_option,
4733 msg -> potential_expiry),
4736 (msg->options_present & FTB_CLTT) ?
4738 &skip_failover_option,
4739 ((msg->options_present & FTB_IP_FLAGS) && msg->ip_flags) ?
4742 : &skip_failover_option,
4746 : &skip_failover_option,
4749 strlen (message), message)
4750 : &skip_failover_option,
4751 #ifdef DO_BNDACK_SHOULD_NOT
4752 &skip_failover_option,
4753 &skip_failover_option,
4754 &skip_failover_option,
4756 (failover_option_t *)0));
4758 #if defined (DEBUG_FAILOVER_MESSAGES) 4759 if (status != ISC_R_SUCCESS)
4771 dhcp_failover_link_t *link;
4772 isc_result_t status;
4773 #if defined (DEBUG_FAILOVER_MESSAGES) 4775 unsigned obufix = 0;
4777 # define FMA obuf, &obufix, sizeof obuf 4780 # define FMA (char *)0, (unsigned *)0, 0 4783 if (!state -> link_to_peer ||
4786 link = (dhcp_failover_link_t *)state -> link_to_peer;
4792 (link, link -> outer,
4793 FTM_POOLREQ, link->xid++,
4794 (failover_option_t *)0));
4796 #if defined (DEBUG_FAILOVER_MESSAGES) 4797 if (status != ISC_R_SUCCESS)
4810 dhcp_failover_link_t *link;
4811 isc_result_t status;
4812 #if defined (DEBUG_FAILOVER_MESSAGES) 4814 unsigned obufix = 0;
4816 # define FMA obuf, &obufix, sizeof obuf 4819 # define FMA (char *)0, (unsigned *)0, 0 4822 if (!state -> link_to_peer ||
4825 link = (dhcp_failover_link_t *)state -> link_to_peer;
4831 (link, link -> outer,
4832 FTM_POOLRESP, link->imsg->xid,
4835 (failover_option_t *)0));
4837 #if defined (DEBUG_FAILOVER_MESSAGES) 4838 if (status != ISC_R_SUCCESS)
4850 dhcp_failover_link_t *link;
4851 isc_result_t status;
4852 #if defined (DEBUG_FAILOVER_MESSAGES) 4854 unsigned obufix = 0;
4856 # define FMA obuf, &obufix, sizeof obuf 4859 # define FMA (char *)0, (unsigned *)0, 0 4862 if (!state -> link_to_peer ||
4865 link = (dhcp_failover_link_t *)state -> link_to_peer;
4870 if (state -> curUPD)
4871 return ISC_R_ALREADYRUNNING;
4874 (link, link -> outer,
4875 FTM_UPDREQ, link->xid++,
4876 (failover_option_t *)0));
4878 if (status == ISC_R_SUCCESS)
4879 state -> curUPD = FTM_UPDREQ;
4881 #if defined (DEBUG_FAILOVER_MESSAGES) 4882 if (status != ISC_R_SUCCESS)
4889 log_info (
"Sent update request message to %s", state -> name);
4896 dhcp_failover_link_t *link;
4897 isc_result_t status;
4898 #if defined (DEBUG_FAILOVER_MESSAGES) 4900 unsigned obufix = 0;
4902 # define FMA obuf, &obufix, sizeof obuf 4905 # define FMA (char *)0, (unsigned *)0, 0 4908 if (!state -> link_to_peer ||
4911 link = (dhcp_failover_link_t *)state -> link_to_peer;
4917 if (state -> curUPD && (state -> curUPD != FTM_UPDREQ))
4918 return ISC_R_ALREADYRUNNING;
4921 (link, link -> outer,
4922 FTM_UPDREQALL, link->xid++,
4923 (failover_option_t *)0));
4925 if (status == ISC_R_SUCCESS)
4926 state -> curUPD = FTM_UPDREQALL;
4928 #if defined (DEBUG_FAILOVER_MESSAGES) 4929 if (status != ISC_R_SUCCESS)
4936 log_info (
"Sent update request all message to %s", state -> name);
4942 dhcp_failover_link_t *link;
4943 isc_result_t status;
4944 #if defined (DEBUG_FAILOVER_MESSAGES) 4946 unsigned obufix = 0;
4948 # define FMA obuf, &obufix, sizeof obuf 4951 # define FMA (char *)0, (unsigned *)0, 0 4954 if (!state -> link_to_peer ||
4957 link = (dhcp_failover_link_t *)state -> link_to_peer;
4963 (link, link -> outer,
4964 FTM_UPDDONE, state->updxid,
4965 (failover_option_t *)0));
4967 #if defined (DEBUG_FAILOVER_MESSAGES) 4968 if (status != ISC_R_SUCCESS)
4976 log_info (
"Sent update done message to %s", state -> name);
5000 static isc_boolean_t
5001 failover_lease_is_better(dhcp_failover_state_t *state,
struct lease *lease,
5002 failover_message_t *msg)
5012 if ((msg->options_present & FTB_CLTT) != 0)
5013 msg_cltt = msg->cltt;
5017 switch(local_state) {
5020 if (msg_cltt < lease->cltt)
5022 else if (msg_cltt > lease->
cltt)
5024 else if (state->i_am == primary)
5041 else if (state->i_am == primary)
5057 failover_message_t *msg)
5059 struct lease *lt = NULL, *lease = NULL;
5061 int reason = FTR_MISC_REJECT;
5062 const char *message;
5063 int new_binding_state;
5064 int send_to_backup = 0;
5065 int required_options;
5066 isc_boolean_t chaddr_changed = ISC_FALSE;
5067 isc_boolean_t ident_changed = ISC_FALSE;
5070 required_options = FTB_ASSIGNED_IP_ADDRESS | FTB_BINDING_STATUS;
5071 if ((msg->options_present & required_options) != required_options) {
5072 message =
"binding update lacks required options";
5073 reason = FTR_MISSING_BINDINFO;
5077 ia.len =
sizeof msg -> assigned_addr;
5078 memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
5081 message =
"unknown IP address";
5082 reason = FTR_ILLEGAL_IP_ADDR;
5090 if ((lease->pool == NULL) || (lease->pool->failover_peer == NULL) ||
5091 (lease->pool->failover_peer != state)) {
5092 message =
"IP address is covered by a different failover " 5093 "relationship state";
5094 reason = FTR_ILLEGAL_IP_ADDR;
5108 if ((lease->flags & ON_ACK_QUEUE) != 0) {
5109 if (failover_lease_is_better(state, lease, msg)) {
5110 message =
"incoming update is less critical than " 5112 reason = FTR_LESS_CRIT_BIND_INFO;
5122 message =
"no memory";
5126 if (msg -> options_present & FTB_CHADDR) {
5128 message =
"BNDUPD to ABANDONED with a CHADDR";
5131 if (msg -> chaddr.count >
sizeof lt -> hardware_addr.hbuf) {
5132 message =
"chaddr too long";
5138 msg->chaddr.count) != 0))
5139 chaddr_changed = ISC_TRUE;
5141 lt -> hardware_addr.hlen = msg -> chaddr.count;
5142 memcpy (lt -> hardware_addr.hbuf, msg -> chaddr.data,
5143 msg -> chaddr.count);
5144 }
else if (msg->binding_status ==
FTS_ACTIVE ||
5147 message =
"BNDUPD without CHADDR";
5148 reason = FTR_MISSING_BINDINFO;
5151 chaddr_changed = ISC_TRUE;
5161 if (msg->options_present & FTB_CLIENT_IDENTIFIER) {
5163 message =
"BNDUPD to ABANDONED with client-id";
5167 if ((lt->
uid_len != msg->client_identifier.count) ||
5168 (lt->
uid == NULL) ||
5169 (memcmp(lt->
uid, msg->client_identifier.data,
5171 ident_changed = ISC_TRUE;
5173 lt->
uid_len = msg->client_identifier.count;
5188 message =
"no memory";
5197 msg -> client_identifier.data, lt -> uid_len);
5198 }
else if (lt->
uid && msg->binding_status !=
FTS_RESET &&
5201 ident_changed = ISC_TRUE;
5234 (chaddr_changed || ident_changed)) {
5237 if (lease->scope != NULL)
5242 if (msg -> options_present & FTB_STOS) {
5243 lt -> starts = msg -> stos;
5245 if (msg -> options_present & FTB_LEASE_EXPIRY) {
5246 lt -> ends = msg -> expiry;
5248 if (msg->options_present & FTB_POTENTIAL_EXPIRY) {
5249 lt->
atsfp = lt->
tsfp = msg->potential_expiry;
5251 if (msg->options_present & FTB_IP_FLAGS) {
5252 if (msg->ip_flags & FTF_IP_FLAG_RESERVE) {
5253 if ((((state->i_am == primary) &&
5254 (lease->binding_state ==
FTS_FREE)) ||
5255 ((state->i_am == secondary) &&
5258 message =
"Address is not reserved.";
5259 reason = FTR_IP_NOT_RESERVED;
5267 if (msg->ip_flags & FTF_IP_FLAG_BOOTP) {
5268 if ((((state->i_am == primary) &&
5269 (lease->binding_state ==
FTS_FREE)) ||
5270 ((state->i_am == secondary) &&
5273 message =
"Address is not allocated to BOOTP.";
5280 if (msg->ip_flags & ~(FTF_IP_FLAG_RESERVE | FTF_IP_FLAG_BOOTP))
5281 log_info(
"Unknown IP-flags set in BNDUPD (0x%x).",
5286 #if defined (DEBUG_LEASE_STATE_TRANSITIONS) 5287 log_info (
"processing state transition for %s: %s to %s",
5295 if (state -> me.state ==
normal) {
5298 (lease, state, msg -> binding_status,
5299 msg -> potential_expiry));
5306 (lease, state, msg -> binding_status,
5307 msg -> potential_expiry));
5309 if (new_binding_state != msg -> binding_status) {
5312 if (snprintf (outbuf,
sizeof outbuf,
5313 "%s: invalid state transition: %s to %s",
5318 log_fatal (
"%s: impossible outbuf overflow",
5319 "dhcp_failover_process_bind_update");
5329 lt -> next_binding_state =
FTS_FREE;
5336 if ((state->i_am == primary) &&
5340 lt -> next_binding_state = new_binding_state;
5342 msg -> binding_status = lt -> next_binding_state;
5353 message =
"database update failed";
5364 if (send_to_backup && secondary_not_hoarding(state, lease->pool)) {
5371 log_error(
"can't commit lease %s for mac addr " 5372 "affinity",
piaddr(lease->ip_addr));
5379 lease_dereference (<,
MDL);
5381 lease_dereference (&lease,
MDL);
5383 return ISC_R_SUCCESS;
5392 secondary_not_hoarding(dhcp_failover_state_t *state,
struct pool *p) {
5400 hold = ((total * state->max_lease_ownership) + 50) / 100;
5411 return(lts > -hold);
5415 failover_message_t *msg)
5417 struct lease *lt = (
struct lease *)0;
5418 struct lease *lease = (
struct lease *)0;
5420 const char *message =
"no memory";
5421 u_int32_t pot_expire;
5422 int send_to_backup = ISC_FALSE;
5425 ia.len =
sizeof msg -> assigned_addr;
5426 memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
5429 message =
"no such lease";
5434 if (msg -> options_present & FTB_REJECT_REASON) {
5435 log_error (
"bind update on %s from %s rejected: %.*s",
5436 piaddr (ia), state -> name,
5437 (
int)((msg -> options_present & FTB_MESSAGE)
5438 ? msg -> message.count
5440 (msg -> reject_reason))),
5441 (msg -> options_present & FTB_MESSAGE)
5442 ? (
const char *)(msg -> message.data)
5444 (msg -> reject_reason)));
5455 message =
"xid mismatch";
5460 if (msg->options_present & FTO_POTENTIAL_EXPIRY)
5461 pot_expire = msg->potential_expiry;
5463 pot_expire = lease->
tstp;
5483 lease->
atsfp = lease->
tsfp = pot_expire;
5484 if ((state->i_am == secondary) &&
5506 if (state->i_am == primary &&
5509 send_to_backup = ISC_TRUE;
5511 if (!send_to_backup && state->me.state ==
normal)
5517 lease->
atsfp = lease->
tsfp = pot_expire;
5522 (
struct lease *)0, 0, 0, 0);
5540 if (state -> send_update_done == lease) {
5541 lease_dereference (&state -> send_update_done,
MDL);
5548 if (send_to_backup && secondary_not_hoarding(state, lease->
pool)) {
5557 if (state->me.state ==
normal)
5566 lease_dereference (&lease,
MDL);
5568 lease_dereference (<,
MDL);
5570 return ISC_R_SUCCESS;
5573 log_info (
"bind update on %s got ack from %s: %s.",
5574 piaddr (ia), state -> name, message);
5585 #define FREE_LEASES 0 5586 #define ACTIVE_LEASES 1 5587 #define EXPIRED_LEASES 2 5588 #define ABANDONED_LEASES 3 5589 #define BACKUP_LEASES 4 5590 #define RESERVED_LEASES 5 5596 for (p = s ->
pools; p; p = p ->
next) {
5608 for (l = *(lptr [i]); l; l = l ->
next) {
5620 return ISC_R_SUCCESS;
5625 failover_message_t *msg)
5627 if (state->send_update_done) {
5628 log_info(
"Received update request while old update still " 5629 "flying! Silently discarding old request.");
5630 lease_dereference(&state->send_update_done,
MDL);
5636 state->updxid = msg->xid;
5641 if (state -> update_queue_tail) {
5642 lease_reference (&state -> send_update_done,
5643 state -> update_queue_tail,
MDL);
5645 log_info (
"Update request from %s: sending update",
5651 log_info (
"Update request from %s: nothing pending",
5655 return ISC_R_SUCCESS;
5660 failover_message_t *msg)
5662 if (state->send_update_done) {
5663 log_info(
"Received update request while old update still " 5664 "flying! Silently discarding old request.");
5665 lease_dereference(&state->send_update_done,
MDL);
5671 state->updxid = msg->xid;
5673 if (state -> update_queue_tail) {
5674 lease_reference (&state -> send_update_done,
5675 state -> update_queue_tail,
MDL);
5677 log_info (
"Update request all from %s: sending update",
5683 log_info (
"Update request all from %s: nothing pending",
5687 return ISC_R_SUCCESS;
5692 failover_message_t *msg)
5696 log_info (
"failover peer %s: peer update completed.",
5699 state -> curUPD = 0;
5701 switch (state -> me.state) {
5717 if (state->i_am == secondary) {
5720 log_error(
"Secondary is in conflict_done " 5721 "state after conflict resolution, " 5722 "this is illegal.");
5726 if (state->i_am == primary)
5729 log_error(
"Spurious update-done message.");
5735 log_error(
"Spurious update-done message.");
5744 if (state -> me.stos + state -> mclt >
cur_time &&
5745 state -> partner.state !=
recover &&
5748 #if defined (DEBUG_FAILOVER_TIMING) 5751 state -> me.stos + state -> mclt),
5752 "dhcp_failover_recover_done");
5754 tv . tv_sec = (
int)(state -> me.stos + state -> mclt);
5759 (
tvref_t)omapi_object_reference,
5766 return ISC_R_SUCCESS;
5771 dhcp_failover_state_t *state = sp;
5773 #if defined (DEBUG_FAILOVER_TIMING) 5774 log_info (
"dhcp_failover_recover_done");
5780 #if defined (DEBUG_FAILOVER_MESSAGES) 5787 unsigned *obufix,
unsigned obufmax,
const char *s)
5789 int len = strlen (s);
5791 while (len + *obufix + 1 >= obufmax) {
5800 strcpy (&obuf [*obufix], s);
5807 unsigned char loadb_mx_tbl[256] = {
5808 251, 175, 119, 215, 81, 14, 79, 191, 103, 49,
5809 181, 143, 186, 157, 0, 232, 31, 32, 55, 60,
5810 152, 58, 17, 237, 174, 70, 160, 144, 220, 90,
5811 57, 223, 59, 3, 18, 140, 111, 166, 203, 196,
5812 134, 243, 124, 95, 222, 179, 197, 65, 180, 48,
5813 36, 15, 107, 46, 233, 130, 165, 30, 123, 161,
5814 209, 23, 97, 16, 40, 91, 219, 61, 100, 10,
5815 210, 109, 250, 127, 22, 138, 29, 108, 244, 67,
5816 207, 9, 178, 204, 74, 98, 126, 249, 167, 116,
5817 34, 77, 193, 200, 121, 5, 20, 113, 71, 35,
5818 128, 13, 182, 94, 25, 226, 227, 199, 75, 27,
5819 41, 245, 230, 224, 43, 225, 177, 26, 155, 150,
5820 212, 142, 218, 115, 241, 73, 88, 105, 39, 114,
5821 62, 255, 192, 201, 145, 214, 168, 158, 221, 148,
5822 154, 122, 12, 84, 82, 163, 44, 139, 228, 236,
5823 205, 242, 217, 11, 187, 146, 159, 64, 86, 239,
5824 195, 42, 106, 198, 118, 112, 184, 172, 87, 2,
5825 173, 117, 176, 229, 247, 253, 137, 185, 99, 164,
5826 102, 147, 45, 66, 231, 52, 141, 211, 194, 206,
5827 246, 238, 56, 110, 78, 248, 63, 240, 189, 93,
5828 92, 51, 53, 183, 19, 171, 72, 50, 33, 104,
5829 101, 69, 8, 252, 83, 120, 76, 135, 85, 54,
5830 202, 125, 188, 213, 96, 235, 136, 208, 162, 129,
5831 190, 132, 156, 38, 47, 1, 7, 254, 24, 4,
5832 216, 131, 89, 21, 28, 133, 37, 153, 149, 80,
5833 170, 68, 6, 169, 234, 151 };
5835 static unsigned char loadb_p_hash (
const unsigned char *,
unsigned);
5836 static unsigned char loadb_p_hash (
const unsigned char *key,
unsigned len)
5838 unsigned char hash = len;
5840 for(i = len; i > 0; )
5841 hash = loadb_mx_tbl [hash ^ (key [--i])];
5849 unsigned char hbaix;
5853 ec = ntohs(packet->
raw->
secs);
5855 #if defined(SECS_BYTEORDER) 5862 if ((ec > 255) && ((ec & 0xff) == 0)) {
5863 ec = (ec >> 8) | (ec << 8);
5867 if (state->load_balance_max_secs < ec) {
5878 memset(&ds, 0,
sizeof ds);
5883 hbaix = loadb_p_hash(ds.data, ds.len);
5887 hbaix = loadb_p_hash(packet->
raw->
chaddr,
5891 hm = state->hba[(hbaix >> 3) & 0x1F] & (1 << (hbaix & 0x07));
5893 if (state->i_am == primary)
5907 dhcp_failover_state_t *state;
5908 unsigned char hbaix;
5916 if (!state || !state->hba)
5933 hm = state->hba[(hbaix >> 3) & 0x1F] & (1 << (hbaix & 0x07));
5935 if (state->i_am == primary)
5949 dhcp_failover_state_t *state,
5956 if (binding_state == lease -> binding_state)
5957 return binding_state;
5959 switch (lease -> binding_state) {
5962 switch (binding_state) {
5973 if (state -> i_am == secondary)
5974 return binding_state;
5982 new_state = binding_state;
5992 if (state -> i_am == primary) {
5996 return binding_state;
5997 new_state = lease -> binding_state;
6002 switch (binding_state) {
6008 new_state = lease -> binding_state;
6011 return binding_state;
6019 if (lease -> ends - 65 >
cur_time) {
6020 new_state = lease -> binding_state;
6028 return binding_state;
6036 switch (binding_state) {
6042 new_state = lease -> binding_state;
6045 return binding_state;
6052 return binding_state;
6059 switch (binding_state) {
6070 return binding_state;
6077 switch (binding_state) {
6083 new_state = lease -> binding_state;
6086 return binding_state;
6093 return binding_state;
6100 switch (binding_state) {
6109 if (state -> i_am == primary)
6110 return binding_state;
6116 return binding_state;
6119 new_state = lease -> binding_state;
6139 dhcp_failover_state_t *state,
6146 if (binding_state == lease -> binding_state)
6147 new_state = binding_state;
6149 switch (lease -> binding_state) {
6159 new_state = binding_state;
6166 switch (binding_state) {
6169 new_state = lease -> binding_state;
6181 new_state = binding_state;
6192 new_state = binding_state;
6227 dhcp_failover_state_t *peer;
6229 if (lease && lease->
pool &&
6253 if (peer -> i_am == primary)
6257 ((lease->
tsfp < peer->me.stos) ?
6258 (peer->me.stos + peer->mclt <
cur_time) :
6277 if ((peer->i_am == primary) &&
6280 if ((peer->i_am == secondary) &&
6311 if (peer->i_am == secondary)
6315 ((lease->
tsfp < peer->me.stos) ?
6316 (peer->me.stos + peer->mclt <
cur_time) :
6333 static isc_result_t failover_message_reference (failover_message_t **mp,
6334 failover_message_t *m,
6335 const char *file,
int line)
6339 return ISC_R_SUCCESS;
6342 static isc_result_t failover_message_dereference (failover_message_t **mp,
6343 const char *file,
int line)
6345 failover_message_t *m;
6348 if (m -> refcnt == 0) {
6350 failover_message_dereference (&m -> next,
6352 if (m -> chaddr.data)
6353 dfree (m -> chaddr.data, file, line);
6354 if (m -> client_identifier.data)
6355 dfree (m -> client_identifier.data, file, line);
6357 dfree (m -> hba.data, file, line);
6358 if (m -> message.data)
6359 dfree (m -> message.data, file, line);
6360 if (m -> relationship_name.data)
6361 dfree (m -> relationship_name.data, file, line);
6362 if (m -> reply_options.data)
6363 dfree (m -> reply_options.data, file, line);
6364 if (m -> request_options.data)
6365 dfree (m -> request_options.data, file, line);
6366 if (m -> vendor_class.data)
6367 dfree (m -> vendor_class.data, file, line);
6368 if (m -> vendor_options.data)
6369 dfree (m -> vendor_options.data, file, line);
6372 dfree (*mp, file, line);
6375 return ISC_R_SUCCESS;
isc_result_t dhcp_failover_state_signal(omapi_object_t *, const char *, va_list)
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
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_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 supersede_lease(struct lease *, struct lease *, int, int, int)
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)