33 #if defined (FAILOVER_PROTOCOL) 36 dhcp_failover_link_t *);
39 static isc_result_t failover_message_reference (failover_message_t **,
42 static isc_result_t failover_message_dereference (failover_message_t **,
45 static void dhcp_failover_pool_balance(dhcp_failover_state_t *state);
46 static void dhcp_failover_pool_reqbalance(dhcp_failover_state_t *state);
47 static int dhcp_failover_pool_dobalance(dhcp_failover_state_t *state,
48 isc_boolean_t *sendreq);
49 static inline int secondary_not_hoarding(dhcp_failover_state_t *state,
55 dhcp_failover_state_t *state;
62 if (state -> pool_count == 0) {
63 log_error (
"failover peer declaration with no %s",
65 log_error (
"In order to use failover, you MUST %s",
66 "refer to your main failover declaration");
67 log_error (
"in each pool declaration. You MUST %s",
68 "NOT use range declarations outside");
75 #if defined (DEBUG_FAILOVER_TIMING) 76 log_info (
"add_timeout +90 dhcp_failover_reconnect");
83 dhcp_failover_state_reference,
85 dhcp_failover_state_dereference);
86 log_error (
"failover peer %s: %s", state -> name,
87 isc_result_totext (status));
92 if (status != ISC_R_SUCCESS) {
93 #if defined (DEBUG_FAILOVER_TIMING) 95 "dhcp_failover_listener_restart");
110 dhcp_failover_state_t *state;
120 dhcp_failover_state_t *peer;
122 dhcp_failover_state_t *dup = (dhcp_failover_state_t *)0;
126 if (status == ISC_R_NOTFOUND) {
128 dhcp_failover_state_reference (&peer -> next,
134 return ISC_R_SUCCESS;
136 dhcp_failover_state_dereference (&dup,
MDL);
137 if (status == ISC_R_SUCCESS)
143 dhcp_failover_state_t **peer;
148 dhcp_failover_state_t *p;
151 if (!strcmp (name, p -> name))
154 return dhcp_failover_state_reference (peer, p, file, line);
155 return ISC_R_NOTFOUND;
177 dhcp_failover_link_t *obj;
178 dhcp_failover_state_t *state;
186 for (o = h; o -> outer; o = o -> outer)
188 for (; o; o = o -> inner) {
194 state = (dhcp_failover_state_t *)o;
196 obj = (dhcp_failover_link_t *)0;
197 status = dhcp_failover_link_allocate (&obj,
MDL);
198 if (status != ISC_R_SUCCESS)
201 state -> partner.address,
MDL);
202 obj -> peer_port = state -> partner.port;
203 dhcp_failover_state_reference (&obj -> state_object, state,
MDL);
205 memset (&ds, 0,
sizeof ds);
211 dhcp_failover_link_dereference (&obj,
MDL);
212 return ISC_R_UNEXPECTED;
218 if (status != ISC_R_SUCCESS) {
219 dhcp_failover_link_dereference (&obj,
MDL);
223 for (i = 0; i < addrs -> count; i++) {
224 addrs -> addresses [i].addrtype = AF_INET;
225 addrs -> addresses [i].addrlen =
sizeof (
struct in_addr);
226 memcpy (addrs -> addresses [i].address,
227 &ds.data [i * 4], sizeof (
struct in_addr));
228 addrs -> addresses [i].port = obj -> peer_port;
233 if (!state -> me.address ||
241 memset (&local_addr, 0,
sizeof local_addr);
243 local_addr.
addrlen =
sizeof (
struct in_addr);
245 log_fatal (
"failover peer %s: no local address.",
249 if (ds.len != sizeof (
struct in_addr)) {
250 log_error(
"failover peer %s: 'address' parameter " 251 "fails to resolve to an IPv4 address",
254 dhcp_failover_link_dereference (&obj,
MDL);
260 memcpy (local_addr.
address, ds.data, ds.len);
272 dhcp_failover_link_dereference (&obj,
MDL);
277 const char *name, va_list ap)
280 dhcp_failover_link_t *link;
282 dhcp_failover_state_t *s, *state = (dhcp_failover_state_t *)0;
289 return ISC_R_UNEXPECTED;
291 link = (dhcp_failover_link_t *)h;
293 if (!strcmp (name,
"connect")) {
294 if (link -> state_object -> i_am == primary) {
296 if (status != ISC_R_SUCCESS) {
297 log_info (
"dhcp_failover_send_connect: %s",
298 isc_result_totext (status));
302 status = ISC_R_SUCCESS;
305 #if defined (DEBUG_FAILOVER_TIMING) 307 "dhcp_failover_link_startup_timeout");
314 (
tvref_t)dhcp_failover_link_reference,
315 (
tvunref_t)dhcp_failover_link_dereference);
319 if (!strcmp (name,
"disconnect")) {
320 if (link -> state_object) {
321 dhcp_failover_state_reference (&state,
322 link -> state_object,
MDL);
323 link -> state = dhcp_flink_disconnected;
326 if (state->link_to_peer == link)
330 #if defined (DEBUG_FAILOVER_TIMING) 331 log_info(
"add_timeout +5 dhcp_failover_reconnect");
334 tv.tv_usec =
cur_tv.tv_usec;
336 (
tvref_t)dhcp_failover_state_reference,
337 (
tvunref_t)dhcp_failover_state_dereference);
339 dhcp_failover_state_dereference (&state,
MDL);
341 return ISC_R_SUCCESS;
344 if (!strcmp (name,
"status")) {
345 if (link -> state_object) {
348 status = va_arg(ap, isc_result_t);
350 if ((status == ISC_R_HOSTUNREACH) || (status == ISC_R_TIMEDOUT)) {
351 dhcp_failover_state_reference (&state,
352 link -> state_object,
MDL);
353 link -> state = dhcp_flink_disconnected;
360 #if defined (DEBUG_FAILOVER_TIMING) 362 "dhcp_failover_reconnect");
368 (
tvref_t)dhcp_failover_state_reference,
369 (
tvunref_t)dhcp_failover_state_dereference);
371 dhcp_failover_state_dereference (&state,
MDL);
373 return ISC_R_SUCCESS;
377 if (strcmp (name,
"ready")) {
378 if (h -> inner && h -> inner -> type -> signal_handler)
379 return (*(h -> inner -> type -> signal_handler))
380 (h -> inner, name, ap);
381 return ISC_R_NOTFOUND;
391 switch (link -> state) {
392 case dhcp_flink_start:
393 link -> state = dhcp_flink_message_length_wait;
396 case dhcp_flink_message_length_wait:
398 link -> state = dhcp_flink_message_wait;
399 link -> imsg =
dmalloc (
sizeof (failover_message_t),
MDL);
401 status = ISC_R_NOMEMORY;
404 failover_message_dereference (&link->imsg,
407 link -> state = dhcp_flink_disconnected;
408 log_info (
"message length wait: %s",
409 isc_result_totext (status));
413 return ISC_R_UNEXPECTED;
415 memset (link -> imsg, 0,
sizeof (failover_message_t));
416 link -> imsg -> refcnt = 1;
419 link -> imsg_count = 0;
422 if (link->imsg_len < DHCP_FAILOVER_MIN_MESSAGE_SIZE ||
423 link->imsg_len > DHCP_FAILOVER_MAX_MESSAGE_SIZE) {
424 status = ISC_R_UNEXPECTED;
425 goto dhcp_flink_fail;
431 case dhcp_flink_message_wait:
441 link -> imsg_count += 2;
445 link -> imsg_count++;
449 link -> imsg_count++;
453 link -> imsg_count += 4;
457 link -> imsg_count += 4;
459 #if defined (DEBUG_FAILOVER_MESSAGES) 460 # if !defined(DEBUG_FAILOVER_CONTACT_MESSAGES) 461 if (link->imsg->type == FTM_CONTACT)
464 log_info (
"link: message %s payoff %d time %ld xid %ld",
467 (
unsigned long)link -> imsg -> time,
468 (
unsigned long)link -> imsg -> xid);
469 # if !defined(DEBUG_FAILOVER_CONTACT_MESSAGES) 475 if (link -> imsg_payoff - link -> imsg_count) {
477 (link -> imsg_payoff -
478 link -> imsg_count));
479 link -> imsg_count = link -> imsg_payoff;
483 while (link -> imsg_count < link -> imsg_len) {
484 status = do_a_failover_option (c, link);
485 if (status != ISC_R_SUCCESS)
486 goto dhcp_flink_fail;
492 if (link -> imsg -> type == FTM_CONNECT) {
496 if (!(link->imsg->options_present &
497 FTB_RELATIONSHIP_NAME)) {
498 errmsg =
"missing relationship-name";
499 reason = FTR_INVALID_PARTNER;
508 &link->imsg->relationship_name))
515 errmsg =
"unknown failover relationship name";
516 reason = FTR_INVALID_PARTNER;
524 slen = strlen(sname);
525 }
else if (link->imsg->options_present &
526 FTB_RELATIONSHIP_NAME) {
527 sname = (
char *)link->imsg->
528 relationship_name.data;
529 slen = link->imsg->relationship_name.count;
532 slen = strlen(sname);
535 log_error(
"Failover CONNECT from %.*s: %s",
536 slen, sname, errmsg);
540 log_info (
"failover: disconnect: %s", errmsg);
542 link -> state = dhcp_flink_disconnected;
543 return ISC_R_SUCCESS;
546 if ((
cur_time > link -> imsg -> time &&
547 cur_time - link -> imsg -> time > 60) ||
548 (cur_time < link -> imsg -> time &&
549 link -> imsg -> time -
cur_time > 60)) {
550 errmsg =
"time offset too large";
551 reason = FTR_TIMEMISMATCH;
555 if (!(link -> imsg -> options_present & FTB_HBA) ||
556 link -> imsg -> hba.count != 32) {
557 errmsg =
"invalid HBA";
558 reason = FTR_HBA_CONFLICT;
565 errmsg =
"no memory";
566 reason = FTR_MISC_REJECT;
569 memcpy (state -> hba, link -> imsg -> hba.data, 32);
571 if (!link -> state_object)
572 dhcp_failover_state_reference
573 (&link -> state_object, state,
MDL);
574 if (!link -> peer_address)
576 (&link -> peer_address,
577 state -> partner.address,
MDL);
583 if (!link -> state_object) {
584 log_info (
"failover: connect: no matching state.");
586 link -> state = dhcp_flink_disconnected;
594 link -> state = dhcp_flink_message_length_wait;
596 failover_message_dereference (&link -> imsg,
MDL);
610 return ISC_R_SUCCESS;
613 static isc_result_t do_a_failover_option (c, link)
615 dhcp_failover_link_t *link;
617 u_int16_t option_code;
618 u_int16_t option_len;
624 if (link -> imsg_count + 2 > link -> imsg_len) {
625 log_error (
"FAILOVER: message overflow at option code.");
629 if (link->imsg->type > FTM_MAX) {
630 log_error (
"FAILOVER: invalid message type: %d",
637 link -> imsg_count += 2;
639 if (link -> imsg_count + 2 > link -> imsg_len) {
640 log_error (
"FAILOVER: message overflow at length.");
646 link -> imsg_count += 2;
648 if (link -> imsg_count + option_len > link -> imsg_len) {
649 log_error (
"FAILOVER: message overflow at data.");
654 if ((option_code > FTO_MAX) ||
656 #if defined (DEBUG_FAILOVER_MESSAGES) 657 log_debug (
" option code %d (%s) len %d (not recognized)",
663 link -> imsg_count += option_len;
664 return ISC_R_SUCCESS;
668 if (
ft_options [option_code].type == FT_DIGEST) {
669 link -> imsg_count += option_len;
670 if (link -> imsg_count != link -> imsg_len) {
671 log_error (
"FAILOVER: digest not at end of message");
674 #if defined (DEBUG_FAILOVER_MESSAGES) 680 return ISC_R_SUCCESS;
684 if (link -> imsg -> options_present &
ft_options [option_code].bit) {
685 log_error (
"FAILOVER: duplicate option %s",
700 link -> imsg_count += option_len;
701 return ISC_R_SUCCESS;
711 op = ((
unsigned char *)link -> imsg) +
714 op_count = ft_options [option_code].num_present;
716 if (option_len != op_size * op_count) {
717 log_error (
"FAILOVER: option size (%d:%d), option %s",
719 (
ft_sizes [ft_options [option_code].type] *
720 ft_options [option_code].num_present),
721 ft_options [option_code].name);
725 failover_option_t *fo;
732 if (ft_options [option_code].type == FT_DDNS ||
733 ft_options [option_code].type == FT_DDNS1) {
736 (((
char *)link -> imsg) +
737 ft_options [option_code].offset));
739 op_count = (ft_options [option_code].type == FT_DDNS1
744 link -> imsg_count += op_count;
746 ddns -> codes [1] = 0;
748 op_count = option_len - op_count;
750 ddns -> length = op_count;
753 log_error (
"FAILOVER: no memory getting%s(%d)",
754 " DNS data ", op_count);
769 op_size =
ft_sizes [ft_options [option_code].type];
773 if (op_size > 1 && option_len % op_size) {
774 log_error (
"FAILOVER: option_len %d not %s%d",
775 option_len,
"multiple of ", op_size);
779 op_count = option_len / op_size;
781 fo = ((failover_option_t *)
782 (((
char *)link -> imsg) +
783 ft_options [option_code].offset));
785 fo -> count = op_count;
788 log_error (
"FAILOVER: no memory getting %s (%d)",
789 "option data", op_count);
798 if (op_size == 1 || ft_options [option_code].type == FT_IPADDR) {
800 link -> imsg_count += option_len;
823 if ((option_code == 11) && (option_len > 9) &&
824 (strncmp((
const char *)op,
"isc-V3.0.", 9) == 0)) {
825 log_error(
"WARNING: failover as of versions 3.1.0 and " 826 "on are not reverse compatible with " 835 for (i = 0; i < op_count; i++) {
836 switch (ft_options [option_code].type) {
840 link -> imsg_count += 4;
846 link -> imsg_count += 2;
852 log_error (
"FAILOVER: option %s: bad type %d",
853 ft_options [option_code].name,
854 ft_options [option_code].type);
860 link -> imsg -> options_present |= ft_options [option_code].bit;
861 return ISC_R_SUCCESS;
878 if (h -> inner && h -> inner -> type -> set_value)
879 return (*(h -> inner -> type -> set_value))
880 (h -> inner, id, name, value);
881 return ISC_R_NOTFOUND;
889 dhcp_failover_link_t *link;
893 link = (dhcp_failover_link_t *)h;
897 (
int)link -> peer_port,
MDL);
899 if (link -> state >= dhcp_flink_state_max)
901 "invalid link state",
908 if (h -> inner && h -> inner -> type -> get_value)
909 return (*(h -> inner -> type -> get_value))
910 (h -> inner, id, name, value);
911 return ISC_R_NOTFOUND;
915 const char *file,
int line)
917 dhcp_failover_link_t *link;
920 link = (dhcp_failover_link_t *)h;
922 if (link -> peer_address)
925 failover_message_dereference (&link -> imsg, file, line);
926 if (link -> state_object)
927 dhcp_failover_state_dereference (&link -> state_object,
929 return ISC_R_SUCCESS;
939 dhcp_failover_link_t *link;
944 link = (dhcp_failover_link_t *)l;
947 if (status != ISC_R_SUCCESS)
950 if (status != ISC_R_SUCCESS)
953 if (status != ISC_R_SUCCESS)
957 if (status != ISC_R_SUCCESS)
959 if (link -> state >= dhcp_flink_state_max)
964 if (status != ISC_R_SUCCESS)
967 if (link -> inner && link -> inner -> type -> stuff_values)
968 return (*(link -> inner -> type -> stuff_values)) (c,
id,
970 return ISC_R_SUCCESS;
985 "local-port", &value);
986 if (status != ISC_R_SUCCESS)
988 if (!value -> value) {
995 if (status != ISC_R_SUCCESS)
997 local_addr.
port = port;
1000 "local-address", &value);
1001 if (status != ISC_R_SUCCESS)
1003 if (!value -> value) {
1010 value -> value -> u.buffer.len != sizeof (
struct in_addr))
1013 memcpy (local_addr.
address, value -> value -> u.buffer.
value,
1014 value -> value -> u.buffer.len);
1015 local_addr.
addrlen = value -> value -> u.buffer.len;
1021 for (l = failover_listeners; l; l = l -> next) {
1022 if (l -> address.port == local_addr.
port &&
1023 l -> address.addrtype == local_addr.
addrtype &&
1024 l -> address.addrlen == local_addr.
addrlen &&
1025 !memcmp (l -> address.address, local_addr.
address,
1031 return ISC_R_SUCCESS;
1034 status = dhcp_failover_listener_allocate (&obj,
MDL);
1035 if (status != ISC_R_SUCCESS)
1037 obj -> address = local_addr;
1040 if (status != ISC_R_SUCCESS)
1045 if (status != ISC_R_SUCCESS) {
1046 dhcp_failover_listener_dereference (&obj,
MDL);
1050 if (status != ISC_R_SUCCESS) {
1051 dhcp_failover_listener_dereference (&obj,
MDL);
1056 if (failover_listeners) {
1057 dhcp_failover_listener_reference (&obj -> next,
1058 failover_listeners,
MDL);
1059 dhcp_failover_listener_dereference (&failover_listeners,
MDL);
1061 dhcp_failover_listener_reference (&failover_listeners, obj,
MDL);
1063 return dhcp_failover_listener_dereference (&obj,
MDL);
1070 const char *name, va_list ap)
1072 isc_result_t status;
1074 dhcp_failover_link_t *obj;
1076 dhcp_failover_state_t *s, *state = (dhcp_failover_state_t *)0;
1083 if (strcmp (name,
"connect")) {
1084 if (p -> inner && p -> inner -> type -> signal_handler)
1085 return (*(p -> inner -> type -> signal_handler))
1086 (p -> inner, name, ap);
1087 return ISC_R_NOTFOUND;
1098 (s, (u_int8_t *)&c -> remote_addr.sin_addr,
1099 sizeof c -> remote_addr.sin_addr)) {
1105 log_info (
"failover: listener: no matching state");
1107 return(ISC_R_NOTFOUND);
1110 obj = (dhcp_failover_link_t *)0;
1111 status = dhcp_failover_link_allocate (&obj,
MDL);
1112 if (status != ISC_R_SUCCESS)
1114 obj -> peer_port = ntohs (c -> remote_addr.sin_port);
1118 if (status != ISC_R_SUCCESS) {
1120 dhcp_failover_link_dereference (&obj,
MDL);
1121 log_info (
"failover: listener: picayune failure.");
1128 if (status != ISC_R_SUCCESS)
1131 status = dhcp_failover_state_reference (&obj -> state_object,
1133 if (status != ISC_R_SUCCESS)
1138 return dhcp_failover_link_dereference (&obj,
MDL);
1149 if (h -> inner && h -> inner -> type -> set_value)
1150 return (*(h -> inner -> type -> set_value))
1151 (h -> inner, id, name, value);
1152 return ISC_R_NOTFOUND;
1163 if (h -> inner && h -> inner -> type -> get_value)
1164 return (*(h -> inner -> type -> get_value))
1165 (h -> inner, id, name, value);
1166 return ISC_R_NOTFOUND;
1170 const char *file,
int line)
1178 dhcp_failover_listener_dereference (&l -> next, file, line);
1180 return ISC_R_SUCCESS;
1193 if (p -> inner && p -> inner -> type -> stuff_values)
1194 return (*(p -> inner -> type -> stuff_values)) (c, id,
1196 return ISC_R_SUCCESS;
1203 isc_result_t status;
1204 dhcp_failover_state_t *obj;
1209 "local-port", &value);
1210 if (status != ISC_R_SUCCESS)
1212 if (!value -> value) {
1219 if (status != ISC_R_SUCCESS)
1222 obj = (dhcp_failover_state_t *)0;
1223 dhcp_failover_state_allocate (&obj,
MDL);
1224 obj -> me.port = port;
1227 if (status != ISC_R_SUCCESS) {
1228 dhcp_failover_state_dereference (&obj,
MDL);
1234 if (status != ISC_R_SUCCESS) {
1235 dhcp_failover_state_dereference (&obj,
MDL);
1239 dhcp_failover_state_dereference (&obj,
MDL);
1246 const char *name, va_list ap)
1248 isc_result_t status;
1249 dhcp_failover_state_t *state;
1250 dhcp_failover_link_t *link;
1255 state = (dhcp_failover_state_t *)o;
1258 if (strcmp (name,
"disconnect") &&
1259 strcmp (name,
"message")) {
1260 if (state -> inner && state -> inner -> type -> signal_handler)
1261 return (*(state -> inner -> type -> signal_handler))
1262 (state -> inner, name, ap);
1263 return ISC_R_NOTFOUND;
1268 if (!strcmp (name,
"disconnect")) {
1269 link = va_arg (ap, dhcp_failover_link_t *);
1271 dhcp_failover_link_dereference (&state -> link_to_peer,
MDL);
1273 if (state -> i_am == primary) {
1274 #if defined (DEBUG_FAILOVER_TIMING) 1276 "dhcp_failover_reconnect");
1282 (
tvref_t)dhcp_failover_state_reference,
1284 dhcp_failover_state_dereference);
1286 }
else if (!strcmp (name,
"message")) {
1287 link = va_arg (ap, dhcp_failover_link_t *);
1289 if (link -> imsg -> type == FTM_CONNECT) {
1295 if (state -> link_to_peer) {
1299 "already connected");
1301 return ISC_R_SUCCESS;
1303 if (!(link -> imsg -> options_present & FTB_MCLT)) {
1307 "no MCLT provided");
1309 return ISC_R_SUCCESS;
1312 dhcp_failover_link_reference (&state -> link_to_peer,
1316 if (status != ISC_R_SUCCESS) {
1317 dhcp_failover_link_dereference
1318 (&state -> link_to_peer,
MDL);
1319 log_info (
"dhcp_failover_send_connectack: %s",
1320 isc_result_totext (status));
1322 return ISC_R_SUCCESS;
1324 if (link -> imsg -> options_present & FTB_MAX_UNACKED)
1325 state -> partner.max_flying_updates =
1326 link -> imsg -> max_unacked;
1327 if (link -> imsg -> options_present & FTB_RECEIVE_TIMER)
1328 state -> partner.max_response_delay =
1329 link -> imsg -> receive_timer;
1330 state -> mclt = link -> imsg -> mclt;
1334 }
else if (link -> imsg -> type == FTM_CONNECTACK) {
1342 if (!(link->imsg->options_present &
1343 FTB_RELATIONSHIP_NAME)) {
1344 errmsg =
"missing relationship-name";
1345 reason = FTR_INVALID_PARTNER;
1349 if (link->imsg->options_present & FTB_REJECT_REASON) {
1351 log_error (
"Failover CONNECT to %s rejected: %s",
1352 state ? state->name :
"unknown",
1354 (link -> imsg -> reject_reason)));
1357 return ISC_R_SUCCESS;
1361 &link->imsg->relationship_name)) {
1363 snprintf(errbuf,
sizeof(errbuf),
"remote failover " 1364 "relationship name %.*s does not match",
1365 (
int)link->imsg->relationship_name.count,
1366 link->imsg->relationship_name.data);
1368 reason = FTR_INVALID_PARTNER;
1370 log_error(
"Failover CONNECTACK from %s: %s",
1371 state->name, errmsg);
1375 return ISC_R_SUCCESS;
1378 if (state -> link_to_peer) {
1379 errmsg =
"already connected";
1380 reason = FTR_DUP_CONNECTION;
1384 if ((
cur_time > link -> imsg -> time &&
1385 cur_time - link -> imsg -> time > 60) ||
1386 (cur_time < link -> imsg -> time &&
1387 link -> imsg -> time -
cur_time > 60)) {
1388 errmsg =
"time offset too large";
1389 reason = FTR_TIMEMISMATCH;
1393 dhcp_failover_link_reference (&state -> link_to_peer,
1400 if (state -> me.state ==
startup)
1402 state -> saved_state);
1407 if (link -> imsg -> options_present & FTB_MAX_UNACKED)
1408 state -> partner.max_flying_updates =
1409 link -> imsg -> max_unacked;
1410 if (link -> imsg -> options_present & FTB_RECEIVE_TIMER)
1411 state -> partner.max_response_delay =
1412 link -> imsg -> receive_timer;
1413 #if defined (DEBUG_FAILOVER_CONTACT_TIMING) 1415 (
int)state -> partner.max_response_delay / 3,
1416 "dhcp_failover_send_contact");
1419 (
int)state -> partner.max_response_delay / 3;
1423 (
tvref_t)dhcp_failover_state_reference,
1424 (
tvunref_t)dhcp_failover_state_dereference);
1425 #if defined (DEBUG_FAILOVER_CONTACT_TIMING) 1427 (
int)state -> me.max_response_delay,
1428 "dhcp_failover_timeout");
1431 (
int)state -> me.max_response_delay;
1435 (
tvref_t)dhcp_failover_state_reference,
1436 (
tvunref_t)dhcp_failover_state_dereference);
1437 }
else if (link -> imsg -> type == FTM_DISCONNECT) {
1438 if (link -> imsg -> reject_reason) {
1439 log_error (
"Failover DISCONNECT from %s: %s",
1440 state ? state->name :
"unknown",
1442 (link -> imsg -> reject_reason)));
1445 }
else if (link -> imsg -> type == FTM_BNDUPD) {
1448 }
else if (link -> imsg -> type == FTM_BNDACK) {
1450 }
else if (link -> imsg -> type == FTM_UPDREQ) {
1453 }
else if (link -> imsg -> type == FTM_UPDREQALL) {
1455 (state, link -> imsg);
1456 }
else if (link -> imsg -> type == FTM_UPDDONE) {
1459 }
else if (link -> imsg -> type == FTM_POOLREQ) {
1460 dhcp_failover_pool_reqbalance(state);
1461 }
else if (link -> imsg -> type == FTM_POOLRESP) {
1462 log_info (
"pool response: %ld leases",
1464 link -> imsg -> addresses_transferred);
1465 }
else if (link -> imsg -> type == FTM_STATE) {
1474 if (state -> link_to_peer &&
1475 state -> link_to_peer == link &&
1476 state -> link_to_peer -> state != dhcp_flink_disconnected)
1478 #if defined (DEBUG_FAILOVER_CONTACT_TIMING) 1480 (
int)state -> me.max_response_delay,
1481 "dhcp_failover_timeout");
1484 (
int)state -> me.max_response_delay;
1488 (
tvref_t)dhcp_failover_state_reference,
1489 (
tvunref_t)dhcp_failover_state_dereference);
1495 return ISC_R_SUCCESS;
1501 isc_result_t status;
1504 if (!strcmp (name,
"disconnect")) {
1505 if (state -> link_to_peer) {
1506 log_info (
"peer %s: disconnected", state -> name);
1507 if (state -> link_to_peer -> state_object)
1508 dhcp_failover_state_dereference
1509 (&state -> link_to_peer -> state_object,
MDL);
1510 dhcp_failover_link_dereference (&state -> link_to_peer,
1517 switch (state -> me.state ==
startup ?
1518 state -> saved_state : state -> me.state) {
1540 if (state -> me.state ==
startup)
1542 (state, state -> saved_state));
1543 return ISC_R_SUCCESS;
1561 }
else if (!strcmp (name,
"connect")) {
1562 switch (state -> me.state) {
1589 }
else if (!strcmp (name,
"startup")) {
1591 return ISC_R_SUCCESS;
1592 }
else if (!strcmp (name,
"connect-timeout")) {
1593 switch (state -> me.state) {
1601 return ISC_R_SUCCESS;
1625 switch (state -> me.state) {
1628 state -> nrr =
" (my state unknown)";
1650 state -> nrr =
" (resolving conflicts)";
1655 state -> nrr =
" (recovering)";
1660 state -> nrr =
" (shut down)";
1665 state -> nrr =
" (paused)";
1670 state -> nrr =
" (recover wait)";
1675 state -> nrr =
" (recover done)";
1680 state -> nrr =
" (startup)";
1692 switch (state -> partner.state) {
1695 state -> nrr =
" (peer demands: recovering)";
1702 state -> nrr =
" (peer demands: resolving conflicts)";
1711 return ISC_R_SUCCESS;
1730 if (state->ack_queue_tail == NULL)
1734 for (lp = state->ack_queue_head; lp; lp = lp->
next_pending)
1738 if (state->update_queue_head) {
1739 lease_reference(&state->ack_queue_tail->next_pending,
1740 state->update_queue_head,
MDL);
1741 lease_dereference(&state->update_queue_head,
MDL);
1743 lease_reference(&state->update_queue_head, state->ack_queue_head,
MDL);
1745 if (!state->update_queue_tail) {
1746 #if defined (POINTER_DEBUG) 1747 if (state->ack_queue_tail->next_pending) {
1748 log_error(
"next pending on ack queue tail.");
1752 lease_reference(&state->update_queue_tail,
1753 state->ack_queue_tail,
MDL);
1755 lease_dereference(&state->ack_queue_tail,
MDL);
1756 lease_dereference(&state->ack_queue_head,
MDL);
1757 state->cur_unacked_updates = 0;
1774 switch (state -> me.state) {
1790 saved_state = state -> me.state;
1791 saved_stos = state -> me.stos;
1806 !state -> update_queue_head && !state -> ack_queue_head)
1807 state -> me.stos =
cur_time - state -> mclt;
1809 state -> me.state = new_state;
1811 state -> saved_state = saved_state;
1815 log_error (
"Unable to record current failover state for %s",
1817 state -> me.state = saved_state;
1818 state -> me.stos = saved_stos;
1819 return ISC_R_IOERROR;
1822 log_info (
"failover peer %s: I move from %s to %s",
1827 if ((state->me.state ==
normal) && (state->partner.state ==
normal))
1828 log_info(
"failover peer %s: Both servers normal", state->name);
1844 if (state -> link_to_peer)
1847 switch (new_state) {
1857 if (state->auto_partner_down == 0)
1860 #if defined (DEBUG_FAILOVER_TIMING) 1861 log_info(
"add_timeout +%lu dhcp_failover_auto_partner_down",
1862 (
unsigned long)state->auto_partner_down);
1864 tv.tv_sec =
cur_time + state->auto_partner_down;
1877 dhcp_failover_pool_balance(state);
1880 if (state->update_queue_tail != NULL) {
1882 log_info(
"Sending updates to %s.", state->name);
1888 if ((state->i_am == primary) ||
1889 ((state->i_am == secondary) &&
1895 #if defined (DEBUG_FAILOVER_TIMING) 1897 "dhcp_failover_startup_timeout");
1904 (
tvref_t)omapi_object_reference,
1912 if (state -> me.stos + state -> mclt >
cur_time) {
1913 #if defined (DEBUG_FAILOVER_TIMING) 1916 state -> me.stos + state -> mclt),
1917 "dhcp_failover_startup_timeout");
1919 tv . tv_sec = (
int)(state -> me.stos + state -> mclt);
1924 (
tvref_t)omapi_object_reference,
1936 if (state -> link_to_peer)
1944 #if defined (BINARY_LEASES) 1945 long int tiebreaker = 0;
1951 l->
tsfp = state->me.stos + state->mclt;
1959 if (tiebreaker != LONG_MAX)
1969 #if defined (DEBUG_FAILOVER_TIMING) 1989 return ISC_R_SUCCESS;
1993 failover_message_t *msg)
1999 new_state = msg -> server_state;
2000 startupp = (msg -> server_flags & FTF_SERVER_STARTUP) ? 1 : 0;
2002 if (state -> partner.state == new_state && state -> me.state) {
2003 switch (state -> me.state) {
2016 state->saved_state);
2017 return ISC_R_SUCCESS;
2026 return ISC_R_SUCCESS;
2043 state -> partner.state = new_state;
2046 log_info (
"failover peer %s: peer moves from %s to %s",
2052 if ((state->me.state ==
normal) && (state->partner.state ==
normal))
2053 log_info(
"failover peer %s: Both servers normal", state->name);
2059 log_error (
"Unable to record current failover state for %s",
2066 switch (new_state) {
2083 log_error(
"failover peer %s: Invalid state: %d", state->name,
2086 return ISC_R_SUCCESS;
2092 switch (state -> me.state ==
startup ?
2093 state -> saved_state : state -> me.state) {
2095 switch (new_state) {
2101 if (state -> me.state ==
startup)
2112 log_error(
"Peer %s: Invalid state transition %s " 2113 "to %s.", state->name,
2138 switch (new_state) {
2140 log_info (
"failover peer %s: requesting %s",
2141 state -> name,
"full update from peer");
2145 if (state -> me.state ==
recover)
2171 if (state -> me.state ==
recover)
2192 switch (new_state) {
2195 log_error(
"Peer %s moves to normal during conflict " 2196 "resolution - panic, shutting down.",
2205 log_error(
"Peer %s: Unexpected move to " 2206 "conflict-done.", state->name);
2233 switch (new_state) {
2251 log_fatal(
"Peer %s: Invalid attempt to move from %s " 2252 "to %s while local state is conflict-done.",
2264 switch (new_state) {
2290 switch (new_state) {
2330 switch (new_state) {
2358 switch (new_state) {
2360 log_error(
"Both servers have entered recover-done!");
2401 if (state -> me.state ==
startup && state -> saved_state !=
startup)
2408 return ISC_R_SUCCESS;
2417 dhcp_failover_pool_balance(dhcp_failover_state_t *state)
2421 state->sched_balance = 0;
2423 dhcp_failover_pool_dobalance(state, NULL);
2434 dhcp_failover_state_t *state;
2435 isc_boolean_t sendreq = ISC_FALSE;
2437 state = (dhcp_failover_state_t *)failover_state;
2440 state->sched_balance = 0;
2442 if (dhcp_failover_pool_dobalance(state, &sendreq))
2454 dhcp_failover_pool_reqbalance(dhcp_failover_state_t *state)
2460 state->sched_balance = 0;
2462 queued = dhcp_failover_pool_dobalance(state, NULL);
2469 log_info(
"peer %s: Got POOLREQ, answering negatively! " 2470 "Peer may be out of leases or database inconsistent.",
2482 dhcp_failover_pool_dobalance(dhcp_failover_state_t *state,
2483 isc_boolean_t *sendreq)
2485 int lts, total, thresh, hold, panic, pass;
2486 int leases_queued = 0;
2487 struct lease *lp = NULL;
2489 struct lease *ltemp = NULL;
2496 int (*log_func)(
const char *, ...);
2497 const char *result, *reqlog;
2499 if (state -> me.state !=
normal)
2529 thresh = ((total * state->max_lease_misbalance) + 50) / 100;
2530 hold = ((total * state->max_lease_ownership) + 50) / 100;
2545 panic = thresh * -2;
2550 if ((sendreq != NULL) && (lts < panic)) {
2551 reqlog =
" (requesting peer rebalance!)";
2552 *sendreq = ISC_TRUE;
2556 log_info(
"balancing pool %lx %s total %d free %d " 2557 "backup %d lts %d max-own (+/-)%d%s",
2559 (p->shared_network ?
2561 p->free_leases, p->backup_leases, lts, hold,
2581 lease_dereference(&next,
MDL);
2584 lease_reference(&next, ltemp,
MDL);
2611 }
else if (lts <= -hold)
2627 lease_dereference(&lp,
MDL);
2629 lease_reference(&lp, next,
MDL);
2637 lease_dereference(&next,
MDL);
2639 lease_dereference(&lp,
MDL);
2642 result =
"IMBALANCED";
2645 result =
"balanced";
2649 log_func(
"%s pool %lx %s total %d free %d backup %d " 2650 "lts %d max-misbal %d", result, (
unsigned long)p,
2651 (p->shared_network ?
2652 p->shared_network->name :
""), p->lease_count,
2653 p->free_leases, p->backup_leases, lts, thresh);
2663 return leases_queued;
2673 dhcp_failover_state_t *peer;
2676 struct lease *ltemp;
2680 if(!peer || peer->me.state !=
normal)
2709 est1 = ((est1 * peer->max_lease_misbalance) + 50) / 100;
2710 est2 = ((est2 * peer->max_lease_misbalance) + 50) / 100;
2715 if(peer->i_am == primary)
2725 if(est1 > peer->max_balance)
2726 est1 = peer->max_balance;
2732 est2 = peer->last_balance + peer->min_balance;
2733 if(peer->last_balance && (est1 < est2))
2737 est1 += random() % 5;
2740 if(peer->sched_balance) {
2741 if (est1 >= peer->sched_balance)
2751 peer->sched_balance = est1;
2753 #if defined(DEBUG_FAILOVER_TIMING) 2754 log_info(
"add_timeout +%d dhcp_failover_pool_rebalance",
2760 (
tvref_t)dhcp_failover_state_reference,
2761 (
tvunref_t)dhcp_failover_state_dereference);
2770 for (p = s ->
pools; p; p = p ->
next) {
2782 isc_result_t status;
2785 if (!state -> link_to_peer)
2786 return ISC_R_SUCCESS;
2791 if (state->toack_queue_head != NULL)
2794 while ((state -> partner.max_flying_updates >
2795 state -> cur_unacked_updates) && state -> update_queue_head) {
2797 lease_reference (&lp, state -> update_queue_head,
MDL);
2801 if (status != ISC_R_SUCCESS) {
2802 lease_dereference (&lp,
MDL);
2809 lease_dereference (&state -> update_queue_head,
MDL);
2811 lease_reference (&state -> update_queue_head,
2815 lease_dereference (&state -> update_queue_tail,
MDL);
2818 if (state -> ack_queue_head) {
2822 lease_dereference (&state -> ack_queue_tail,
MDL);
2824 lease_reference (&state -> ack_queue_head, lp,
MDL);
2826 #if defined (POINTER_DEBUG) 2828 log_error (
"ack_queue_tail: lp -> next_pending");
2832 lease_reference (&state -> ack_queue_tail, lp,
MDL);
2834 lease_dereference (&lp,
MDL);
2837 state -> cur_unacked_updates++;
2839 return ISC_R_SUCCESS;
2848 dhcp_failover_state_t *
state;
2850 if (!lease -> pool ||
2851 !lease -> pool -> failover_peer)
2859 state = lease -> pool -> failover_peer;
2865 if (state -> update_queue_head) {
2866 lease_reference (&state -> update_queue_tail ->
next_pending,
2868 lease_dereference (&state -> update_queue_tail,
MDL);
2870 lease_reference (&state -> update_queue_head, lease,
MDL);
2872 #if defined (POINTER_DEBUG) 2874 log_error (
"next pending on update queue lease.");
2875 #if defined (DEBUG_RC_HISTORY) 2876 dump_rc_history (lease);
2881 lease_reference (&state -> update_queue_tail, lease,
MDL);
2890 failover_message_t *msg = (failover_message_t *)0;
2896 while (state -> toack_queue_head) {
2897 failover_message_reference
2898 (&msg, state -> toack_queue_head,
MDL);
2899 failover_message_dereference
2900 (&state -> toack_queue_head,
MDL);
2902 failover_message_reference
2903 (&state -> toack_queue_head, msg -> next,
MDL);
2908 failover_message_dereference (&msg,
MDL);
2911 if (state -> toack_queue_tail)
2912 failover_message_dereference (&state -> toack_queue_tail,
MDL);
2913 state -> pending_acks = 0;
2920 dhcp_failover_state_t *state = vs;
2922 #if defined (DEBUG_FAILOVER_TIMING) 2923 log_info (
"dhcp_failover_toack_queue_timeout");
2933 failover_message_t *msg)
2937 if (state -> toack_queue_head) {
2938 failover_message_reference
2939 (&state -> toack_queue_tail -> next, msg,
MDL);
2940 failover_message_dereference (&state -> toack_queue_tail,
MDL);
2942 failover_message_reference (&state -> toack_queue_head,
2945 failover_message_reference (&state -> toack_queue_tail, msg,
MDL);
2947 state -> pending_acks++;
2951 if (state -> pending_acks >= state -> partner.max_flying_updates / 2) {
2956 if (state -> pending_acks > 0) {
2957 #if defined (DEBUG_FAILOVER_TIMING) 2959 "dhcp_failover_toack_queue_timeout");
2965 (
tvref_t)dhcp_failover_state_reference,
2966 (
tvunref_t)dhcp_failover_state_dereference);
2973 struct lease *lease)
2977 if (!(lease ->
flags & ON_ACK_QUEUE))
2980 if (state -> ack_queue_head == lease) {
2981 lease_dereference (&state -> ack_queue_head,
MDL);
2983 lease_reference (&state -> ack_queue_head,
2987 lease_dereference (&state -> ack_queue_tail,
MDL);
2990 for (lp = state -> ack_queue_head;
3004 lease_dereference (&state -> ack_queue_tail,
MDL);
3009 lease_reference (&state -> ack_queue_tail, lp,
MDL);
3013 lease ->
flags &= ~ON_ACK_QUEUE;
3020 state -> cur_unacked_updates--;
3027 if (state -> cur_unacked_updates == 0) {
3037 isc_result_t status;
3047 return ISC_R_SUCCESS;
3049 return ISC_R_SUCCESS;
3051 return ISC_R_SUCCESS;
3053 return ISC_R_SUCCESS;
3055 return ISC_R_SUCCESS;
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;
3069 if (status != ISC_R_SUCCESS)
3073 return ISC_R_SUCCESS;
3075 return ISC_R_SUCCESS;
3077 return ISC_R_SUCCESS;
3079 return ISC_R_SUCCESS;
3081 return ISC_R_SUCCESS;
3083 return ISC_R_SUCCESS;
3085 return ISC_R_SUCCESS;
3087 return ISC_R_SUCCESS;
3090 if (h -> inner && h -> inner -> type -> set_value)
3091 return (*(h -> inner -> type -> set_value))
3092 (h -> inner, id, name, value);
3093 return ISC_R_NOTFOUND;
3102 dhcp_failover_state_t *state = vs;
3103 isc_result_t status;
3106 #if defined (DEBUG_FAILOVER_TIMING) 3107 log_info (
"dhcp_failover_reconnect");
3111 if (state -> link_to_peer)
3116 log_info (
"failover peer %s: %s", state -> name,
3117 isc_result_totext (status));
3118 #if defined (DEBUG_FAILOVER_TIMING) 3119 log_info(
"add_timeout +90 dhcp_failover_reconnect");
3124 (
tvref_t)dhcp_failover_state_reference,
3125 (
tvunref_t)dhcp_failover_state_dereference);
3131 dhcp_failover_state_t *state = vs;
3133 #if defined (DEBUG_FAILOVER_TIMING) 3134 log_info (
"dhcp_failover_startup_timeout");
3142 dhcp_failover_link_t *link = vl;
3147 for (; p; p = p -> outer)
3151 log_info (
"failover: link startup timeout");
3158 dhcp_failover_state_t *state = vs;
3159 isc_result_t status;
3162 #if defined (DEBUG_FAILOVER_TIMING) 3163 log_info (
"dhcp_failover_listener_restart");
3167 if (status != ISC_R_SUCCESS) {
3168 log_info (
"failover peer %s: %s", state -> name,
3169 isc_result_totext (status));
3170 #if defined (DEBUG_FAILOVER_TIMING) 3172 "dhcp_failover_listener_restart");
3178 (
tvref_t)dhcp_failover_state_reference,
3179 (
tvunref_t)dhcp_failover_state_dereference);
3186 dhcp_failover_state_t *state = vs;
3188 #if defined (DEBUG_FAILOVER_TIMING) 3189 log_info(
"dhcp_failover_auto_partner_down");
3200 dhcp_failover_state_t *s;
3203 isc_result_t status;
3207 s = (dhcp_failover_state_t *)h;
3212 name, s -> name,
MDL);
3213 return ISC_R_NOTFOUND;
3215 oc = s -> partner.address;
3217 memset (&ds, 0,
sizeof ds);
3224 return ISC_R_NOTFOUND;
3227 name, ds.data, ds.
len,
MDL);
3234 oc = s -> me.address;
3238 s -> partner.port,
MDL);
3241 name, s -> me.port,
MDL);
3244 s -> me.max_flying_updates,
3250 s -> load_balance_max_secs,
MDL);
3255 return ISC_R_NOTFOUND;
3258 s -> partner.state,
MDL);
3261 s -> me.state,
MDL);
3264 s -> partner.stos,
MDL);
3272 s -> last_packet_sent,
MDL);
3275 s -> last_timestamp_received,
3281 s -> me.max_response_delay,
3285 s -> cur_unacked_updates,
MDL);
3288 if (h -> inner && h -> inner -> type -> get_value)
3289 return (*(h -> inner -> type -> get_value))
3290 (h -> inner, id, name, value);
3291 return ISC_R_NOTFOUND;
3295 const char *file,
int line)
3297 dhcp_failover_state_t *s;
3301 s = (dhcp_failover_state_t *)h;
3303 if (s -> link_to_peer)
3304 dhcp_failover_link_dereference (&s -> link_to_peer, file, line);
3307 s -> name = (
char *)0;
3309 if (s -> partner.address)
3311 if (s -> me.address)
3314 dfree (s -> hba, file, line);
3315 s -> hba = (u_int8_t *)0;
3317 if (s -> update_queue_head)
3318 lease_dereference (&s -> update_queue_head, file, line);
3319 if (s -> update_queue_tail)
3320 lease_dereference (&s -> update_queue_tail, file, line);
3321 if (s -> ack_queue_head)
3322 lease_dereference (&s -> ack_queue_head, file, line);
3323 if (s -> ack_queue_tail)
3324 lease_dereference (&s -> ack_queue_tail, file, line);
3325 if (s -> send_update_done)
3326 lease_dereference (&s -> send_update_done, file, line);
3327 if (s -> toack_queue_head)
3328 failover_message_dereference (&s -> toack_queue_head,
3330 if (s -> toack_queue_tail)
3331 failover_message_dereference (&s -> toack_queue_tail,
3333 return ISC_R_SUCCESS;
3345 dhcp_failover_state_t *s;
3346 isc_result_t status;
3353 s = (dhcp_failover_state_t *)h;
3356 if (status != ISC_R_SUCCESS)
3359 if (status != ISC_R_SUCCESS)
3363 if (status != ISC_R_SUCCESS)
3366 if (status != ISC_R_SUCCESS)
3369 sizeof s -> partner.address);
3370 if (status != ISC_R_SUCCESS)
3374 if (status != ISC_R_SUCCESS)
3377 if (status != ISC_R_SUCCESS)
3380 if (status != ISC_R_SUCCESS)
3384 if (status != ISC_R_SUCCESS)
3387 if (status != ISC_R_SUCCESS)
3390 sizeof s -> me.address);
3391 if (status != ISC_R_SUCCESS)
3395 if (status != ISC_R_SUCCESS)
3398 if (status != ISC_R_SUCCESS)
3401 if (status != ISC_R_SUCCESS)
3405 if (status != ISC_R_SUCCESS)
3408 if (status != ISC_R_SUCCESS)
3411 s -> me.max_flying_updates);
3412 if (status != ISC_R_SUCCESS)
3416 if (status != ISC_R_SUCCESS)
3419 if (status != ISC_R_SUCCESS)
3422 if (status != ISC_R_SUCCESS)
3426 if (status != ISC_R_SUCCESS)
3429 if (status != ISC_R_SUCCESS)
3432 (c, (u_int32_t)s -> load_balance_max_secs));
3433 if (status != ISC_R_SUCCESS)
3439 if (status != ISC_R_SUCCESS)
3442 if (status != ISC_R_SUCCESS)
3445 if (status != ISC_R_SUCCESS)
3450 if (status != ISC_R_SUCCESS)
3453 if (status != ISC_R_SUCCESS)
3456 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 (u_int32_t)s -> partner.stos);
3477 if (status != ISC_R_SUCCESS)
3481 if (status != ISC_R_SUCCESS)
3484 if (status != ISC_R_SUCCESS)
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 (c, (u_int32_t)s -> last_packet_sent));
3508 if (status != ISC_R_SUCCESS)
3512 if (status != ISC_R_SUCCESS)
3515 if (status != ISC_R_SUCCESS)
3518 (c, (u_int32_t)s -> last_timestamp_received));
3519 if (status != ISC_R_SUCCESS)
3523 if (status != ISC_R_SUCCESS)
3526 if (status != ISC_R_SUCCESS)
3529 if (status != ISC_R_SUCCESS)
3533 if (status != ISC_R_SUCCESS)
3536 if (status != ISC_R_SUCCESS)
3539 (c, (u_int32_t)s -> me.max_response_delay));
3540 if (status != ISC_R_SUCCESS)
3544 if (status != ISC_R_SUCCESS)
3547 if (status != ISC_R_SUCCESS)
3550 (c, (u_int32_t)s -> cur_unacked_updates));
3551 if (status != ISC_R_SUCCESS)
3554 if (h -> inner && h -> inner -> type -> stuff_values)
3555 return (*(h -> inner -> type -> stuff_values)) (c,
id,
3557 return ISC_R_SUCCESS;
3565 isc_result_t status;
3566 dhcp_failover_state_t *s;
3573 if (status == ISC_R_SUCCESS) {
3577 if (status != ISC_R_SUCCESS)
3589 if (status == ISC_R_SUCCESS) {
3591 unsigned l = strlen (s -> name);
3592 if (l == tv -> value -> u.buffer.len &&
3594 tv -> value -> u.buffer.
value, l))
3607 return ISC_R_NOTFOUND;
3618 return ISC_R_SUCCESS;
3624 return ISC_R_NOTIMPLEMENTED;
3630 return ISC_R_NOTIMPLEMENTED;
3634 u_int8_t *addr,
unsigned addrlen)
3639 memset (&ds, 0,
sizeof ds);
3646 state -> partner.address,
MDL)) {
3647 for (i = 0; i + addrlen - 1 < ds.len; i += addrlen) {
3648 if (!memcmp (&ds.data [i],
3661 dhcp_failover_state_t *state;
3662 failover_option_t *name;
3664 if ((strlen(state->name) == name->count) &&
3665 (memcmp(state->name, name->data, name->count) == 0))
3673 static char resbuf[
sizeof(
"Undefined-255: This reason code is not defined " 3674 "in the protocol standard.")];
3676 if ((reason > 0xff) || (reason < 0))
3677 return "Reason code out of range.";
3680 case FTR_ILLEGAL_IP_ADDR:
3681 return "Illegal IP address (not part of any address pool).";
3683 case FTR_FATAL_CONFLICT:
3684 return "Fatal conflict exists: address in use by other client.";
3686 case FTR_MISSING_BINDINFO:
3687 return "Missing binding information.";
3689 case FTR_TIMEMISMATCH:
3690 return "Connection rejected, time mismatch too great.";
3692 case FTR_INVALID_MCLT:
3693 return "Connection rejected, invalid MCLT.";
3695 case FTR_MISC_REJECT:
3696 return "Connection rejected, unknown reason.";
3698 case FTR_DUP_CONNECTION:
3699 return "Connection rejected, duplicate connection.";
3701 case FTR_INVALID_PARTNER:
3702 return "Connection rejected, invalid failover partner.";
3704 case FTR_TLS_UNSUPPORTED:
3705 return "TLS not supported.";
3707 case FTR_TLS_UNCONFIGURED:
3708 return "TLS supported but not configured.";
3710 case FTR_TLS_REQUIRED:
3711 return "TLS required but not supported by partner.";
3713 case FTR_DIGEST_UNSUPPORTED:
3714 return "Message digest not supported.";
3716 case FTR_DIGEST_UNCONFIGURED:
3717 return "Message digest not configured.";
3719 case FTR_VERSION_MISMATCH:
3720 return "Protocol version mismatch.";
3722 case FTR_OUTDATED_BIND_INFO:
3723 return "Outdated binding information.";
3725 case FTR_LESS_CRIT_BIND_INFO:
3726 return "Less critical binding information.";
3728 case FTR_NO_TRAFFIC:
3729 return "No traffic within sufficient time.";
3731 case FTR_HBA_CONFLICT:
3732 return "Hash bucket assignment conflict.";
3734 case FTR_IP_NOT_RESERVED:
3735 return "IP not reserved on this server.";
3737 case FTR_IP_DIGEST_FAILURE:
3738 return "Message digest failed to compare.";
3740 case FTR_IP_MISSING_DIGEST:
3741 return "Missing message digest.";
3744 return "Unknown Error.";
3747 sprintf(resbuf,
"Undefined-%d: This reason code is not defined in the " 3748 "protocol standard.", reason);
3758 return "unknown-state";
3761 return "partner-down";
3767 return "conflict-done";
3770 return "communications-interrupted";
3773 return "resolution-interrupted";
3776 return "potential-conflict";
3782 return "recover-done";
3785 return "recover-wait";
3800 static char messbuf[
sizeof(
"unknown-message-255")];
3803 return "invalid-message";
3807 return "pool-request";
3810 return "pool-response";
3813 return "bind-update";
3821 case FTM_CONNECTACK:
3822 return "connect-ack";
3825 return "update-request";
3828 return "update-done";
3831 return "update-request-all";
3839 case FTM_DISCONNECT:
3840 return "disconnect";
3843 sprintf(messbuf,
"unknown-message-%u", type);
3850 static char optbuf[
sizeof(
"unknown-option-65535")];
3853 return "invalid-option";
3856 case FTO_ADDRESSES_TRANSFERRED:
3857 return "addresses-transferred";
3859 case FTO_ASSIGNED_IP_ADDRESS:
3860 return "assigned-ip-address";
3862 case FTO_BINDING_STATUS:
3863 return "binding-status";
3865 case FTO_CLIENT_IDENTIFIER:
3866 return "client-identifier";
3877 case FTO_DELAYED_SERVICE:
3878 return "delayed-service";
3886 case FTO_LEASE_EXPIRY:
3887 return "lease-expiry";
3889 case FTO_MAX_UNACKED:
3890 return "max-unacked";
3898 case FTO_MESSAGE_DIGEST:
3899 return "message-digest";
3901 case FTO_POTENTIAL_EXPIRY:
3902 return "potential-expiry";
3904 case FTO_PROTOCOL_VERSION:
3905 return "protocol-version";
3907 case FTO_RECEIVE_TIMER:
3908 return "receive-timer";
3910 case FTO_REJECT_REASON:
3911 return "reject-reason";
3913 case FTO_RELATIONSHIP_NAME:
3914 return "relationship-name";
3916 case FTO_REPLY_OPTIONS:
3917 return "reply-options";
3919 case FTO_REQUEST_OPTIONS:
3920 return "request-options";
3922 case FTO_SERVER_FLAGS:
3923 return "server-flags";
3925 case FTO_SERVER_STATE:
3926 return "server-state";
3934 case FTO_TLS_REQUEST:
3935 return "tls-request";
3937 case FTO_VENDOR_CLASS:
3938 return "vendor-class";
3940 case FTO_VENDOR_OPTIONS:
3941 return "vendor-options";
3944 sprintf(optbuf,
"unknown-option-%u", type);
3953 const char *fmt, ...)
3966 if (vsnprintf (tbuf,
sizeof tbuf, fmt, va) >=
sizeof tbuf)
3967 log_fatal (
"%s: vsnprintf would truncate",
3968 "dhcp_failover_make_option");
3972 strlen (tbuf), tbuf);
3976 char *obuf,
unsigned *obufix,
3977 unsigned obufmax, ...)
3980 struct failover_option_info *info;
3982 unsigned size, count;
3988 #if defined (DEBUG_FAILOVER_MESSAGES) 3996 failover_option_t
option, *op;
4000 if (code < 1 || code > FTO_MAX || ft_options [code].type == FT_UNDEF) {
4003 info = &ft_options [code];
4005 va_start (va, obufmax);
4009 if (info -> type == FT_DDNS || info -> type == FT_DDNS1) {
4010 count = info -> type == FT_DDNS ? 1 : 2;
4011 size = va_arg (va,
int) + count;
4014 if (info -> num_present)
4015 count = info -> num_present;
4017 count = va_arg (va,
int);
4020 switch (info -> type) {
4027 case FT_TEXT_OR_BYTES:
4029 txt = va_arg (va,
char *);
4034 ilen = va_arg (va,
unsigned);
4035 size = count * ilen;
4048 log_fatal (
"bogus type in failover_make_option: %d",
4057 option.count = size;
4068 #if defined (DEBUG_FAILOVER_MESSAGES) 4076 if (snprintf (tbuf,
sizeof tbuf,
" (%s<%d>", info -> name,
4077 option.count) >=
sizeof tbuf)
4078 log_fatal (
"dhcp_failover_make_option: tbuf overflow");
4083 switch (info -> type) {
4085 for (i = 0; i < count; i++) {
4086 val = va_arg (va,
unsigned);
4087 #if defined (DEBUG_FAILOVER_MESSAGES) 4089 sprintf (tbuf,
" %d", val);
4092 option.data [i + 4] = val;
4097 for (i = 0; i < count; i++) {
4098 iaddr = va_arg (va, u_int8_t *);
4101 log_error (
"IP addrlen=%d, should be 4.",
4107 #if defined (DEBUG_FAILOVER_MESSAGES) 4109 sprintf (tbuf,
" %u.%u.%u.%u",
4110 iaddr [0], iaddr [1], iaddr [2], iaddr [3]);
4113 memcpy (&option.data [4 + i * ilen], iaddr, ilen);
4118 for (i = 0; i < count; i++) {
4119 val = va_arg (va,
unsigned);
4120 #if defined (DEBUG_FAILOVER_MESSAGES) 4122 sprintf (tbuf,
" %d", val);
4125 putULong (&option.data [4 + i * 4], val);
4131 bval = va_arg (va, u_int8_t *);
4132 #if defined (DEBUG_FAILOVER_MESSAGES) 4133 for (i = 0; i < count; i++) {
4135 sprintf (tbuf,
" %d", bval [i]);
4139 memcpy (&option.data [4], bval, count);
4146 case FT_TEXT_OR_BYTES:
4148 #if defined (DEBUG_FAILOVER_MESSAGES) 4156 if (snprintf (tbuf,
sizeof tbuf,
"\"%s\"", txt) >=
sizeof tbuf)
4157 log_fatal (
"dhcp_failover_make_option: tbuf overflow");
4160 memcpy (&option.data [4], txt, count);
4165 option.data [4] = va_arg (va,
unsigned);
4167 option.data [5] = va_arg (va,
unsigned);
4168 bval = va_arg (va, u_int8_t *);
4169 memcpy (&option.data [4 + count], bval, size - count - 4);
4170 #if defined (DEBUG_FAILOVER_MESSAGES) 4171 for (i = 4; i < size; i++) {
4173 sprintf (tbuf,
" %d", option.data [i]);
4180 for (i = 0; i < count; i++) {
4181 val = va_arg (va, u_int32_t);
4182 #if defined (DEBUG_FAILOVER_MESSAGES) 4184 sprintf (tbuf,
" %d", val);
4187 putUShort (&option.data [4 + i * 2], val);
4196 #if defined DEBUG_FAILOVER_MESSAGES 4202 op =
dmalloc (
sizeof (failover_option_t),
MDL);
4216 int msg_type, u_int32_t xid, ...)
4222 failover_option_t *option;
4223 unsigned char *opbuf;
4224 isc_result_t status = ISC_R_SUCCESS;
4230 va_start (list, xid);
4231 while ((option = va_arg (list, failover_option_t *))) {
4233 size += option -> count;
4240 if (!bad_option && size) {
4243 status = ISC_R_NOMEMORY;
4245 opbuf = (
unsigned char *)0;
4247 va_start (list, xid);
4248 while ((option = va_arg (list, failover_option_t *))) {
4251 if (!bad_option && opbuf)
4252 memcpy (&opbuf [opix],
4253 option -> data, option -> count);
4256 opix += option -> count;
4270 if (status != ISC_R_SUCCESS)
4276 if (status != ISC_R_SUCCESS)
4282 if (status != ISC_R_SUCCESS)
4287 if (status != ISC_R_SUCCESS)
4292 if (status != ISC_R_SUCCESS)
4298 if (status != ISC_R_SUCCESS)
4302 if (link -> state_object &&
4303 link -> state_object -> link_to_peer == link) {
4304 #if defined (DEBUG_FAILOVER_CONTACT_TIMING) 4306 (
int)(link -> state_object ->
4307 partner.max_response_delay) / 3,
4308 "dhcp_failover_send_contact");
4311 (
int)(link -> state_object ->
4312 partner.max_response_delay) / 3;
4316 (
tvref_t)dhcp_failover_state_reference,
4317 (
tvunref_t)dhcp_failover_state_dereference);
4324 log_info (
"dhcp_failover_put_message: something went wrong.");
4331 dhcp_failover_state_t *state = vstate;
4332 dhcp_failover_link_t *link;
4334 #if defined (DEBUG_FAILOVER_TIMING) 4335 log_info (
"dhcp_failover_timeout");
4340 link = state -> link_to_peer;
4346 log_error (
"timeout waiting for failover peer %s", state -> name);
4355 dhcp_failover_state_t *state = vstate;
4356 dhcp_failover_link_t *link;
4357 isc_result_t status;
4359 #if defined(DEBUG_FAILOVER_MESSAGES) && \ 4360 defined(DEBUG_FAILOVER_CONTACT_MESSAGES) 4362 unsigned obufix = 0;
4367 #if defined (DEBUG_FAILOVER_CONTACT_TIMING) 4368 log_info (
"dhcp_failover_send_contact");
4373 link = state -> link_to_peer;
4380 (link, link -> outer,
4381 FTM_CONTACT, link->xid++,
4382 (failover_option_t *)0));
4384 #if defined(DEBUG_FAILOVER_MESSAGES) && \ 4385 defined(DEBUG_FAILOVER_CONTACT_MESSAGES) 4386 if (status != ISC_R_SUCCESS)
4400 dhcp_failover_link_t *link;
4401 isc_result_t status;
4403 #if defined (DEBUG_FAILOVER_MESSAGES) 4405 unsigned obufix = 0;
4407 # define FMA obuf, &obufix, sizeof obuf 4410 # define FMA (char *)0, (unsigned *)0, 0 4415 link = state -> link_to_peer;
4422 (link, link -> outer,
4423 FTM_STATE, link->xid++,
4426 ? state -> saved_state
4427 : state -> me.state)),
4429 (FTO_SERVER_FLAGS, FMA,
4431 ? FTF_SERVER_STARTUP : 0)),
4433 (failover_option_t *)0));
4435 #if defined (DEBUG_FAILOVER_MESSAGES) 4436 if (status != ISC_R_SUCCESS)
4445 return ISC_R_SUCCESS;
4452 dhcp_failover_link_t *link;
4453 dhcp_failover_state_t *state;
4454 isc_result_t status;
4455 #if defined (DEBUG_FAILOVER_MESSAGES) 4457 unsigned obufix = 0;
4459 # define FMA obuf, &obufix, sizeof obuf 4462 # define FMA (char *)0, (unsigned *)0, 0 4467 link = (dhcp_failover_link_t *)l;
4468 state = link -> state_object;
4475 FTM_CONNECT, link->xid++,
4477 strlen(state->name), state->name),
4479 state -> me.max_flying_updates),
4481 state -> me.max_response_delay),
4485 DHCP_FAILOVER_VERSION),
4493 (failover_option_t *)0));
4495 #if defined (DEBUG_FAILOVER_MESSAGES) 4496 if (status != ISC_R_SUCCESS)
4507 dhcp_failover_state_t *state,
4508 int reason,
const char *errmsg)
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;
4531 FTM_CONNECTACK, link->imsg->xid,
4534 strlen(state->name), state->name)
4535 : (link->imsg->options_present & FTB_RELATIONSHIP_NAME)
4537 link->imsg->relationship_name.count,
4538 link->imsg->relationship_name.data)
4539 : &skip_failover_option,
4542 state -> me.max_flying_updates)
4543 : &skip_failover_option,
4546 state -> me.max_response_delay)
4547 : &skip_failover_option,
4551 DHCP_FAILOVER_VERSION),
4552 (link->imsg->options_present & FTB_TLS_REQUEST)
4555 : &skip_failover_option,
4559 : &skip_failover_option,
4562 strlen (errmsg), errmsg)
4563 : &skip_failover_option,
4564 (failover_option_t *)0));
4566 #if defined (DEBUG_FAILOVER_MESSAGES) 4567 if (status != ISC_R_SUCCESS)
4579 const char *message)
4581 dhcp_failover_link_t *link;
4582 isc_result_t status;
4583 #if defined (DEBUG_FAILOVER_MESSAGES) 4585 unsigned obufix = 0;
4587 # define FMA obuf, &obufix, sizeof obuf 4590 # define FMA (char *)0, (unsigned *)0, 0 4595 link = (dhcp_failover_link_t *)l;
4599 if (!message && reason)
4604 FTM_DISCONNECT, link->xid++,
4609 strlen (message), message)
4610 : &skip_failover_option),
4611 (failover_option_t *)0));
4613 #if defined (DEBUG_FAILOVER_MESSAGES) 4614 if (status != ISC_R_SUCCESS)
4627 struct lease *lease)
4629 dhcp_failover_link_t *link;
4630 isc_result_t status;
4633 #if defined (DEBUG_FAILOVER_MESSAGES) 4635 unsigned obufix = 0;
4637 # define FMA obuf, &obufix, sizeof obuf 4640 # define FMA (char *)0, (unsigned *)0, 0 4643 if (!state -> link_to_peer ||
4646 link = (dhcp_failover_link_t *)state -> link_to_peer;
4658 if ((state->i_am == primary) && (transmit_state ==
FTS_FREE))
4660 else if ((state->i_am == secondary) &&
4664 flags |= FTF_IP_FLAG_RESERVE;
4667 flags |= FTF_IP_FLAG_BOOTP;
4707 (link, link -> outer,
4713 lease -> desired_binding_state),
4718 : &skip_failover_option,
4719 lease -> hardware_addr.hlen
4721 lease -> hardware_addr.hlen,
4722 lease -> hardware_addr.hbuf)
4723 : &skip_failover_option,
4730 (lease->
cltt != 0) ?
4732 &skip_failover_option,
4735 &skip_failover_option,
4736 &skip_failover_option,
4737 &skip_failover_option,
4738 &skip_failover_option,
4739 (failover_option_t *)0));
4741 #if defined (DEBUG_FAILOVER_MESSAGES) 4742 if (status != ISC_R_SUCCESS)
4755 failover_message_t *msg,
4756 int reason,
const char *message)
4758 dhcp_failover_link_t *link;
4759 isc_result_t status;
4760 #if defined (DEBUG_FAILOVER_MESSAGES) 4762 unsigned obufix = 0;
4764 # define FMA obuf, &obufix, sizeof obuf 4767 # define FMA (char *)0, (unsigned *)0, 0 4770 if (!state -> link_to_peer ||
4773 link = (dhcp_failover_link_t *)state -> link_to_peer;
4778 if (!message && reason)
4783 (link, link -> outer,
4784 FTM_BNDACK, msg->xid,
4786 sizeof msg -> assigned_addr,
4787 &msg -> assigned_addr),
4788 #ifdef DO_BNDACK_SHOULD_NOT
4790 msg -> binding_status),
4791 (msg -> options_present & FTB_CLIENT_IDENTIFIER)
4793 msg -> client_identifier.count,
4794 msg -> client_identifier.data)
4795 : &skip_failover_option,
4796 (msg -> options_present & FTB_CHADDR)
4798 msg -> chaddr.count,
4800 : &skip_failover_option,
4804 msg -> potential_expiry),
4807 (msg->options_present & FTB_CLTT) ?
4809 &skip_failover_option,
4810 ((msg->options_present & FTB_IP_FLAGS) && msg->ip_flags) ?
4813 : &skip_failover_option,
4817 : &skip_failover_option,
4820 strlen (message), message)
4821 : &skip_failover_option,
4822 #ifdef DO_BNDACK_SHOULD_NOT
4823 &skip_failover_option,
4824 &skip_failover_option,
4825 &skip_failover_option,
4827 (failover_option_t *)0));
4829 #if defined (DEBUG_FAILOVER_MESSAGES) 4830 if (status != ISC_R_SUCCESS)
4842 dhcp_failover_link_t *link;
4843 isc_result_t status;
4844 #if defined (DEBUG_FAILOVER_MESSAGES) 4846 unsigned obufix = 0;
4848 # define FMA obuf, &obufix, sizeof obuf 4851 # define FMA (char *)0, (unsigned *)0, 0 4854 if (!state -> link_to_peer ||
4857 link = (dhcp_failover_link_t *)state -> link_to_peer;
4863 (link, link -> outer,
4864 FTM_POOLREQ, link->xid++,
4865 (failover_option_t *)0));
4867 #if defined (DEBUG_FAILOVER_MESSAGES) 4868 if (status != ISC_R_SUCCESS)
4881 dhcp_failover_link_t *link;
4882 isc_result_t status;
4883 #if defined (DEBUG_FAILOVER_MESSAGES) 4885 unsigned obufix = 0;
4887 # define FMA obuf, &obufix, sizeof obuf 4890 # define FMA (char *)0, (unsigned *)0, 0 4893 if (!state -> link_to_peer ||
4896 link = (dhcp_failover_link_t *)state -> link_to_peer;
4902 (link, link -> outer,
4903 FTM_POOLRESP, link->imsg->xid,
4906 (failover_option_t *)0));
4908 #if defined (DEBUG_FAILOVER_MESSAGES) 4909 if (status != ISC_R_SUCCESS)
4921 dhcp_failover_link_t *link;
4922 isc_result_t status;
4923 #if defined (DEBUG_FAILOVER_MESSAGES) 4925 unsigned obufix = 0;
4927 # define FMA obuf, &obufix, sizeof obuf 4930 # define FMA (char *)0, (unsigned *)0, 0 4933 if (!state->link_to_peer ||
4936 link = (dhcp_failover_link_t *)state->link_to_peer;
4944 if (state->curUPD == FTM_UPDREQALL) {
4949 link->xid++, NULL));
4951 state->curUPD = FTM_UPDREQ;
4953 #if defined (DEBUG_FAILOVER_MESSAGES) 4954 if (status != ISC_R_SUCCESS)
4962 if (status == ISC_R_SUCCESS) {
4963 log_info(
"Sent update request message to %s", state->name);
4965 log_error(
"Failed to send update request all message to %s: %s",
4966 state->name, isc_result_totext(status));
4974 dhcp_failover_link_t *link;
4975 isc_result_t status;
4976 #if defined (DEBUG_FAILOVER_MESSAGES) 4978 unsigned obufix = 0;
4980 # define FMA obuf, &obufix, sizeof obuf 4983 # define FMA (char *)0, (unsigned *)0, 0 4986 if (!state->link_to_peer ||
4989 link = (dhcp_failover_link_t *)state->link_to_peer;
4999 link->xid++, NULL));
5001 state->curUPD = FTM_UPDREQALL;
5003 #if defined (DEBUG_FAILOVER_MESSAGES) 5004 if (status != ISC_R_SUCCESS)
5012 if (status == ISC_R_SUCCESS) {
5013 log_info(
"Sent update request all message to %s", state->name);
5015 log_error(
"Failed to send update request all message to %s: %s",
5016 state->name, isc_result_totext(status));
5023 dhcp_failover_link_t *link;
5024 isc_result_t status;
5025 #if defined (DEBUG_FAILOVER_MESSAGES) 5027 unsigned obufix = 0;
5029 # define FMA obuf, &obufix, sizeof obuf 5032 # define FMA (char *)0, (unsigned *)0, 0 5035 if (!state -> link_to_peer ||
5038 link = (dhcp_failover_link_t *)state -> link_to_peer;
5044 (link, link -> outer,
5045 FTM_UPDDONE, state->updxid,
5046 (failover_option_t *)0));
5048 #if defined (DEBUG_FAILOVER_MESSAGES) 5049 if (status != ISC_R_SUCCESS)
5057 log_info (
"Sent update done message to %s", state -> name);
5081 static isc_boolean_t
5082 failover_lease_is_better(dhcp_failover_state_t *state,
struct lease *lease,
5083 failover_message_t *msg)
5093 if ((msg->options_present & FTB_CLTT) != 0)
5094 msg_cltt = msg->cltt;
5098 switch(local_state) {
5101 if (msg_cltt < lease->cltt)
5103 else if (msg_cltt > lease->
cltt)
5105 else if (state->i_am == primary)
5122 else if (state->i_am == primary)
5138 failover_message_t *msg)
5140 struct lease *lt = NULL, *lease = NULL;
5142 int reason = FTR_MISC_REJECT;
5143 const char *message;
5144 int new_binding_state;
5145 int send_to_backup = 0;
5146 int required_options;
5147 isc_boolean_t chaddr_changed = ISC_FALSE;
5148 isc_boolean_t ident_changed = ISC_FALSE;
5151 required_options = FTB_ASSIGNED_IP_ADDRESS | FTB_BINDING_STATUS;
5152 if ((msg->options_present & required_options) != required_options) {
5153 message =
"binding update lacks required options";
5154 reason = FTR_MISSING_BINDINFO;
5158 ia.len =
sizeof msg -> assigned_addr;
5159 memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
5162 message =
"unknown IP address";
5163 reason = FTR_ILLEGAL_IP_ADDR;
5171 if ((lease->pool == NULL) || (lease->pool->failover_peer == NULL) ||
5172 (lease->pool->failover_peer != state)) {
5173 message =
"IP address is covered by a different failover " 5174 "relationship state";
5175 reason = FTR_ILLEGAL_IP_ADDR;
5189 if ((lease->flags & ON_ACK_QUEUE) != 0) {
5190 if (failover_lease_is_better(state, lease, msg)) {
5191 message =
"incoming update is less critical than " 5193 reason = FTR_LESS_CRIT_BIND_INFO;
5203 message =
"no memory";
5207 if (msg -> options_present & FTB_CHADDR) {
5209 message =
"BNDUPD to ABANDONED with a CHADDR";
5212 if (msg -> chaddr.count >
sizeof lt -> hardware_addr.hbuf) {
5213 message =
"chaddr too long";
5219 msg->chaddr.count) != 0))
5220 chaddr_changed = ISC_TRUE;
5222 lt -> hardware_addr.hlen = msg -> chaddr.count;
5223 memcpy (lt -> hardware_addr.hbuf, msg -> chaddr.data,
5224 msg -> chaddr.count);
5225 }
else if (msg->binding_status ==
FTS_ACTIVE ||
5228 message =
"BNDUPD without CHADDR";
5229 reason = FTR_MISSING_BINDINFO;
5232 chaddr_changed = ISC_TRUE;
5242 if (msg->options_present & FTB_CLIENT_IDENTIFIER) {
5244 message =
"BNDUPD to ABANDONED with client-id";
5248 if ((lt->
uid_len != msg->client_identifier.count) ||
5249 (lt->
uid == NULL) ||
5250 (memcmp(lt->
uid, msg->client_identifier.data,
5252 ident_changed = ISC_TRUE;
5254 lt->
uid_len = msg->client_identifier.count;
5269 message =
"no memory";
5278 msg -> client_identifier.data, lt -> uid_len);
5279 }
else if (lt->
uid && msg->binding_status !=
FTS_RESET &&
5282 ident_changed = ISC_TRUE;
5315 (chaddr_changed || ident_changed)) {
5316 #if defined (NSUPDATE) 5320 if (lease->scope != NULL)
5325 if (msg -> options_present & FTB_STOS) {
5326 lt -> starts = msg -> stos;
5328 if (msg -> options_present & FTB_LEASE_EXPIRY) {
5329 lt -> ends = msg -> expiry;
5331 if (msg->options_present & FTB_POTENTIAL_EXPIRY) {
5332 lt->
atsfp = lt->
tsfp = msg->potential_expiry;
5334 if (msg->options_present & FTB_IP_FLAGS) {
5335 if (msg->ip_flags & FTF_IP_FLAG_RESERVE) {
5336 if ((((state->i_am == primary) &&
5337 (lease->binding_state ==
FTS_FREE)) ||
5338 ((state->i_am == secondary) &&
5341 message =
"Address is not reserved.";
5342 reason = FTR_IP_NOT_RESERVED;
5350 if (msg->ip_flags & FTF_IP_FLAG_BOOTP) {
5351 if ((((state->i_am == primary) &&
5352 (lease->binding_state ==
FTS_FREE)) ||
5353 ((state->i_am == secondary) &&
5356 message =
"Address is not allocated to BOOTP.";
5363 if (msg->ip_flags & ~(FTF_IP_FLAG_RESERVE | FTF_IP_FLAG_BOOTP))
5364 log_info(
"Unknown IP-flags set in BNDUPD (0x%x).",
5369 #if defined (DEBUG_LEASE_STATE_TRANSITIONS) 5370 log_info (
"processing state transition for %s: %s to %s",
5378 if (state -> me.state ==
normal) {
5381 (lease, state, msg -> binding_status,
5382 msg -> potential_expiry));
5389 (lease, state, msg -> binding_status,
5390 msg -> potential_expiry));
5392 if (new_binding_state != msg -> binding_status) {
5395 if (snprintf (outbuf,
sizeof outbuf,
5396 "%s: invalid state transition: %s to %s",
5401 log_fatal (
"%s: impossible outbuf overflow",
5402 "dhcp_failover_process_bind_update");
5412 lt -> next_binding_state =
FTS_FREE;
5419 if ((state->i_am == primary) &&
5423 lt -> next_binding_state = new_binding_state;
5425 msg -> binding_status = lt -> next_binding_state;
5436 message =
"database update failed";
5447 if (send_to_backup && secondary_not_hoarding(state, lease->pool)) {
5454 log_error(
"can't commit lease %s for mac addr " 5455 "affinity",
piaddr(lease->ip_addr));
5462 lease_dereference (<,
MDL);
5464 lease_dereference (&lease,
MDL);
5466 return ISC_R_SUCCESS;
5475 secondary_not_hoarding(dhcp_failover_state_t *state,
struct pool *p) {
5483 hold = ((total * state->max_lease_ownership) + 50) / 100;
5494 return(lts > -hold);
5498 failover_message_t *msg)
5500 struct lease *lease = NULL;
5502 const char *message =
"no memory";
5503 u_int32_t pot_expire;
5504 int send_to_backup = ISC_FALSE;
5507 ia.len =
sizeof msg -> assigned_addr;
5508 memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
5511 message =
"no such lease";
5516 if (msg -> options_present & FTB_REJECT_REASON) {
5517 log_error (
"bind update on %s from %s rejected: %.*s",
5518 piaddr (ia), state -> name,
5519 (
int)((msg -> options_present & FTB_MESSAGE)
5520 ? msg -> message.count
5522 (msg -> reject_reason))),
5523 (msg -> options_present & FTB_MESSAGE)
5524 ? (
const char *)(msg -> message.data)
5526 (msg -> reject_reason)));
5537 message =
"xid mismatch";
5542 if (msg->options_present & FTO_POTENTIAL_EXPIRY)
5543 pot_expire = msg->potential_expiry;
5545 pot_expire = lease->
tstp;
5565 lease->
atsfp = lease->
tsfp = pot_expire;
5566 if ((state->i_am == secondary) &&
5588 if (state->i_am == primary &&
5591 send_to_backup = ISC_TRUE;
5593 if (!send_to_backup && state->me.state ==
normal)
5599 lease->
atsfp = lease->
tsfp = pot_expire;
5621 if (state -> send_update_done == lease) {
5622 lease_dereference (&state -> send_update_done,
MDL);
5629 if (send_to_backup && secondary_not_hoarding(state, lease->
pool)) {
5638 if (state->me.state ==
normal)
5647 lease_dereference (&lease,
MDL);
5648 return ISC_R_SUCCESS;
5651 log_info (
"bind update on %s got ack from %s: %s.",
5652 piaddr (ia), state -> name, message);
5663 #define FREE_LEASES 0 5664 #define ACTIVE_LEASES 1 5665 #define EXPIRED_LEASES 2 5666 #define ABANDONED_LEASES 3 5667 #define BACKUP_LEASES 4 5668 #define RESERVED_LEASES 5 5674 for (p = s ->
pools; p; p = p ->
next) {
5700 return ISC_R_SUCCESS;
5705 failover_message_t *msg)
5707 if (state->send_update_done) {
5708 log_info(
"Received update request while old update still " 5709 "flying! Silently discarding old request.");
5710 lease_dereference(&state->send_update_done,
MDL);
5716 state->updxid = msg->xid;
5721 if (state -> update_queue_tail) {
5722 lease_reference (&state -> send_update_done,
5723 state -> update_queue_tail,
MDL);
5725 log_info (
"Update request from %s: sending update",
5731 log_info (
"Update request from %s: nothing pending",
5735 return ISC_R_SUCCESS;
5740 failover_message_t *msg)
5742 if (state->send_update_done) {
5743 log_info(
"Received update request while old update still " 5744 "flying! Silently discarding old request.");
5745 lease_dereference(&state->send_update_done,
MDL);
5751 state->updxid = msg->xid;
5753 if (state -> update_queue_tail) {
5754 lease_reference (&state -> send_update_done,
5755 state -> update_queue_tail,
MDL);
5757 log_info (
"Update request all from %s: sending update",
5763 log_info (
"Update request all from %s: nothing pending",
5767 return ISC_R_SUCCESS;
5772 failover_message_t *msg)
5776 log_info (
"failover peer %s: peer update completed.",
5779 state -> curUPD = 0;
5781 switch (state -> me.state) {
5797 if (state->i_am == secondary) {
5800 log_error(
"Secondary is in conflict_done " 5801 "state after conflict resolution, " 5802 "this is illegal.");
5806 if (state->i_am == primary)
5809 log_error(
"Spurious update-done message.");
5815 log_error(
"Spurious update-done message.");
5824 if (state -> me.stos + state -> mclt >
cur_time &&
5825 state -> partner.state !=
recover &&
5828 #if defined (DEBUG_FAILOVER_TIMING) 5831 state -> me.stos + state -> mclt),
5832 "dhcp_failover_recover_done");
5834 tv . tv_sec = (
int)(state -> me.stos + state -> mclt);
5839 (
tvref_t)omapi_object_reference,
5846 return ISC_R_SUCCESS;
5851 dhcp_failover_state_t *state = sp;
5853 #if defined (DEBUG_FAILOVER_TIMING) 5854 log_info (
"dhcp_failover_recover_done");
5860 #if defined (DEBUG_FAILOVER_MESSAGES) 5867 unsigned *obufix,
unsigned obufmax,
const char *s)
5869 int len = strlen (s);
5871 while (len + *obufix + 1 >= obufmax) {
5880 strcpy (&obuf [*obufix], s);
5887 unsigned char loadb_mx_tbl[256] = {
5888 251, 175, 119, 215, 81, 14, 79, 191, 103, 49,
5889 181, 143, 186, 157, 0, 232, 31, 32, 55, 60,
5890 152, 58, 17, 237, 174, 70, 160, 144, 220, 90,
5891 57, 223, 59, 3, 18, 140, 111, 166, 203, 196,
5892 134, 243, 124, 95, 222, 179, 197, 65, 180, 48,
5893 36, 15, 107, 46, 233, 130, 165, 30, 123, 161,
5894 209, 23, 97, 16, 40, 91, 219, 61, 100, 10,
5895 210, 109, 250, 127, 22, 138, 29, 108, 244, 67,
5896 207, 9, 178, 204, 74, 98, 126, 249, 167, 116,
5897 34, 77, 193, 200, 121, 5, 20, 113, 71, 35,
5898 128, 13, 182, 94, 25, 226, 227, 199, 75, 27,
5899 41, 245, 230, 224, 43, 225, 177, 26, 155, 150,
5900 212, 142, 218, 115, 241, 73, 88, 105, 39, 114,
5901 62, 255, 192, 201, 145, 214, 168, 158, 221, 148,
5902 154, 122, 12, 84, 82, 163, 44, 139, 228, 236,
5903 205, 242, 217, 11, 187, 146, 159, 64, 86, 239,
5904 195, 42, 106, 198, 118, 112, 184, 172, 87, 2,
5905 173, 117, 176, 229, 247, 253, 137, 185, 99, 164,
5906 102, 147, 45, 66, 231, 52, 141, 211, 194, 206,
5907 246, 238, 56, 110, 78, 248, 63, 240, 189, 93,
5908 92, 51, 53, 183, 19, 171, 72, 50, 33, 104,
5909 101, 69, 8, 252, 83, 120, 76, 135, 85, 54,
5910 202, 125, 188, 213, 96, 235, 136, 208, 162, 129,
5911 190, 132, 156, 38, 47, 1, 7, 254, 24, 4,
5912 216, 131, 89, 21, 28, 133, 37, 153, 149, 80,
5913 170, 68, 6, 169, 234, 151 };
5915 static unsigned char loadb_p_hash (
const unsigned char *,
unsigned);
5916 static unsigned char loadb_p_hash (
const unsigned char *key,
unsigned len)
5918 unsigned char hash = len;
5920 for(i = len; i > 0; )
5921 hash = loadb_mx_tbl [hash ^ (key [--i])];
5929 unsigned char hbaix;
5933 ec = ntohs(packet->
raw->
secs);
5935 #if defined(SECS_BYTEORDER) 5942 if ((ec > 255) && ((ec & 0xff) == 0)) {
5943 ec = (ec >> 8) | (ec << 8);
5947 if (state->load_balance_max_secs < ec) {
5961 memset(&ds, 0,
sizeof ds);
5966 hbaix = loadb_p_hash(ds.data, ds.len);
5970 hbaix = loadb_p_hash(packet->
raw->
chaddr,
5974 hm = state->hba[(hbaix >> 3) & 0x1F] & (1 << (hbaix & 0x07));
5976 if (state->i_am == primary)
5990 dhcp_failover_state_t *state;
5991 unsigned char hbaix;
5999 if (!state || !state->hba)
6016 hm = state->hba[(hbaix >> 3) & 0x1F] & (1 << (hbaix & 0x07));
6018 if (state->i_am == primary)
6032 dhcp_failover_state_t *state,
6039 if (binding_state == lease -> binding_state)
6040 return binding_state;
6042 switch (lease -> binding_state) {
6045 switch (binding_state) {
6056 if (state -> i_am == secondary)
6057 return binding_state;
6065 new_state = binding_state;
6075 if (state -> i_am == primary) {
6081 return binding_state;
6083 new_state = lease -> binding_state;
6088 switch (binding_state) {
6094 new_state = lease -> binding_state;
6097 return binding_state;
6105 if (lease -> ends - 65 >
cur_time) {
6106 new_state = lease -> binding_state;
6114 return binding_state;
6122 switch (binding_state) {
6128 new_state = lease -> binding_state;
6131 return binding_state;
6138 return binding_state;
6145 switch (binding_state) {
6156 return binding_state;
6163 switch (binding_state) {
6169 new_state = lease -> binding_state;
6172 return binding_state;
6179 return binding_state;
6186 switch (binding_state) {
6195 if (state -> i_am == primary)
6196 return binding_state;
6202 return binding_state;
6205 new_state = lease -> binding_state;
6225 dhcp_failover_state_t *state,
6232 if (binding_state == lease -> binding_state)
6233 new_state = binding_state;
6235 switch (lease -> binding_state) {
6245 new_state = binding_state;
6252 switch (binding_state) {
6255 new_state = lease -> binding_state;
6267 new_state = binding_state;
6278 new_state = binding_state;
6313 dhcp_failover_state_t *peer;
6315 if (lease && lease->
pool &&
6339 if (peer -> i_am == primary)
6343 ((lease->
tsfp < peer->me.stos) ?
6344 (peer->me.stos + peer->mclt <
cur_time) :
6363 if ((peer->i_am == primary) &&
6366 if ((peer->i_am == secondary) &&
6397 if (peer->i_am == secondary)
6401 ((lease->
tsfp < peer->me.stos) ?
6402 (peer->me.stos + peer->mclt <
cur_time) :
6419 static isc_result_t failover_message_reference (failover_message_t **mp,
6420 failover_message_t *m,
6421 const char *file,
int line)
6425 return ISC_R_SUCCESS;
6428 static isc_result_t failover_message_dereference (failover_message_t **mp,
6429 const char *file,
int line)
6431 failover_message_t *m;
6434 if (m -> refcnt == 0) {
6436 failover_message_dereference (&m -> next,
6438 if (m -> chaddr.data)
6439 dfree (m -> chaddr.data, file, line);
6440 if (m -> client_identifier.data)
6441 dfree (m -> client_identifier.data, file, line);
6443 dfree (m -> hba.data, file, line);
6444 if (m -> message.data)
6445 dfree (m -> message.data, file, line);
6446 if (m -> relationship_name.data)
6447 dfree (m -> relationship_name.data, file, line);
6448 if (m -> reply_options.data)
6449 dfree (m -> reply_options.data, file, line);
6450 if (m -> request_options.data)
6451 dfree (m -> request_options.data, file, line);
6452 if (m -> vendor_class.data)
6453 dfree (m -> vendor_class.data, file, line);
6454 if (m -> vendor_options.data)
6455 dfree (m -> vendor_options.data, file, line);
6458 dfree (*mp, file, line);
6461 return ISC_R_SUCCESS;
isc_result_t dhcp_failover_state_signal(omapi_object_t *, const char *, va_list)
int supersede_lease(struct lease *, struct lease *, int, int, int, int)
isc_result_t dhcp_failover_send_poolreq(dhcp_failover_state_t *)
isc_result_t dhcp_failover_state_stuff(omapi_object_t *, omapi_object_t *, omapi_object_t *)
isc_result_t dhcp_failover_send_connectack(omapi_object_t *, dhcp_failover_state_t *, int, const char *)
isc_result_t dhcp_failover_link_get_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **)
struct binding_scope * global_scope
int write_failover_state(dhcp_failover_state_t *)
isc_result_t dhcp_failover_listener_set_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *)
int dhcp_failover_state_match_by_name(dhcp_failover_state_t *, failover_option_t *)
failover_option_t failover_option_t * dhcp_failover_make_option(unsigned, char *, unsigned *, unsigned,...)
omapi_object_type_t * omapi_type_connection
isc_result_t dhcp_failover_send_connect(omapi_object_t *)
isc_result_t omapi_make_int_value(omapi_value_t **, omapi_data_string_t *, int, const char *, int)
isc_result_t omapi_object_reference(omapi_object_t **, omapi_object_t *, const char *, int)
const char * piaddr(const struct iaddr addr)
omapi_object_type_t * dhcp_type_failover_link
#define DHCP_R_PROTOCOLERROR
struct shared_network * shared_networks
#define DHO_PXE_CLIENT_ID
void * dmalloc(unsigned, const char *, int)
struct lease_state * state
int option_cache_dereference(struct option_cache **ptr, const char *file, int line)
isc_result_t omapi_connection_copyin(omapi_object_t *, const unsigned char *, unsigned)
void dhcp_failover_pool_check(struct pool *)
struct iaddr ip_addr(struct iaddr subnet, struct iaddr mask, u_int32_t host_address)
void cancel_timeout(void(*)(void *) where, void *what)
isc_result_t dhcp_failover_register(omapi_object_t *)
isc_result_t dhcp_failover_link_initiate(omapi_object_t *)
#define DHCP_R_INVALIDARG
omapi_typed_data_t * value
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
struct lease * next_pending
isc_result_t dhcp_failover_state_create(omapi_object_t **, omapi_object_t *)
isc_result_t omapi_signal_in(omapi_object_t *, const char *,...)
isc_result_t dhcp_failover_listener_stuff(omapi_object_t *, omapi_object_t *, omapi_object_t *)
struct universe dhcp_universe
void dhcp_failover_keepalive(void *)
void data_string_forget(struct data_string *data, const char *file, int line)
isc_result_t dhcp_failover_send_update_request(dhcp_failover_state_t *)
omapi_object_type_t * dhcp_type_failover_state
int option_cache_reference(struct option_cache **ptr, struct option_cache *src, const char *file, int line)
const char * dhcp_failover_option_name(unsigned)
int log_error(const char *,...) __attribute__((__format__(__printf__
int binding_scope_dereference(struct binding_scope **ptr, const char *file, int line)
failover_option_t * dhcp_failover_option_printf(unsigned, char *, unsigned *, unsigned, const char *,...) __attribute__((__format__(__printf__
void add_timeout(struct timeval *when, void(*)(void *) where, void *what, tvref_t ref, tvunref_t unref)
void(* tvunref_t)(void *, const char *, int)
dhcp_failover_state_t * failover_peer
#define OMAPI_OBJECT_ALLOC(name, stype, type)
void dhcp_failover_recover_done(void *)
failover_option_t null_failover_option
isc_result_t omapi_listen_addr(omapi_object_t *, omapi_addr_t *, int)
#define DHCP_R_KEYCONFLICT
void(* tvref_t)(void *, void *, const char *, int)
const char * binding_state_print(enum failover_state state)
struct option_state * options
isc_result_t dhcp_failover_send_bind_ack(dhcp_failover_state_t *, failover_message_t *, int, const char *)
void log_fatal(const char *,...) __attribute__((__format__(__printf__
isc_result_t dhcp_failover_send_poolresp(dhcp_failover_state_t *, int)
const char * dhcp_flink_state_names[]
isc_result_t dhcp_failover_link_destroy(omapi_object_t *, const char *, int)
const char * dhcp_failover_message_name(unsigned)
isc_result_t dhcp_failover_state_transition(dhcp_failover_state_t *, const char *)
isc_result_t dhcp_failover_state_destroy(omapi_object_t *, const char *, int)
struct hardware hardware_addr
isc_result_t omapi_connection_put_uint32(omapi_object_t *, u_int32_t)
omapi_object_type_t * omapi_type_protocol
omapi_object_type_t * dhcp_type_failover_listener
failover_option_t skip_failover_option
isc_result_t omapi_make_uint_value(omapi_value_t **, omapi_data_string_t *, unsigned int, const char *, int)
isc_result_t dhcp_failover_listen(omapi_object_t *)
isc_result_t dhcp_failover_state_remove(omapi_object_t *, omapi_object_t *)
int evaluate_option_cache(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
isc_result_t dhcp_failover_set_state(dhcp_failover_state_t *, enum failover_state)
isc_result_t omapi_get_value_str(omapi_object_t *, omapi_object_t *, const char *, omapi_value_t **)
isc_result_t omapi_connection_require(omapi_object_t *, unsigned)
isc_result_t dhcp_failover_process_bind_ack(dhcp_failover_state_t *, failover_message_t *)
isc_result_t dhcp_failover_state_set_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *)
void dhcp_failover_pool_rebalance(void *)
isc_result_t dhcp_failover_generate_update_queue(dhcp_failover_state_t *, int)
binding_state_t binding_state
isc_result_t dhcp_failover_put_message(dhcp_failover_link_t *, omapi_object_t *, int, u_int32_t,...)
isc_result_t dhcp_failover_state_get_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **)
void dhcp_failover_rescind_updates(dhcp_failover_state_t *)
void dhcp_failover_listener_restart(void *)
isc_result_t dhcp_failover_process_update_request_all(dhcp_failover_state_t *, failover_message_t *)
isc_result_t dhcp_failover_send_disconnect(omapi_object_t *, int, const char *)
isc_result_t dhcp_failover_peer_state_changed(dhcp_failover_state_t *, failover_message_t *)
int write_lease(struct lease *lease)
void putULong(unsigned char *, u_int32_t)
isc_result_t dhcp_failover_process_update_request(dhcp_failover_state_t *, failover_message_t *)
isc_result_t omapi_object_dereference(omapi_object_t **, const char *, int)
void commit_leases_timeout(void *)
isc_result_t omapi_signal(omapi_object_t *, const char *,...)
int dhcp_failover_queue_ack(dhcp_failover_state_t *, failover_message_t *msg)
isc_result_t dhcp_failover_link_signal(omapi_object_t *, const char *, va_list)
const char * dhcp_failover_state_name_print(enum failover_state)
isc_result_t omapi_get_int_value(unsigned long *, omapi_typed_data_t *)
binding_state_t normal_binding_state_transition_check(struct lease *, dhcp_failover_state_t *, binding_state_t, u_int32_t)
void dfree(void *, const char *, int)
isc_result_t dhcp_failover_link_stuff_values(omapi_object_t *, omapi_object_t *, omapi_object_t *)
isc_result_t omapi_handle_td_lookup(omapi_object_t **, omapi_typed_data_t *)
dhcp_failover_state_t * failover_states
int load_balance_mine(struct packet *, dhcp_failover_state_t *)
isc_result_t omapi_connection_get_uint32(omapi_object_t *, u_int32_t *)
isc_result_t omapi_addr_list_dereference(omapi_addr_list_t **, const char *, int)
void dhcp_failover_link_startup_timeout(void *)
struct option_cache * lookup_option(struct universe *universe, struct option_state *options, unsigned code)
int int log_info(const char *,...) __attribute__((__format__(__printf__
isc_result_t find_failover_peer(dhcp_failover_state_t **, const char *, const char *, int)
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)
#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)
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)