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;
1990 log_info (
"failover peer %s: peer moves from %s to %s",
1996 if ((state->me.state ==
normal) && (state->partner.state ==
normal))
1997 log_info(
"failover peer %s: Both servers normal", state->name);
2003 log_error (
"Unable to record current failover state for %s",
2010 switch (new_state) {
2027 log_error(
"failover peer %s: Invalid state: %d", state->name,
2030 return ISC_R_SUCCESS;
2036 switch (state -> me.state ==
startup ?
2037 state -> saved_state : state -> me.state) {
2039 switch (new_state) {
2045 if (state -> me.state ==
startup)
2056 log_error(
"Peer %s: Invalid state transition %s "
2057 "to %s.", state->name,
2082 switch (new_state) {
2084 log_info (
"failover peer %s: requesting %s",
2085 state -> name,
"full update from peer");
2089 if (state -> me.state ==
recover)
2115 if (state -> me.state ==
recover)
2136 switch (new_state) {
2139 log_error(
"Peer %s moves to normal during conflict "
2140 "resolution - panic, shutting down.",
2149 log_error(
"Peer %s: Unexpected move to "
2150 "conflict-done.", state->name);
2177 switch (new_state) {
2184 log_fatal(
"Peer %s: Invalid attempt to move from %s "
2185 "to %s while local state is conflict-done.",
2197 switch (new_state) {
2223 switch (new_state) {
2263 switch (new_state) {
2291 switch (new_state) {
2293 log_error(
"Both servers have entered recover-done!");
2332 if (state -> me.state ==
startup && state -> saved_state !=
startup)
2339 return ISC_R_SUCCESS;
2348 dhcp_failover_pool_balance(dhcp_failover_state_t *state)
2352 state->sched_balance = 0;
2354 dhcp_failover_pool_dobalance(state, NULL);
2365 dhcp_failover_state_t *
state;
2366 isc_boolean_t sendreq = ISC_FALSE;
2368 state = (dhcp_failover_state_t *)failover_state;
2371 state->sched_balance = 0;
2373 if (dhcp_failover_pool_dobalance(state, &sendreq))
2385 dhcp_failover_pool_reqbalance(dhcp_failover_state_t *state)
2391 state->sched_balance = 0;
2393 queued = dhcp_failover_pool_dobalance(state, NULL);
2400 log_info(
"peer %s: Got POOLREQ, answering negatively! "
2401 "Peer may be out of leases or database inconsistent.",
2413 dhcp_failover_pool_dobalance(dhcp_failover_state_t *state,
2414 isc_boolean_t *sendreq)
2416 int lts, total, thresh, hold, panic, pass;
2417 int leases_queued = 0;
2426 int (*log_func)(
const char *, ...);
2427 const char *result, *reqlog;
2429 if (state -> me.state !=
normal)
2461 thresh = ((total * state->max_lease_misbalance) + 50) / 100;
2462 hold = ((total * state->max_lease_ownership) + 50) / 100;
2477 panic = thresh * -2;
2482 if ((sendreq != NULL) && (lts < panic)) {
2483 reqlog =
" (requesting peer rebalance!)";
2484 *sendreq = ISC_TRUE;
2488 log_info(
"balancing pool %lx %s total %d free %d "
2489 "backup %d lts %d max-own (+/-)%d%s",
2491 (p->shared_network ?
2493 p->free_leases, p->backup_leases, lts, hold,
2509 lease_reference(&lp, *lq,
MDL);
2513 lease_dereference(&next,
MDL);
2515 lease_reference(&next, lp->
next,
MDL);
2542 }
else if (lts <= -hold)
2558 lease_dereference(&lp,
MDL);
2560 lease_reference(&lp, next,
MDL);
2563 lease_reference(&lp, *lq,
MDL);
2568 lease_dereference(&next,
MDL);
2570 lease_dereference(&lp,
MDL);
2573 result =
"IMBALANCED";
2576 result =
"balanced";
2580 log_func(
"%s pool %lx %s total %d free %d backup %d "
2581 "lts %d max-misbal %d", result, (
unsigned long)p,
2582 (p->shared_network ?
2583 p->shared_network->name :
""), p->lease_count,
2584 p->free_leases, p->backup_leases, lts, thresh);
2596 return leases_queued;
2606 dhcp_failover_state_t *peer;
2612 if(!peer || peer->me.state !=
normal)
2639 est1 = ((est1 * peer->max_lease_misbalance) + 50) / 100;
2640 est2 = ((est2 * peer->max_lease_misbalance) + 50) / 100;
2645 if(peer->i_am == primary)
2655 if(est1 > peer->max_balance)
2656 est1 = peer->max_balance;
2662 est2 = peer->last_balance + peer->min_balance;
2663 if(peer->last_balance && (est1 < est2))
2667 est1 += random() % 5;
2670 if(peer->sched_balance) {
2671 if (est1 >= peer->sched_balance)
2681 peer->sched_balance = est1;
2683 #if defined(DEBUG_FAILOVER_TIMING)
2684 log_info(
"add_timeout +%d dhcp_failover_pool_rebalance",
2690 (
tvref_t)dhcp_failover_state_reference,
2691 (
tvunref_t)dhcp_failover_state_dereference);
2700 for (p = s ->
pools; p; p = p ->
next) {
2712 isc_result_t status;
2715 if (!state -> link_to_peer)
2716 return ISC_R_SUCCESS;
2721 if (state->toack_queue_head != NULL)
2724 while ((state -> partner.max_flying_updates >
2725 state -> cur_unacked_updates) && state -> update_queue_head) {
2727 lease_reference (&lp, state -> update_queue_head,
MDL);
2731 if (status != ISC_R_SUCCESS) {
2732 lease_dereference (&lp,
MDL);
2739 lease_dereference (&state -> update_queue_head,
MDL);
2741 lease_reference (&state -> update_queue_head,
2745 lease_dereference (&state -> update_queue_tail,
MDL);
2748 if (state -> ack_queue_head) {
2752 lease_dereference (&state -> ack_queue_tail,
MDL);
2754 lease_reference (&state -> ack_queue_head, lp,
MDL);
2756 #if defined (POINTER_DEBUG)
2758 log_error (
"ack_queue_tail: lp -> next_pending");
2762 lease_reference (&state -> ack_queue_tail, lp,
MDL);
2764 lease_dereference (&lp,
MDL);
2767 state -> cur_unacked_updates++;
2769 return ISC_R_SUCCESS;
2778 dhcp_failover_state_t *
state;
2780 if (!lease -> pool ||
2781 !lease -> pool -> failover_peer)
2789 state = lease -> pool -> failover_peer;
2795 if (state -> update_queue_head) {
2796 lease_reference (&state -> update_queue_tail ->
next_pending,
2798 lease_dereference (&state -> update_queue_tail,
MDL);
2800 lease_reference (&state -> update_queue_head, lease,
MDL);
2802 #if defined (POINTER_DEBUG)
2804 log_error (
"next pending on update queue lease.");
2805 #if defined (DEBUG_RC_HISTORY)
2806 dump_rc_history (lease);
2811 lease_reference (&state -> update_queue_tail, lease,
MDL);
2820 failover_message_t *msg = (failover_message_t *)0;
2826 while (state -> toack_queue_head) {
2827 failover_message_reference
2828 (&msg, state -> toack_queue_head,
MDL);
2829 failover_message_dereference
2830 (&state -> toack_queue_head,
MDL);
2832 failover_message_reference
2833 (&state -> toack_queue_head, msg -> next,
MDL);
2838 failover_message_dereference (&msg,
MDL);
2841 if (state -> toack_queue_tail)
2842 failover_message_dereference (&state -> toack_queue_tail,
MDL);
2843 state -> pending_acks = 0;
2850 dhcp_failover_state_t *state = vs;
2852 #if defined (DEBUG_FAILOVER_TIMING)
2853 log_info (
"dhcp_failover_toack_queue_timeout");
2863 failover_message_t *msg)
2867 if (state -> toack_queue_head) {
2868 failover_message_reference
2869 (&state -> toack_queue_tail -> next, msg,
MDL);
2870 failover_message_dereference (&state -> toack_queue_tail,
MDL);
2872 failover_message_reference (&state -> toack_queue_head,
2875 failover_message_reference (&state -> toack_queue_tail, msg,
MDL);
2877 state -> pending_acks++;
2881 if (state -> pending_acks >= state -> partner.max_flying_updates / 2) {
2886 if (state -> pending_acks > 0) {
2887 #if defined (DEBUG_FAILOVER_TIMING)
2889 "dhcp_failover_toack_queue_timeout");
2895 (
tvref_t)dhcp_failover_state_reference,
2896 (
tvunref_t)dhcp_failover_state_dereference);
2903 struct lease *lease)
2907 if (!(lease ->
flags & ON_ACK_QUEUE))
2910 if (state -> ack_queue_head == lease) {
2911 lease_dereference (&state -> ack_queue_head,
MDL);
2913 lease_reference (&state -> ack_queue_head,
2917 lease_dereference (&state -> ack_queue_tail,
MDL);
2920 for (lp = state -> ack_queue_head;
2934 lease_dereference (&state -> ack_queue_tail,
MDL);
2939 lease_reference (&state -> ack_queue_tail, lp,
MDL);
2943 lease ->
flags &= ~ON_ACK_QUEUE;
2950 state -> cur_unacked_updates--;
2957 if (state -> cur_unacked_updates == 0) {
2967 isc_result_t status;
2977 return ISC_R_SUCCESS;
2979 return ISC_R_SUCCESS;
2981 return ISC_R_SUCCESS;
2983 return ISC_R_SUCCESS;
2985 return ISC_R_SUCCESS;
2987 return ISC_R_SUCCESS;
2989 return ISC_R_SUCCESS;
2991 return ISC_R_SUCCESS;
2993 return ISC_R_SUCCESS;
2995 return ISC_R_SUCCESS;
2999 if (status != ISC_R_SUCCESS)
3003 return ISC_R_SUCCESS;
3005 return ISC_R_SUCCESS;
3007 return ISC_R_SUCCESS;
3009 return ISC_R_SUCCESS;
3011 return ISC_R_SUCCESS;
3013 return ISC_R_SUCCESS;
3015 return ISC_R_SUCCESS;
3017 return ISC_R_SUCCESS;
3020 if (h -> inner && h -> inner -> type -> set_value)
3021 return (*(h -> inner -> type -> set_value))
3022 (h -> inner, id, name, value);
3023 return ISC_R_NOTFOUND;
3032 dhcp_failover_state_t *state = vs;
3033 isc_result_t status;
3036 #if defined (DEBUG_FAILOVER_TIMING)
3037 log_info (
"dhcp_failover_reconnect");
3041 if (state -> link_to_peer)
3046 log_info (
"failover peer %s: %s", state -> name,
3047 isc_result_totext (status));
3048 #if defined (DEBUG_FAILOVER_TIMING)
3049 log_info(
"add_timeout +90 dhcp_failover_reconnect");
3054 (
tvref_t)dhcp_failover_state_reference,
3055 (
tvunref_t)dhcp_failover_state_dereference);
3061 dhcp_failover_state_t *state = vs;
3063 #if defined (DEBUG_FAILOVER_TIMING)
3064 log_info (
"dhcp_failover_startup_timeout");
3072 dhcp_failover_link_t *link = vl;
3077 for (; p; p = p -> outer)
3081 log_info (
"failover: link startup timeout");
3088 dhcp_failover_state_t *state = vs;
3089 isc_result_t status;
3092 #if defined (DEBUG_FAILOVER_TIMING)
3093 log_info (
"dhcp_failover_listener_restart");
3097 if (status != ISC_R_SUCCESS) {
3098 log_info (
"failover peer %s: %s", state -> name,
3099 isc_result_totext (status));
3100 #if defined (DEBUG_FAILOVER_TIMING)
3102 "dhcp_failover_listener_restart");
3108 (
tvref_t)dhcp_failover_state_reference,
3109 (
tvunref_t)dhcp_failover_state_dereference);
3116 dhcp_failover_state_t *state = vs;
3118 #if defined (DEBUG_FAILOVER_TIMING)
3119 log_info(
"dhcp_failover_auto_partner_down");
3130 dhcp_failover_state_t *s;
3133 isc_result_t status;
3137 s = (dhcp_failover_state_t *)h;
3142 name, s -> name,
MDL);
3143 return ISC_R_NOTFOUND;
3145 oc = s -> partner.address;
3147 memset (&ds, 0,
sizeof ds);
3154 return ISC_R_NOTFOUND;
3157 name, ds.data, ds.
len,
MDL);
3164 oc = s -> me.address;
3168 s -> partner.port,
MDL);
3171 name, s -> me.port,
MDL);
3174 s -> me.max_flying_updates,
3180 s -> load_balance_max_secs,
MDL);
3185 return ISC_R_NOTFOUND;
3188 s -> partner.state,
MDL);
3191 s -> me.state,
MDL);
3194 s -> partner.stos,
MDL);
3202 s -> last_packet_sent,
MDL);
3205 s -> last_timestamp_received,
3211 s -> me.max_response_delay,
3215 s -> cur_unacked_updates,
MDL);
3218 if (h -> inner && h -> inner -> type -> get_value)
3219 return (*(h -> inner -> type -> get_value))
3220 (h -> inner, id, name, value);
3221 return ISC_R_NOTFOUND;
3225 const char *file,
int line)
3227 dhcp_failover_state_t *s;
3231 s = (dhcp_failover_state_t *)h;
3233 if (s -> link_to_peer)
3234 dhcp_failover_link_dereference (&s -> link_to_peer, file, line);
3237 s -> name = (
char *)0;
3239 if (s -> partner.address)
3241 if (s -> me.address)
3244 dfree (s -> hba, file, line);
3245 s -> hba = (u_int8_t *)0;
3247 if (s -> update_queue_head)
3248 lease_dereference (&s -> update_queue_head, file, line);
3249 if (s -> update_queue_tail)
3250 lease_dereference (&s -> update_queue_tail, file, line);
3251 if (s -> ack_queue_head)
3252 lease_dereference (&s -> ack_queue_head, file, line);
3253 if (s -> ack_queue_tail)
3254 lease_dereference (&s -> ack_queue_tail, file, line);
3255 if (s -> send_update_done)
3256 lease_dereference (&s -> send_update_done, file, line);
3257 if (s -> toack_queue_head)
3258 failover_message_dereference (&s -> toack_queue_head,
3260 if (s -> toack_queue_tail)
3261 failover_message_dereference (&s -> toack_queue_tail,
3263 return ISC_R_SUCCESS;
3275 dhcp_failover_state_t *s;
3276 isc_result_t status;
3283 s = (dhcp_failover_state_t *)h;
3286 if (status != ISC_R_SUCCESS)
3289 if (status != ISC_R_SUCCESS)
3293 if (status != ISC_R_SUCCESS)
3296 if (status != ISC_R_SUCCESS)
3299 sizeof s -> partner.address);
3300 if (status != ISC_R_SUCCESS)
3304 if (status != ISC_R_SUCCESS)
3307 if (status != ISC_R_SUCCESS)
3310 if (status != ISC_R_SUCCESS)
3314 if (status != ISC_R_SUCCESS)
3317 if (status != ISC_R_SUCCESS)
3320 sizeof s -> me.address);
3321 if (status != ISC_R_SUCCESS)
3325 if (status != ISC_R_SUCCESS)
3328 if (status != ISC_R_SUCCESS)
3331 if (status != ISC_R_SUCCESS)
3335 if (status != ISC_R_SUCCESS)
3338 if (status != ISC_R_SUCCESS)
3341 s -> me.max_flying_updates);
3342 if (status != ISC_R_SUCCESS)
3346 if (status != ISC_R_SUCCESS)
3349 if (status != ISC_R_SUCCESS)
3352 if (status != ISC_R_SUCCESS)
3356 if (status != ISC_R_SUCCESS)
3359 if (status != ISC_R_SUCCESS)
3362 (c, (u_int32_t)s -> load_balance_max_secs));
3363 if (status != ISC_R_SUCCESS)
3369 if (status != ISC_R_SUCCESS)
3372 if (status != ISC_R_SUCCESS)
3375 if (status != ISC_R_SUCCESS)
3380 if (status != ISC_R_SUCCESS)
3383 if (status != ISC_R_SUCCESS)
3386 if (status != ISC_R_SUCCESS)
3390 if (status != ISC_R_SUCCESS)
3393 if (status != ISC_R_SUCCESS)
3396 if (status != ISC_R_SUCCESS)
3400 if (status != ISC_R_SUCCESS)
3403 if (status != ISC_R_SUCCESS)
3406 (u_int32_t)s -> partner.stos);
3407 if (status != ISC_R_SUCCESS)
3411 if (status != ISC_R_SUCCESS)
3414 if (status != ISC_R_SUCCESS)
3417 if (status != ISC_R_SUCCESS)
3421 if (status != ISC_R_SUCCESS)
3424 if (status != ISC_R_SUCCESS)
3427 if (status != ISC_R_SUCCESS)
3431 if (status != ISC_R_SUCCESS)
3434 if (status != ISC_R_SUCCESS)
3437 (c, (u_int32_t)s -> last_packet_sent));
3438 if (status != ISC_R_SUCCESS)
3442 if (status != ISC_R_SUCCESS)
3445 if (status != ISC_R_SUCCESS)
3448 (c, (u_int32_t)s -> last_timestamp_received));
3449 if (status != ISC_R_SUCCESS)
3453 if (status != ISC_R_SUCCESS)
3456 if (status != ISC_R_SUCCESS)
3459 if (status != ISC_R_SUCCESS)
3463 if (status != ISC_R_SUCCESS)
3466 if (status != ISC_R_SUCCESS)
3469 (c, (u_int32_t)s -> me.max_response_delay));
3470 if (status != ISC_R_SUCCESS)
3474 if (status != ISC_R_SUCCESS)
3477 if (status != ISC_R_SUCCESS)
3480 (c, (u_int32_t)s -> cur_unacked_updates));
3481 if (status != ISC_R_SUCCESS)
3484 if (h -> inner && h -> inner -> type -> stuff_values)
3485 return (*(h -> inner -> type -> stuff_values)) (c,
id,
3487 return ISC_R_SUCCESS;
3495 isc_result_t status;
3496 dhcp_failover_state_t *s;
3503 if (status == ISC_R_SUCCESS) {
3507 if (status != ISC_R_SUCCESS)
3519 if (status == ISC_R_SUCCESS) {
3521 unsigned l = strlen (s -> name);
3522 if (l == tv -> value -> u.buffer.len &&
3524 tv -> value -> u.buffer.
value, l))
3537 return ISC_R_NOTFOUND;
3548 return ISC_R_SUCCESS;
3554 return ISC_R_NOTIMPLEMENTED;
3560 return ISC_R_NOTIMPLEMENTED;
3564 u_int8_t *addr,
unsigned addrlen)
3569 memset (&ds, 0,
sizeof ds);
3576 state -> partner.address,
MDL)) {
3577 for (i = 0; i + addrlen - 1 < ds.len; i += addrlen) {
3578 if (!memcmp (&ds.data [i],
3591 dhcp_failover_state_t *state;
3592 failover_option_t *name;
3594 if ((strlen(state->name) == name->count) &&
3595 (memcmp(state->name, name->data, name->count) == 0))
3603 static char resbuf[
sizeof(
"Undefined-255: This reason code is not defined "
3604 "in the protocol standard.")];
3606 if ((reason > 0xff) || (reason < 0))
3607 return "Reason code out of range.";
3610 case FTR_ILLEGAL_IP_ADDR:
3611 return "Illegal IP address (not part of any address pool).";
3613 case FTR_FATAL_CONFLICT:
3614 return "Fatal conflict exists: address in use by other client.";
3616 case FTR_MISSING_BINDINFO:
3617 return "Missing binding information.";
3619 case FTR_TIMEMISMATCH:
3620 return "Connection rejected, time mismatch too great.";
3622 case FTR_INVALID_MCLT:
3623 return "Connection rejected, invalid MCLT.";
3625 case FTR_MISC_REJECT:
3626 return "Connection rejected, unknown reason.";
3628 case FTR_DUP_CONNECTION:
3629 return "Connection rejected, duplicate connection.";
3631 case FTR_INVALID_PARTNER:
3632 return "Connection rejected, invalid failover partner.";
3634 case FTR_TLS_UNSUPPORTED:
3635 return "TLS not supported.";
3637 case FTR_TLS_UNCONFIGURED:
3638 return "TLS supported but not configured.";
3640 case FTR_TLS_REQUIRED:
3641 return "TLS required but not supported by partner.";
3643 case FTR_DIGEST_UNSUPPORTED:
3644 return "Message digest not supported.";
3646 case FTR_DIGEST_UNCONFIGURED:
3647 return "Message digest not configured.";
3649 case FTR_VERSION_MISMATCH:
3650 return "Protocol version mismatch.";
3652 case FTR_OUTDATED_BIND_INFO:
3653 return "Outdated binding information.";
3655 case FTR_LESS_CRIT_BIND_INFO:
3656 return "Less critical binding information.";
3658 case FTR_NO_TRAFFIC:
3659 return "No traffic within sufficient time.";
3661 case FTR_HBA_CONFLICT:
3662 return "Hash bucket assignment conflict.";
3664 case FTR_IP_NOT_RESERVED:
3665 return "IP not reserved on this server.";
3667 case FTR_IP_DIGEST_FAILURE:
3668 return "Message digest failed to compare.";
3670 case FTR_IP_MISSING_DIGEST:
3671 return "Missing message digest.";
3674 return "Unknown Error.";
3677 sprintf(resbuf,
"Undefined-%d: This reason code is not defined in the "
3678 "protocol standard.", reason);
3688 return "unknown-state";
3691 return "partner-down";
3697 return "conflict-done";
3700 return "communications-interrupted";
3703 return "resolution-interrupted";
3706 return "potential-conflict";
3712 return "recover-done";
3715 return "recover-wait";
3730 static char messbuf[
sizeof(
"unknown-message-255")];
3733 return "invalid-message";
3737 return "pool-request";
3740 return "pool-response";
3743 return "bind-update";
3751 case FTM_CONNECTACK:
3752 return "connect-ack";
3755 return "update-request";
3758 return "update-done";
3761 return "update-request-all";
3769 case FTM_DISCONNECT:
3770 return "disconnect";
3773 sprintf(messbuf,
"unknown-message-%u", type);
3780 static char optbuf[
sizeof(
"unknown-option-65535")];
3783 return "invalid-option";
3786 case FTO_ADDRESSES_TRANSFERRED:
3787 return "addresses-transferred";
3789 case FTO_ASSIGNED_IP_ADDRESS:
3790 return "assigned-ip-address";
3792 case FTO_BINDING_STATUS:
3793 return "binding-status";
3795 case FTO_CLIENT_IDENTIFIER:
3796 return "client-identifier";
3807 case FTO_DELAYED_SERVICE:
3808 return "delayed-service";
3816 case FTO_LEASE_EXPIRY:
3817 return "lease-expiry";
3819 case FTO_MAX_UNACKED:
3820 return "max-unacked";
3828 case FTO_MESSAGE_DIGEST:
3829 return "message-digest";
3831 case FTO_POTENTIAL_EXPIRY:
3832 return "potential-expiry";
3834 case FTO_PROTOCOL_VERSION:
3835 return "protocol-version";
3837 case FTO_RECEIVE_TIMER:
3838 return "receive-timer";
3840 case FTO_REJECT_REASON:
3841 return "reject-reason";
3843 case FTO_RELATIONSHIP_NAME:
3844 return "relationship-name";
3846 case FTO_REPLY_OPTIONS:
3847 return "reply-options";
3849 case FTO_REQUEST_OPTIONS:
3850 return "request-options";
3852 case FTO_SERVER_FLAGS:
3853 return "server-flags";
3855 case FTO_SERVER_STATE:
3856 return "server-state";
3864 case FTO_TLS_REQUEST:
3865 return "tls-request";
3867 case FTO_VENDOR_CLASS:
3868 return "vendor-class";
3870 case FTO_VENDOR_OPTIONS:
3871 return "vendor-options";
3874 sprintf(optbuf,
"unknown-option-%u", type);
3883 const char *fmt, ...)
3896 if (vsnprintf (tbuf,
sizeof tbuf, fmt, va) >=
sizeof tbuf)
3897 log_fatal (
"%s: vsnprintf would truncate",
3898 "dhcp_failover_make_option");
3902 strlen (tbuf), tbuf);
3906 char *obuf,
unsigned *obufix,
3907 unsigned obufmax, ...)
3910 struct failover_option_info *info;
3912 unsigned size, count;
3918 #if defined (DEBUG_FAILOVER_MESSAGES)
3926 failover_option_t
option, *op;
3930 if (code < 1 || code > FTO_MAX || ft_options [code].type == FT_UNDEF) {
3933 info = &ft_options [code];
3935 va_start (va, obufmax);
3939 if (info -> type == FT_DDNS || info -> type == FT_DDNS1) {
3940 count = info -> type == FT_DDNS ? 1 : 2;
3941 size = va_arg (va,
int) + count;
3944 if (info -> num_present)
3945 count = info -> num_present;
3947 count = va_arg (va,
int);
3950 switch (info -> type) {
3957 case FT_TEXT_OR_BYTES:
3959 txt = va_arg (va,
char *);
3964 ilen = va_arg (va,
unsigned);
3965 size = count * ilen;
3978 log_fatal (
"bogus type in failover_make_option: %d",
3987 option.count = size;
3998 #if defined (DEBUG_FAILOVER_MESSAGES)
4006 if (snprintf (tbuf,
sizeof tbuf,
" (%s<%d>", info -> name,
4007 option.count) >=
sizeof tbuf)
4008 log_fatal (
"dhcp_failover_make_option: tbuf overflow");
4013 switch (info -> type) {
4015 for (i = 0; i < count; i++) {
4016 val = va_arg (va,
unsigned);
4017 #if defined (DEBUG_FAILOVER_MESSAGES)
4019 sprintf (tbuf,
" %d", val);
4022 option.data [i + 4] = val;
4027 for (i = 0; i < count; i++) {
4028 iaddr = va_arg (va, u_int8_t *);
4031 log_error (
"IP addrlen=%d, should be 4.",
4037 #if defined (DEBUG_FAILOVER_MESSAGES)
4039 sprintf (tbuf,
" %u.%u.%u.%u",
4040 iaddr [0], iaddr [1], iaddr [2], iaddr [3]);
4043 memcpy (&option.data [4 + i * ilen], iaddr, ilen);
4048 for (i = 0; i < count; i++) {
4049 val = va_arg (va,
unsigned);
4050 #if defined (DEBUG_FAILOVER_MESSAGES)
4052 sprintf (tbuf,
" %d", val);
4055 putULong (&option.data [4 + i * 4], val);
4061 bval = va_arg (va, u_int8_t *);
4062 #if defined (DEBUG_FAILOVER_MESSAGES)
4063 for (i = 0; i < count; i++) {
4065 sprintf (tbuf,
" %d", bval [i]);
4069 memcpy (&option.data [4], bval, count);
4076 case FT_TEXT_OR_BYTES:
4078 #if defined (DEBUG_FAILOVER_MESSAGES)
4086 if (snprintf (tbuf,
sizeof tbuf,
"\"%s\"", txt) >=
sizeof tbuf)
4087 log_fatal (
"dhcp_failover_make_option: tbuf overflow");
4090 memcpy (&option.data [4], txt, count);
4095 option.data [4] = va_arg (va,
unsigned);
4097 option.data [5] = va_arg (va,
unsigned);
4098 bval = va_arg (va, u_int8_t *);
4099 memcpy (&option.data [4 + count], bval, size - count - 4);
4100 #if defined (DEBUG_FAILOVER_MESSAGES)
4101 for (i = 4; i < size; i++) {
4103 sprintf (tbuf,
" %d", option.data [i]);
4110 for (i = 0; i < count; i++) {
4111 val = va_arg (va, u_int32_t);
4112 #if defined (DEBUG_FAILOVER_MESSAGES)
4114 sprintf (tbuf,
" %d", val);
4117 putUShort (&option.data [4 + i * 2], val);
4126 #if defined DEBUG_FAILOVER_MESSAGES
4132 op =
dmalloc (
sizeof (failover_option_t),
MDL);
4146 int msg_type, u_int32_t xid, ...)
4152 failover_option_t *option;
4153 unsigned char *opbuf;
4154 isc_result_t status = ISC_R_SUCCESS;
4160 va_start (list, xid);
4161 while ((option = va_arg (list, failover_option_t *))) {
4163 size += option -> count;
4170 if (!bad_option && size) {
4173 status = ISC_R_NOMEMORY;
4175 opbuf = (
unsigned char *)0;
4177 va_start (list, xid);
4178 while ((option = va_arg (list, failover_option_t *))) {
4181 if (!bad_option && opbuf)
4182 memcpy (&opbuf [opix],
4183 option -> data, option -> count);
4186 opix += option -> count;
4200 if (status != ISC_R_SUCCESS)
4206 if (status != ISC_R_SUCCESS)
4212 if (status != ISC_R_SUCCESS)
4217 if (status != ISC_R_SUCCESS)
4222 if (status != ISC_R_SUCCESS)
4228 if (status != ISC_R_SUCCESS)
4232 if (link -> state_object &&
4233 link -> state_object -> link_to_peer == link) {
4234 #if defined (DEBUG_FAILOVER_CONTACT_TIMING)
4236 (
int)(link -> state_object ->
4237 partner.max_response_delay) / 3,
4238 "dhcp_failover_send_contact");
4241 (
int)(link -> state_object ->
4242 partner.max_response_delay) / 3;
4246 (
tvref_t)dhcp_failover_state_reference,
4247 (
tvunref_t)dhcp_failover_state_dereference);
4254 log_info (
"dhcp_failover_put_message: something went wrong.");
4261 dhcp_failover_state_t *state = vstate;
4262 dhcp_failover_link_t *link;
4264 #if defined (DEBUG_FAILOVER_TIMING)
4265 log_info (
"dhcp_failover_timeout");
4270 link = state -> link_to_peer;
4276 log_error (
"timeout waiting for failover peer %s", state -> name);
4285 dhcp_failover_state_t *state = vstate;
4286 dhcp_failover_link_t *link;
4287 isc_result_t status;
4289 #if defined(DEBUG_FAILOVER_MESSAGES) && \
4290 defined(DEBUG_FAILOVER_CONTACT_MESSAGES)
4292 unsigned obufix = 0;
4297 #if defined (DEBUG_FAILOVER_CONTACT_TIMING)
4298 log_info (
"dhcp_failover_send_contact");
4303 link = state -> link_to_peer;
4310 (link, link -> outer,
4311 FTM_CONTACT, link->xid++,
4312 (failover_option_t *)0));
4314 #if defined(DEBUG_FAILOVER_MESSAGES) && \
4315 defined(DEBUG_FAILOVER_CONTACT_MESSAGES)
4316 if (status != ISC_R_SUCCESS)
4330 dhcp_failover_link_t *link;
4331 isc_result_t status;
4333 #if defined (DEBUG_FAILOVER_MESSAGES)
4335 unsigned obufix = 0;
4337 # define FMA obuf, &obufix, sizeof obuf
4340 # define FMA (char *)0, (unsigned *)0, 0
4345 link = state -> link_to_peer;
4352 (link, link -> outer,
4353 FTM_STATE, link->xid++,
4356 ? state -> saved_state
4357 : state -> me.state)),
4359 (FTO_SERVER_FLAGS, FMA,
4361 ? FTF_SERVER_STARTUP : 0)),
4363 (failover_option_t *)0));
4365 #if defined (DEBUG_FAILOVER_MESSAGES)
4366 if (status != ISC_R_SUCCESS)
4375 return ISC_R_SUCCESS;
4382 dhcp_failover_link_t *link;
4383 dhcp_failover_state_t *state;
4384 isc_result_t status;
4385 #if defined (DEBUG_FAILOVER_MESSAGES)
4387 unsigned obufix = 0;
4389 # define FMA obuf, &obufix, sizeof obuf
4392 # define FMA (char *)0, (unsigned *)0, 0
4397 link = (dhcp_failover_link_t *)l;
4398 state = link -> state_object;
4405 FTM_CONNECT, link->xid++,
4407 strlen(state->name), state->name),
4409 state -> me.max_flying_updates),
4411 state -> me.max_response_delay),
4415 DHCP_FAILOVER_VERSION),
4423 (failover_option_t *)0));
4425 #if defined (DEBUG_FAILOVER_MESSAGES)
4426 if (status != ISC_R_SUCCESS)
4437 dhcp_failover_state_t *state,
4438 int reason,
const char *errmsg)
4440 dhcp_failover_link_t *link;
4441 isc_result_t status;
4442 #if defined (DEBUG_FAILOVER_MESSAGES)
4444 unsigned obufix = 0;
4446 # define FMA obuf, &obufix, sizeof obuf
4449 # define FMA (char *)0, (unsigned *)0, 0
4454 link = (dhcp_failover_link_t *)l;
4461 FTM_CONNECTACK, link->imsg->xid,
4464 strlen(state->name), state->name)
4465 : (link->imsg->options_present & FTB_RELATIONSHIP_NAME)
4467 link->imsg->relationship_name.count,
4468 link->imsg->relationship_name.data)
4469 : &skip_failover_option,
4472 state -> me.max_flying_updates)
4473 : &skip_failover_option,
4476 state -> me.max_response_delay)
4477 : &skip_failover_option,
4481 DHCP_FAILOVER_VERSION),
4482 (link->imsg->options_present & FTB_TLS_REQUEST)
4485 : &skip_failover_option,
4489 : &skip_failover_option,
4492 strlen (errmsg), errmsg)
4493 : &skip_failover_option,
4494 (failover_option_t *)0));
4496 #if defined (DEBUG_FAILOVER_MESSAGES)
4497 if (status != ISC_R_SUCCESS)
4509 const char *message)
4511 dhcp_failover_link_t *link;
4512 isc_result_t status;
4513 #if defined (DEBUG_FAILOVER_MESSAGES)
4515 unsigned obufix = 0;
4517 # define FMA obuf, &obufix, sizeof obuf
4520 # define FMA (char *)0, (unsigned *)0, 0
4525 link = (dhcp_failover_link_t *)l;
4529 if (!message && reason)
4534 FTM_DISCONNECT, link->xid++,
4539 strlen (message), message)
4540 : &skip_failover_option),
4541 (failover_option_t *)0));
4543 #if defined (DEBUG_FAILOVER_MESSAGES)
4544 if (status != ISC_R_SUCCESS)
4557 struct lease *lease)
4559 dhcp_failover_link_t *link;
4560 isc_result_t status;
4563 #if defined (DEBUG_FAILOVER_MESSAGES)
4565 unsigned obufix = 0;
4567 # define FMA obuf, &obufix, sizeof obuf
4570 # define FMA (char *)0, (unsigned *)0, 0
4573 if (!state -> link_to_peer ||
4576 link = (dhcp_failover_link_t *)state -> link_to_peer;
4588 if ((state->i_am == primary) && (transmit_state ==
FTS_FREE))
4590 else if ((state->i_am == secondary) &&
4594 flags |= FTF_IP_FLAG_RESERVE;
4597 flags |= FTF_IP_FLAG_BOOTP;
4637 (link, link -> outer,
4643 lease -> desired_binding_state),
4648 : &skip_failover_option,
4649 lease -> hardware_addr.hlen
4651 lease -> hardware_addr.hlen,
4652 lease -> hardware_addr.hbuf)
4653 : &skip_failover_option,
4660 (lease->
cltt != 0) ?
4662 &skip_failover_option,
4665 &skip_failover_option,
4666 &skip_failover_option,
4667 &skip_failover_option,
4668 &skip_failover_option,
4669 (failover_option_t *)0));
4671 #if defined (DEBUG_FAILOVER_MESSAGES)
4672 if (status != ISC_R_SUCCESS)
4685 failover_message_t *msg,
4686 int reason,
const char *message)
4688 dhcp_failover_link_t *link;
4689 isc_result_t status;
4690 #if defined (DEBUG_FAILOVER_MESSAGES)
4692 unsigned obufix = 0;
4694 # define FMA obuf, &obufix, sizeof obuf
4697 # define FMA (char *)0, (unsigned *)0, 0
4700 if (!state -> link_to_peer ||
4703 link = (dhcp_failover_link_t *)state -> link_to_peer;
4708 if (!message && reason)
4713 (link, link -> outer,
4714 FTM_BNDACK, msg->xid,
4716 sizeof msg -> assigned_addr,
4717 &msg -> assigned_addr),
4718 #ifdef DO_BNDACK_SHOULD_NOT
4720 msg -> binding_status),
4721 (msg -> options_present & FTB_CLIENT_IDENTIFIER)
4723 msg -> client_identifier.count,
4724 msg -> client_identifier.data)
4725 : &skip_failover_option,
4726 (msg -> options_present & FTB_CHADDR)
4728 msg -> chaddr.count,
4730 : &skip_failover_option,
4734 msg -> potential_expiry),
4737 (msg->options_present & FTB_CLTT) ?
4739 &skip_failover_option,
4740 ((msg->options_present & FTB_IP_FLAGS) && msg->ip_flags) ?
4743 : &skip_failover_option,
4747 : &skip_failover_option,
4750 strlen (message), message)
4751 : &skip_failover_option,
4752 #ifdef DO_BNDACK_SHOULD_NOT
4753 &skip_failover_option,
4754 &skip_failover_option,
4755 &skip_failover_option,
4757 (failover_option_t *)0));
4759 #if defined (DEBUG_FAILOVER_MESSAGES)
4760 if (status != ISC_R_SUCCESS)
4772 dhcp_failover_link_t *link;
4773 isc_result_t status;
4774 #if defined (DEBUG_FAILOVER_MESSAGES)
4776 unsigned obufix = 0;
4778 # define FMA obuf, &obufix, sizeof obuf
4781 # define FMA (char *)0, (unsigned *)0, 0
4784 if (!state -> link_to_peer ||
4787 link = (dhcp_failover_link_t *)state -> link_to_peer;
4793 (link, link -> outer,
4794 FTM_POOLREQ, link->xid++,
4795 (failover_option_t *)0));
4797 #if defined (DEBUG_FAILOVER_MESSAGES)
4798 if (status != ISC_R_SUCCESS)
4811 dhcp_failover_link_t *link;
4812 isc_result_t status;
4813 #if defined (DEBUG_FAILOVER_MESSAGES)
4815 unsigned obufix = 0;
4817 # define FMA obuf, &obufix, sizeof obuf
4820 # define FMA (char *)0, (unsigned *)0, 0
4823 if (!state -> link_to_peer ||
4826 link = (dhcp_failover_link_t *)state -> link_to_peer;
4832 (link, link -> outer,
4833 FTM_POOLRESP, link->imsg->xid,
4836 (failover_option_t *)0));
4838 #if defined (DEBUG_FAILOVER_MESSAGES)
4839 if (status != ISC_R_SUCCESS)
4851 dhcp_failover_link_t *link;
4852 isc_result_t status;
4853 #if defined (DEBUG_FAILOVER_MESSAGES)
4855 unsigned obufix = 0;
4857 # define FMA obuf, &obufix, sizeof obuf
4860 # define FMA (char *)0, (unsigned *)0, 0
4863 if (!state -> link_to_peer ||
4866 link = (dhcp_failover_link_t *)state -> link_to_peer;
4871 if (state -> curUPD)
4872 return ISC_R_ALREADYRUNNING;
4875 (link, link -> outer,
4876 FTM_UPDREQ, link->xid++,
4877 (failover_option_t *)0));
4879 if (status == ISC_R_SUCCESS)
4880 state -> curUPD = FTM_UPDREQ;
4882 #if defined (DEBUG_FAILOVER_MESSAGES)
4883 if (status != ISC_R_SUCCESS)
4890 log_info (
"Sent update request message to %s", state -> name);
4897 dhcp_failover_link_t *link;
4898 isc_result_t status;
4899 #if defined (DEBUG_FAILOVER_MESSAGES)
4901 unsigned obufix = 0;
4903 # define FMA obuf, &obufix, sizeof obuf
4906 # define FMA (char *)0, (unsigned *)0, 0
4909 if (!state -> link_to_peer ||
4912 link = (dhcp_failover_link_t *)state -> link_to_peer;
4918 if (state -> curUPD && (state -> curUPD != FTM_UPDREQ))
4919 return ISC_R_ALREADYRUNNING;
4922 (link, link -> outer,
4923 FTM_UPDREQALL, link->xid++,
4924 (failover_option_t *)0));
4926 if (status == ISC_R_SUCCESS)
4927 state -> curUPD = FTM_UPDREQALL;
4929 #if defined (DEBUG_FAILOVER_MESSAGES)
4930 if (status != ISC_R_SUCCESS)
4937 log_info (
"Sent update request all message to %s", state -> name);
4943 dhcp_failover_link_t *link;
4944 isc_result_t status;
4945 #if defined (DEBUG_FAILOVER_MESSAGES)
4947 unsigned obufix = 0;
4949 # define FMA obuf, &obufix, sizeof obuf
4952 # define FMA (char *)0, (unsigned *)0, 0
4955 if (!state -> link_to_peer ||
4958 link = (dhcp_failover_link_t *)state -> link_to_peer;
4964 (link, link -> outer,
4965 FTM_UPDDONE, state->updxid,
4966 (failover_option_t *)0));
4968 #if defined (DEBUG_FAILOVER_MESSAGES)
4969 if (status != ISC_R_SUCCESS)
4977 log_info (
"Sent update done message to %s", state -> name);
5001 static isc_boolean_t
5002 failover_lease_is_better(dhcp_failover_state_t *state,
struct lease *lease,
5003 failover_message_t *msg)
5013 if ((msg->options_present & FTB_CLTT) != 0)
5014 msg_cltt = msg->cltt;
5018 switch(local_state) {
5021 if (msg_cltt < lease->cltt)
5023 else if (msg_cltt > lease->
cltt)
5025 else if (state->i_am == primary)
5042 else if (state->i_am == primary)
5058 failover_message_t *msg)
5060 struct lease *lt = NULL, *lease = NULL;
5062 int reason = FTR_MISC_REJECT;
5063 const char *message;
5064 int new_binding_state;
5065 int send_to_backup = 0;
5066 int required_options;
5067 isc_boolean_t chaddr_changed = ISC_FALSE;
5068 isc_boolean_t ident_changed = ISC_FALSE;
5071 required_options = FTB_ASSIGNED_IP_ADDRESS | FTB_BINDING_STATUS;
5072 if ((msg->options_present & required_options) != required_options) {
5073 message =
"binding update lacks required options";
5074 reason = FTR_MISSING_BINDINFO;
5078 ia.len =
sizeof msg -> assigned_addr;
5079 memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
5082 message =
"unknown IP address";
5083 reason = FTR_ILLEGAL_IP_ADDR;
5091 if ((lease->pool == NULL) || (lease->pool->failover_peer == NULL) ||
5092 (lease->pool->failover_peer != state)) {
5093 message =
"IP address is covered by a different failover "
5094 "relationship state";
5095 reason = FTR_ILLEGAL_IP_ADDR;
5109 if ((lease->flags & ON_ACK_QUEUE) != 0) {
5110 if (failover_lease_is_better(state, lease, msg)) {
5111 message =
"incoming update is less critical than "
5113 reason = FTR_LESS_CRIT_BIND_INFO;
5123 message =
"no memory";
5127 if (msg -> options_present & FTB_CHADDR) {
5129 message =
"BNDUPD to ABANDONED with a CHADDR";
5132 if (msg -> chaddr.count >
sizeof lt -> hardware_addr.hbuf) {
5133 message =
"chaddr too long";
5139 msg->chaddr.count) != 0))
5140 chaddr_changed = ISC_TRUE;
5142 lt -> hardware_addr.hlen = msg -> chaddr.count;
5143 memcpy (lt -> hardware_addr.hbuf, msg -> chaddr.data,
5144 msg -> chaddr.count);
5145 }
else if (msg->binding_status ==
FTS_ACTIVE ||
5148 message =
"BNDUPD without CHADDR";
5149 reason = FTR_MISSING_BINDINFO;
5152 chaddr_changed = ISC_TRUE;
5162 if (msg->options_present & FTB_CLIENT_IDENTIFIER) {
5164 message =
"BNDUPD to ABANDONED with client-id";
5168 if ((lt->
uid_len != msg->client_identifier.count) ||
5169 (lt->
uid == NULL) ||
5170 (memcmp(lt->
uid, msg->client_identifier.data,
5172 ident_changed = ISC_TRUE;
5174 lt->
uid_len = msg->client_identifier.count;
5189 message =
"no memory";
5198 msg -> client_identifier.data, lt -> uid_len);
5199 }
else if (lt->
uid && msg->binding_status !=
FTS_RESET &&
5202 ident_changed = ISC_TRUE;
5235 (chaddr_changed || ident_changed)) {
5236 #if defined (NSUPDATE)
5240 if (lease->scope != NULL)
5245 if (msg -> options_present & FTB_STOS) {
5246 lt -> starts = msg -> stos;
5248 if (msg -> options_present & FTB_LEASE_EXPIRY) {
5249 lt -> ends = msg -> expiry;
5251 if (msg->options_present & FTB_POTENTIAL_EXPIRY) {
5252 lt->
atsfp = lt->
tsfp = msg->potential_expiry;
5254 if (msg->options_present & FTB_IP_FLAGS) {
5255 if (msg->ip_flags & FTF_IP_FLAG_RESERVE) {
5256 if ((((state->i_am == primary) &&
5257 (lease->binding_state ==
FTS_FREE)) ||
5258 ((state->i_am == secondary) &&
5261 message =
"Address is not reserved.";
5262 reason = FTR_IP_NOT_RESERVED;
5270 if (msg->ip_flags & FTF_IP_FLAG_BOOTP) {
5271 if ((((state->i_am == primary) &&
5272 (lease->binding_state ==
FTS_FREE)) ||
5273 ((state->i_am == secondary) &&
5276 message =
"Address is not allocated to BOOTP.";
5283 if (msg->ip_flags & ~(FTF_IP_FLAG_RESERVE | FTF_IP_FLAG_BOOTP))
5284 log_info(
"Unknown IP-flags set in BNDUPD (0x%x).",
5289 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
5290 log_info (
"processing state transition for %s: %s to %s",
5298 if (state -> me.state ==
normal) {
5301 (lease, state, msg -> binding_status,
5302 msg -> potential_expiry));
5309 (lease, state, msg -> binding_status,
5310 msg -> potential_expiry));
5312 if (new_binding_state != msg -> binding_status) {
5315 if (snprintf (outbuf,
sizeof outbuf,
5316 "%s: invalid state transition: %s to %s",
5321 log_fatal (
"%s: impossible outbuf overflow",
5322 "dhcp_failover_process_bind_update");
5332 lt -> next_binding_state =
FTS_FREE;
5339 if ((state->i_am == primary) &&
5343 lt -> next_binding_state = new_binding_state;
5345 msg -> binding_status = lt -> next_binding_state;
5356 message =
"database update failed";
5367 if (send_to_backup && secondary_not_hoarding(state, lease->pool)) {
5374 log_error(
"can't commit lease %s for mac addr "
5375 "affinity",
piaddr(lease->ip_addr));
5382 lease_dereference (<,
MDL);
5384 lease_dereference (&lease,
MDL);
5386 return ISC_R_SUCCESS;
5395 secondary_not_hoarding(dhcp_failover_state_t *state,
struct pool *p) {
5403 hold = ((total * state->max_lease_ownership) + 50) / 100;
5414 return(lts > -hold);
5418 failover_message_t *msg)
5420 struct lease *lt = (
struct lease *)0;
5421 struct lease *lease = (
struct lease *)0;
5423 const char *message =
"no memory";
5424 u_int32_t pot_expire;
5425 int send_to_backup = ISC_FALSE;
5428 ia.len =
sizeof msg -> assigned_addr;
5429 memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
5432 message =
"no such lease";
5437 if (msg -> options_present & FTB_REJECT_REASON) {
5438 log_error (
"bind update on %s from %s rejected: %.*s",
5439 piaddr (ia), state -> name,
5440 (
int)((msg -> options_present & FTB_MESSAGE)
5441 ? msg -> message.count
5443 (msg -> reject_reason))),
5444 (msg -> options_present & FTB_MESSAGE)
5445 ? (
const char *)(msg -> message.data)
5447 (msg -> reject_reason)));
5458 message =
"xid mismatch";
5463 if (msg->options_present & FTO_POTENTIAL_EXPIRY)
5464 pot_expire = msg->potential_expiry;
5466 pot_expire = lease->
tstp;
5486 lease->
atsfp = lease->
tsfp = pot_expire;
5487 if ((state->i_am == secondary) &&
5509 if (state->i_am == primary &&
5512 send_to_backup = ISC_TRUE;
5514 if (!send_to_backup && state->me.state ==
normal)
5520 lease->
atsfp = lease->
tsfp = pot_expire;
5525 (
struct lease *)0, 0, 0, 0);
5543 if (state -> send_update_done == lease) {
5544 lease_dereference (&state -> send_update_done,
MDL);
5551 if (send_to_backup && secondary_not_hoarding(state, lease->
pool)) {
5560 if (state->me.state ==
normal)
5569 lease_dereference (&lease,
MDL);
5571 lease_dereference (<,
MDL);
5573 return ISC_R_SUCCESS;
5576 log_info (
"bind update on %s got ack from %s: %s.",
5577 piaddr (ia), state -> name, message);
5588 #define FREE_LEASES 0
5589 #define ACTIVE_LEASES 1
5590 #define EXPIRED_LEASES 2
5591 #define ABANDONED_LEASES 3
5592 #define BACKUP_LEASES 4
5593 #define RESERVED_LEASES 5
5599 for (p = s ->
pools; p; p = p ->
next) {
5611 for (l = *(lptr [i]); l; l = l ->
next) {
5623 return ISC_R_SUCCESS;
5628 failover_message_t *msg)
5630 if (state->send_update_done) {
5631 log_info(
"Received update request while old update still "
5632 "flying! Silently discarding old request.");
5633 lease_dereference(&state->send_update_done,
MDL);
5639 state->updxid = msg->xid;
5644 if (state -> update_queue_tail) {
5645 lease_reference (&state -> send_update_done,
5646 state -> update_queue_tail,
MDL);
5648 log_info (
"Update request from %s: sending update",
5654 log_info (
"Update request from %s: nothing pending",
5658 return ISC_R_SUCCESS;
5663 failover_message_t *msg)
5665 if (state->send_update_done) {
5666 log_info(
"Received update request while old update still "
5667 "flying! Silently discarding old request.");
5668 lease_dereference(&state->send_update_done,
MDL);
5674 state->updxid = msg->xid;
5676 if (state -> update_queue_tail) {
5677 lease_reference (&state -> send_update_done,
5678 state -> update_queue_tail,
MDL);
5680 log_info (
"Update request all from %s: sending update",
5686 log_info (
"Update request all from %s: nothing pending",
5690 return ISC_R_SUCCESS;
5695 failover_message_t *msg)
5699 log_info (
"failover peer %s: peer update completed.",
5702 state -> curUPD = 0;
5704 switch (state -> me.state) {
5720 if (state->i_am == secondary) {
5723 log_error(
"Secondary is in conflict_done "
5724 "state after conflict resolution, "
5725 "this is illegal.");
5729 if (state->i_am == primary)
5732 log_error(
"Spurious update-done message.");
5738 log_error(
"Spurious update-done message.");
5747 if (state -> me.stos + state -> mclt >
cur_time &&
5748 state -> partner.state !=
recover &&
5751 #if defined (DEBUG_FAILOVER_TIMING)
5754 state -> me.stos + state -> mclt),
5755 "dhcp_failover_recover_done");
5757 tv . tv_sec = (
int)(state -> me.stos + state -> mclt);
5762 (
tvref_t)omapi_object_reference,
5769 return ISC_R_SUCCESS;
5774 dhcp_failover_state_t *state = sp;
5776 #if defined (DEBUG_FAILOVER_TIMING)
5777 log_info (
"dhcp_failover_recover_done");
5783 #if defined (DEBUG_FAILOVER_MESSAGES)
5790 unsigned *obufix,
unsigned obufmax,
const char *s)
5792 int len = strlen (s);
5794 while (len + *obufix + 1 >= obufmax) {
5803 strcpy (&obuf [*obufix], s);
5810 unsigned char loadb_mx_tbl[256] = {
5811 251, 175, 119, 215, 81, 14, 79, 191, 103, 49,
5812 181, 143, 186, 157, 0, 232, 31, 32, 55, 60,
5813 152, 58, 17, 237, 174, 70, 160, 144, 220, 90,
5814 57, 223, 59, 3, 18, 140, 111, 166, 203, 196,
5815 134, 243, 124, 95, 222, 179, 197, 65, 180, 48,
5816 36, 15, 107, 46, 233, 130, 165, 30, 123, 161,
5817 209, 23, 97, 16, 40, 91, 219, 61, 100, 10,
5818 210, 109, 250, 127, 22, 138, 29, 108, 244, 67,
5819 207, 9, 178, 204, 74, 98, 126, 249, 167, 116,
5820 34, 77, 193, 200, 121, 5, 20, 113, 71, 35,
5821 128, 13, 182, 94, 25, 226, 227, 199, 75, 27,
5822 41, 245, 230, 224, 43, 225, 177, 26, 155, 150,
5823 212, 142, 218, 115, 241, 73, 88, 105, 39, 114,
5824 62, 255, 192, 201, 145, 214, 168, 158, 221, 148,
5825 154, 122, 12, 84, 82, 163, 44, 139, 228, 236,
5826 205, 242, 217, 11, 187, 146, 159, 64, 86, 239,
5827 195, 42, 106, 198, 118, 112, 184, 172, 87, 2,
5828 173, 117, 176, 229, 247, 253, 137, 185, 99, 164,
5829 102, 147, 45, 66, 231, 52, 141, 211, 194, 206,
5830 246, 238, 56, 110, 78, 248, 63, 240, 189, 93,
5831 92, 51, 53, 183, 19, 171, 72, 50, 33, 104,
5832 101, 69, 8, 252, 83, 120, 76, 135, 85, 54,
5833 202, 125, 188, 213, 96, 235, 136, 208, 162, 129,
5834 190, 132, 156, 38, 47, 1, 7, 254, 24, 4,
5835 216, 131, 89, 21, 28, 133, 37, 153, 149, 80,
5836 170, 68, 6, 169, 234, 151 };
5838 static unsigned char loadb_p_hash (
const unsigned char *,
unsigned);
5839 static unsigned char loadb_p_hash (
const unsigned char *key,
unsigned len)
5841 unsigned char hash = len;
5843 for(i = len; i > 0; )
5844 hash = loadb_mx_tbl [hash ^ (key [--i])];
5852 unsigned char hbaix;
5856 ec = ntohs(packet->
raw->
secs);
5858 #if defined(SECS_BYTEORDER)
5865 if ((ec > 255) && ((ec & 0xff) == 0)) {
5866 ec = (ec >> 8) | (ec << 8);
5870 if (state->load_balance_max_secs < ec) {
5881 memset(&ds, 0,
sizeof ds);
5886 hbaix = loadb_p_hash(ds.data, ds.len);
5890 hbaix = loadb_p_hash(packet->
raw->
chaddr,
5894 hm = state->hba[(hbaix >> 3) & 0x1F] & (1 << (hbaix & 0x07));
5896 if (state->i_am == primary)
5910 dhcp_failover_state_t *state;
5911 unsigned char hbaix;
5919 if (!state || !state->hba)
5936 hm = state->hba[(hbaix >> 3) & 0x1F] & (1 << (hbaix & 0x07));
5938 if (state->i_am == primary)
5952 dhcp_failover_state_t *state,
5959 if (binding_state == lease -> binding_state)
5960 return binding_state;
5962 switch (lease -> binding_state) {
5965 switch (binding_state) {
5976 if (state -> i_am == secondary)
5977 return binding_state;
5985 new_state = binding_state;
5995 if (state -> i_am == primary) {
5999 return binding_state;
6000 new_state = lease -> binding_state;
6005 switch (binding_state) {
6011 new_state = lease -> binding_state;
6014 return binding_state;
6022 if (lease -> ends - 65 >
cur_time) {
6023 new_state = lease -> binding_state;
6031 return binding_state;
6039 switch (binding_state) {
6045 new_state = lease -> binding_state;
6048 return binding_state;
6055 return binding_state;
6062 switch (binding_state) {
6073 return binding_state;
6080 switch (binding_state) {
6086 new_state = lease -> binding_state;
6089 return binding_state;
6096 return binding_state;
6103 switch (binding_state) {
6112 if (state -> i_am == primary)
6113 return binding_state;
6119 return binding_state;
6122 new_state = lease -> binding_state;
6142 dhcp_failover_state_t *state,
6149 if (binding_state == lease -> binding_state)
6150 new_state = binding_state;
6152 switch (lease -> binding_state) {
6162 new_state = binding_state;
6169 switch (binding_state) {
6172 new_state = lease -> binding_state;
6184 new_state = binding_state;
6195 new_state = binding_state;
6230 dhcp_failover_state_t *peer;
6232 if (lease && lease->
pool &&
6256 if (peer -> i_am == primary)
6260 ((lease->
tsfp < peer->me.stos) ?
6261 (peer->me.stos + peer->mclt <
cur_time) :
6280 if ((peer->i_am == primary) &&
6283 if ((peer->i_am == secondary) &&
6314 if (peer->i_am == secondary)
6318 ((lease->
tsfp < peer->me.stos) ?
6319 (peer->me.stos + peer->mclt <
cur_time) :
6336 static isc_result_t failover_message_reference (failover_message_t **mp,
6337 failover_message_t *m,
6338 const char *file,
int line)
6342 return ISC_R_SUCCESS;
6345 static isc_result_t failover_message_dereference (failover_message_t **mp,
6346 const char *file,
int line)
6348 failover_message_t *m;
6351 if (m -> refcnt == 0) {
6353 failover_message_dereference (&m -> next,
6355 if (m -> chaddr.data)
6356 dfree (m -> chaddr.data, file, line);
6357 if (m -> client_identifier.data)
6358 dfree (m -> client_identifier.data, file, line);
6360 dfree (m -> hba.data, file, line);
6361 if (m -> message.data)
6362 dfree (m -> message.data, file, line);
6363 if (m -> relationship_name.data)
6364 dfree (m -> relationship_name.data, file, line);
6365 if (m -> reply_options.data)
6366 dfree (m -> reply_options.data, file, line);
6367 if (m -> request_options.data)
6368 dfree (m -> request_options.data, file, line);
6369 if (m -> vendor_class.data)
6370 dfree (m -> vendor_class.data, file, line);
6371 if (m -> vendor_options.data)
6372 dfree (m -> vendor_options.data, file, line);
6375 dfree (*mp, file, line);
6378 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)
dhcp_failover_state_t * failover_peer
#define OMAPI_OBJECT_ALLOC(name, stype, type)
void dhcp_failover_recover_done(void *)
failover_option_t null_failover_option
isc_result_t omapi_listen_addr(omapi_object_t *, omapi_addr_t *, int)
#define DHCP_R_KEYCONFLICT
const char * binding_state_print(enum failover_state state)
struct option_state * options
isc_result_t dhcp_failover_send_bind_ack(dhcp_failover_state_t *, failover_message_t *, int, const char *)
void log_fatal(const char *,...) __attribute__((__format__(__printf__
isc_result_t dhcp_failover_send_poolresp(dhcp_failover_state_t *, int)
const char * dhcp_flink_state_names[]
isc_result_t dhcp_failover_link_destroy(omapi_object_t *, const char *, int)
const char * dhcp_failover_message_name(unsigned)
isc_result_t dhcp_failover_state_transition(dhcp_failover_state_t *, const char *)
isc_result_t dhcp_failover_state_destroy(omapi_object_t *, const char *, int)
struct hardware hardware_addr
isc_result_t omapi_connection_put_uint32(omapi_object_t *, u_int32_t)
omapi_object_type_t * omapi_type_protocol
omapi_object_type_t * dhcp_type_failover_listener
failover_option_t skip_failover_option
isc_result_t omapi_make_uint_value(omapi_value_t **, omapi_data_string_t *, unsigned int, const char *, int)
isc_result_t dhcp_failover_listen(omapi_object_t *)
isc_result_t dhcp_failover_state_remove(omapi_object_t *, omapi_object_t *)
int evaluate_option_cache(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
isc_result_t dhcp_failover_set_state(dhcp_failover_state_t *, enum failover_state)
isc_result_t omapi_get_value_str(omapi_object_t *, omapi_object_t *, const char *, omapi_value_t **)
isc_result_t omapi_connection_require(omapi_object_t *, unsigned)
isc_result_t dhcp_failover_process_bind_ack(dhcp_failover_state_t *, failover_message_t *)
isc_result_t dhcp_failover_state_set_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *)
#define DHCPD_FAILOVER_POOL_DOBALANCE_START()
void dhcp_failover_pool_rebalance(void *)
isc_result_t dhcp_failover_generate_update_queue(dhcp_failover_state_t *, int)
binding_state_t binding_state
isc_result_t dhcp_failover_put_message(dhcp_failover_link_t *, omapi_object_t *, int, u_int32_t,...)
isc_result_t dhcp_failover_state_get_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **)
void dhcp_failover_listener_restart(void *)
isc_result_t dhcp_failover_process_update_request_all(dhcp_failover_state_t *, failover_message_t *)
isc_result_t dhcp_failover_send_disconnect(omapi_object_t *, int, const char *)
isc_result_t dhcp_failover_peer_state_changed(dhcp_failover_state_t *, failover_message_t *)
int write_lease(struct lease *lease)
void putULong(unsigned char *, u_int32_t)
isc_result_t dhcp_failover_process_update_request(dhcp_failover_state_t *, failover_message_t *)
isc_result_t omapi_object_dereference(omapi_object_t **, const char *, int)
void commit_leases_timeout(void *)
isc_result_t omapi_signal(omapi_object_t *, const char *,...)
int dhcp_failover_queue_ack(dhcp_failover_state_t *, failover_message_t *msg)
isc_result_t dhcp_failover_link_signal(omapi_object_t *, const char *, va_list)
void(* tvref_t)(void *, void *, const char *, int)
const char * dhcp_failover_state_name_print(enum failover_state)
isc_result_t omapi_get_int_value(unsigned long *, omapi_typed_data_t *)
binding_state_t normal_binding_state_transition_check(struct lease *, dhcp_failover_state_t *, binding_state_t, u_int32_t)
void dfree(void *, const char *, int)
isc_result_t dhcp_failover_link_stuff_values(omapi_object_t *, omapi_object_t *, omapi_object_t *)
isc_result_t omapi_handle_td_lookup(omapi_object_t **, omapi_typed_data_t *)
dhcp_failover_state_t * failover_states
int load_balance_mine(struct packet *, dhcp_failover_state_t *)
isc_result_t omapi_connection_get_uint32(omapi_object_t *, u_int32_t *)
isc_result_t omapi_addr_list_dereference(omapi_addr_list_t **, const char *, int)
void dhcp_failover_link_startup_timeout(void *)
struct option_cache * lookup_option(struct universe *universe, struct option_state *options, unsigned code)
#define DHCPD_FAILOVER_SET_STATE_START(arg1, arg2)
int 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(* tvunref_t)(void *, const char *, int)
void dhcp_failover_reconnect(void *)
isc_result_t omapi_listen(omapi_object_t *, unsigned, int)
void dhcp_failover_startup(void)
isc_result_t omapi_value_dereference(omapi_value_t **, const char *, int)
isc_result_t dhcp_failover_send_update_done(dhcp_failover_state_t *)
isc_result_t ddns_removals(struct lease *, struct iasubopt *, struct dhcp_ddns_cb *, isc_boolean_t)
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)