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,
56 dhcp_failover_state_t *state;
63 if (state -> pool_count == 0) {
64 log_error (
"failover peer declaration with no %s",
66 log_error (
"In order to use failover, you MUST %s",
67 "refer to your main failover declaration");
68 log_error (
"in each pool declaration. You MUST %s",
69 "NOT use range declarations outside");
76 #if defined (DEBUG_FAILOVER_TIMING) 77 log_info (
"add_timeout +90 dhcp_failover_reconnect");
84 dhcp_failover_state_reference,
86 dhcp_failover_state_dereference);
87 log_error (
"failover peer %s: %s", state -> name,
88 isc_result_totext (status));
93 if (status != ISC_R_SUCCESS) {
94 #if defined (DEBUG_FAILOVER_TIMING) 96 "dhcp_failover_listener_restart");
111 dhcp_failover_state_t *state;
121 dhcp_failover_state_t *peer;
123 dhcp_failover_state_t *dup = (dhcp_failover_state_t *)0;
127 if (status == ISC_R_NOTFOUND) {
129 dhcp_failover_state_reference (&peer -> next,
135 return ISC_R_SUCCESS;
137 dhcp_failover_state_dereference (&dup,
MDL);
138 if (status == ISC_R_SUCCESS)
144 dhcp_failover_state_t **peer;
149 dhcp_failover_state_t *p;
152 if (!strcmp (name, p -> name))
155 return dhcp_failover_state_reference (peer, p, file, line);
156 return ISC_R_NOTFOUND;
178 dhcp_failover_link_t *obj;
179 dhcp_failover_state_t *state;
187 for (o = h; o -> outer; o = o -> outer)
189 for (; o; o = o -> inner) {
195 state = (dhcp_failover_state_t *)o;
197 obj = (dhcp_failover_link_t *)0;
198 status = dhcp_failover_link_allocate (&obj,
MDL);
199 if (status != ISC_R_SUCCESS)
202 state -> partner.address,
MDL);
203 obj -> peer_port = state -> partner.port;
204 dhcp_failover_state_reference (&obj -> state_object, state,
MDL);
206 memset (&ds, 0,
sizeof ds);
212 dhcp_failover_link_dereference (&obj,
MDL);
213 return ISC_R_UNEXPECTED;
219 if (status != ISC_R_SUCCESS) {
220 dhcp_failover_link_dereference (&obj,
MDL);
224 for (i = 0; i < addrs -> count; i++) {
225 addrs -> addresses [i].addrtype = AF_INET;
226 addrs -> addresses [i].addrlen =
sizeof (
struct in_addr);
227 memcpy (addrs -> addresses [i].address,
228 &ds.data [i * 4], sizeof (
struct in_addr));
229 addrs -> addresses [i].port = obj -> peer_port;
234 if (!state -> me.address ||
242 memset (&local_addr, 0,
sizeof local_addr);
244 local_addr.
addrlen =
sizeof (
struct in_addr);
246 log_fatal (
"failover peer %s: no local address.",
250 if (ds.len != sizeof (
struct in_addr)) {
251 log_error(
"failover peer %s: 'address' parameter " 252 "fails to resolve to an IPv4 address",
255 dhcp_failover_link_dereference (&obj,
MDL);
261 memcpy (local_addr.
address, ds.data, ds.len);
273 dhcp_failover_link_dereference (&obj,
MDL);
278 const char *name, va_list ap)
281 dhcp_failover_link_t *link;
283 dhcp_failover_state_t *s, *state = (dhcp_failover_state_t *)0;
290 return ISC_R_UNEXPECTED;
292 link = (dhcp_failover_link_t *)h;
294 if (!strcmp (name,
"connect")) {
295 if (link -> state_object -> i_am == primary) {
297 if (status != ISC_R_SUCCESS) {
298 log_info (
"dhcp_failover_send_connect: %s",
299 isc_result_totext (status));
303 status = ISC_R_SUCCESS;
306 #if defined (DEBUG_FAILOVER_TIMING) 308 "dhcp_failover_link_startup_timeout");
315 (
tvref_t)dhcp_failover_link_reference,
316 (
tvunref_t)dhcp_failover_link_dereference);
320 if (!strcmp (name,
"disconnect")) {
321 if (link -> state_object) {
322 dhcp_failover_state_reference (&state,
323 link -> state_object,
MDL);
324 link -> state = dhcp_flink_disconnected;
327 if (state->link_to_peer == link)
331 #if defined (DEBUG_FAILOVER_TIMING) 332 log_info(
"add_timeout +5 dhcp_failover_reconnect");
335 tv.tv_usec =
cur_tv.tv_usec;
337 (
tvref_t)dhcp_failover_state_reference,
338 (
tvunref_t)dhcp_failover_state_dereference);
340 dhcp_failover_state_dereference (&state,
MDL);
342 return ISC_R_SUCCESS;
345 if (!strcmp (name,
"status")) {
346 if (link -> state_object) {
349 status = va_arg(ap, isc_result_t);
351 if ((status == ISC_R_HOSTUNREACH) || (status == ISC_R_TIMEDOUT)) {
352 dhcp_failover_state_reference (&state,
353 link -> state_object,
MDL);
354 link -> state = dhcp_flink_disconnected;
361 #if defined (DEBUG_FAILOVER_TIMING) 363 "dhcp_failover_reconnect");
369 (
tvref_t)dhcp_failover_state_reference,
370 (
tvunref_t)dhcp_failover_state_dereference);
372 dhcp_failover_state_dereference (&state,
MDL);
374 return ISC_R_SUCCESS;
378 if (strcmp (name,
"ready")) {
379 if (h -> inner && h -> inner -> type -> signal_handler)
380 return (*(h -> inner -> type -> signal_handler))
381 (h -> inner, name, ap);
382 return ISC_R_NOTFOUND;
392 switch (link -> state) {
393 case dhcp_flink_start:
394 link -> state = dhcp_flink_message_length_wait;
397 case dhcp_flink_message_length_wait:
399 link -> state = dhcp_flink_message_wait;
400 link -> imsg =
dmalloc (
sizeof (failover_message_t),
MDL);
402 status = ISC_R_NOMEMORY;
405 failover_message_dereference (&link->imsg,
408 link -> state = dhcp_flink_disconnected;
409 log_info (
"message length wait: %s",
410 isc_result_totext (status));
414 return ISC_R_UNEXPECTED;
416 memset (link -> imsg, 0,
sizeof (failover_message_t));
417 link -> imsg -> refcnt = 1;
420 link -> imsg_count = 0;
423 if (link->imsg_len < DHCP_FAILOVER_MIN_MESSAGE_SIZE ||
424 link->imsg_len > DHCP_FAILOVER_MAX_MESSAGE_SIZE) {
425 status = ISC_R_UNEXPECTED;
426 goto dhcp_flink_fail;
432 case dhcp_flink_message_wait:
442 link -> imsg_count += 2;
446 link -> imsg_count++;
450 link -> imsg_count++;
454 link -> imsg_count += 4;
458 link -> imsg_count += 4;
460 #if defined (DEBUG_FAILOVER_MESSAGES) 461 # if !defined(DEBUG_FAILOVER_CONTACT_MESSAGES) 462 if (link->imsg->type == FTM_CONTACT)
465 log_info (
"link: message %s payoff %d time %ld xid %ld",
468 (
unsigned long)link -> imsg -> time,
469 (
unsigned long)link -> imsg -> xid);
470 # if !defined(DEBUG_FAILOVER_CONTACT_MESSAGES) 476 if (link -> imsg_payoff - link -> imsg_count) {
478 (link -> imsg_payoff -
479 link -> imsg_count));
480 link -> imsg_count = link -> imsg_payoff;
484 while (link -> imsg_count < link -> imsg_len) {
485 status = do_a_failover_option (c, link);
486 if (status != ISC_R_SUCCESS)
487 goto dhcp_flink_fail;
493 if (link -> imsg -> type == FTM_CONNECT) {
497 if (!(link->imsg->options_present &
498 FTB_RELATIONSHIP_NAME)) {
499 errmsg =
"missing relationship-name";
500 reason = FTR_INVALID_PARTNER;
509 &link->imsg->relationship_name))
516 errmsg =
"unknown failover relationship name";
517 reason = FTR_INVALID_PARTNER;
525 slen = strlen(sname);
526 }
else if (link->imsg->options_present &
527 FTB_RELATIONSHIP_NAME) {
528 sname = (
char *)link->imsg->
529 relationship_name.data;
530 slen = link->imsg->relationship_name.count;
533 slen = strlen(sname);
536 log_error(
"Failover CONNECT from %.*s: %s",
537 slen, sname, errmsg);
541 log_info (
"failover: disconnect: %s", errmsg);
543 link -> state = dhcp_flink_disconnected;
544 return ISC_R_SUCCESS;
547 if ((
cur_time > link -> imsg -> time &&
548 cur_time - link -> imsg -> time > 60) ||
549 (cur_time < link -> imsg -> time &&
550 link -> imsg -> time -
cur_time > 60)) {
551 errmsg =
"time offset too large";
552 reason = FTR_TIMEMISMATCH;
556 if (!(link -> imsg -> options_present & FTB_HBA) ||
557 link -> imsg -> hba.count != 32) {
558 errmsg =
"invalid HBA";
559 reason = FTR_HBA_CONFLICT;
566 errmsg =
"no memory";
567 reason = FTR_MISC_REJECT;
570 memcpy (state -> hba, link -> imsg -> hba.data, 32);
572 if (!link -> state_object)
573 dhcp_failover_state_reference
574 (&link -> state_object, state,
MDL);
575 if (!link -> peer_address)
577 (&link -> peer_address,
578 state -> partner.address,
MDL);
584 if (!link -> state_object) {
585 log_info (
"failover: connect: no matching state.");
587 link -> state = dhcp_flink_disconnected;
595 link -> state = dhcp_flink_message_length_wait;
597 failover_message_dereference (&link -> imsg,
MDL);
611 return ISC_R_SUCCESS;
614 static isc_result_t do_a_failover_option (c, link)
616 dhcp_failover_link_t *link;
618 u_int16_t option_code;
619 u_int16_t option_len;
625 if (link -> imsg_count + 2 > link -> imsg_len) {
626 log_error (
"FAILOVER: message overflow at option code.");
630 if (link->imsg->type > FTM_MAX) {
631 log_error (
"FAILOVER: invalid message type: %d",
638 link -> imsg_count += 2;
640 if (link -> imsg_count + 2 > link -> imsg_len) {
641 log_error (
"FAILOVER: message overflow at length.");
647 link -> imsg_count += 2;
649 if (link -> imsg_count + option_len > link -> imsg_len) {
650 log_error (
"FAILOVER: message overflow at data.");
655 if ((option_code > FTO_MAX) ||
657 #if defined (DEBUG_FAILOVER_MESSAGES) 658 log_debug (
" option code %d (%s) len %d (not recognized)",
664 link -> imsg_count += option_len;
665 return ISC_R_SUCCESS;
669 if (
ft_options [option_code].type == FT_DIGEST) {
670 link -> imsg_count += option_len;
671 if (link -> imsg_count != link -> imsg_len) {
672 log_error (
"FAILOVER: digest not at end of message");
675 #if defined (DEBUG_FAILOVER_MESSAGES) 681 return ISC_R_SUCCESS;
685 if (link -> imsg -> options_present &
ft_options [option_code].bit) {
686 log_error (
"FAILOVER: duplicate option %s",
701 link -> imsg_count += option_len;
702 return ISC_R_SUCCESS;
712 op = ((
unsigned char *)link -> imsg) +
715 op_count = ft_options [option_code].num_present;
717 if (option_len != op_size * op_count) {
718 log_error (
"FAILOVER: option size (%d:%d), option %s",
720 (
ft_sizes [ft_options [option_code].type] *
721 ft_options [option_code].num_present),
722 ft_options [option_code].name);
726 failover_option_t *fo;
733 if (ft_options [option_code].type == FT_DDNS ||
734 ft_options [option_code].type == FT_DDNS1) {
737 (((
char *)link -> imsg) +
738 ft_options [option_code].offset));
740 op_count = (ft_options [option_code].type == FT_DDNS1
745 link -> imsg_count += op_count;
747 ddns -> codes [1] = 0;
749 op_count = option_len - op_count;
751 ddns -> length = op_count;
754 log_error (
"FAILOVER: no memory getting%s(%d)",
755 " DNS data ", op_count);
770 op_size =
ft_sizes [ft_options [option_code].type];
774 if (op_size > 1 && option_len % op_size) {
775 log_error (
"FAILOVER: option_len %d not %s%d",
776 option_len,
"multiple of ", op_size);
780 op_count = option_len / op_size;
782 fo = ((failover_option_t *)
783 (((
char *)link -> imsg) +
784 ft_options [option_code].offset));
786 fo -> count = op_count;
789 log_error (
"FAILOVER: no memory getting %s (%d)",
790 "option data", op_count);
799 if (op_size == 1 || ft_options [option_code].type == FT_IPADDR) {
801 link -> imsg_count += option_len;
824 if ((option_code == 11) && (option_len > 9) &&
825 (strncmp((
const char *)op,
"isc-V3.0.", 9) == 0)) {
826 log_error(
"WARNING: failover as of versions 3.1.0 and " 827 "on are not reverse compatible with " 836 for (i = 0; i < op_count; i++) {
837 switch (ft_options [option_code].type) {
841 link -> imsg_count += 4;
847 link -> imsg_count += 2;
853 log_error (
"FAILOVER: option %s: bad type %d",
854 ft_options [option_code].name,
855 ft_options [option_code].type);
861 link -> imsg -> options_present |= ft_options [option_code].bit;
862 return ISC_R_SUCCESS;
879 if (h -> inner && h -> inner -> type -> set_value)
880 return (*(h -> inner -> type -> set_value))
881 (h -> inner, id, name, value);
882 return ISC_R_NOTFOUND;
890 dhcp_failover_link_t *link;
894 link = (dhcp_failover_link_t *)h;
898 (
int)link -> peer_port,
MDL);
900 if (link -> state >= dhcp_flink_state_max)
902 "invalid link state",
909 if (h -> inner && h -> inner -> type -> get_value)
910 return (*(h -> inner -> type -> get_value))
911 (h -> inner, id, name, value);
912 return ISC_R_NOTFOUND;
916 const char *file,
int line)
918 dhcp_failover_link_t *link;
921 link = (dhcp_failover_link_t *)h;
923 if (link -> peer_address)
926 failover_message_dereference (&link -> imsg, file, line);
927 if (link -> state_object)
928 dhcp_failover_state_dereference (&link -> state_object,
930 return ISC_R_SUCCESS;
940 dhcp_failover_link_t *link;
945 link = (dhcp_failover_link_t *)l;
948 if (status != ISC_R_SUCCESS)
951 if (status != ISC_R_SUCCESS)
954 if (status != ISC_R_SUCCESS)
958 if (status != ISC_R_SUCCESS)
960 if (link -> state >= dhcp_flink_state_max)
965 if (status != ISC_R_SUCCESS)
968 if (link -> inner && link -> inner -> type -> stuff_values)
969 return (*(link -> inner -> type -> stuff_values)) (c,
id,
971 return ISC_R_SUCCESS;
986 "local-port", &value);
987 if (status != ISC_R_SUCCESS)
989 if (!value -> value) {
996 if (status != ISC_R_SUCCESS)
998 local_addr.
port = port;
1001 "local-address", &value);
1002 if (status != ISC_R_SUCCESS)
1004 if (!value -> value) {
1011 value -> value -> u.buffer.len != sizeof (
struct in_addr))
1014 memcpy (local_addr.
address, value -> value -> u.buffer.
value,
1015 value -> value -> u.buffer.len);
1016 local_addr.
addrlen = value -> value -> u.buffer.len;
1022 for (l = failover_listeners; l; l = l -> next) {
1023 if (l -> address.port == local_addr.
port &&
1024 l -> address.addrtype == local_addr.
addrtype &&
1025 l -> address.addrlen == local_addr.
addrlen &&
1026 !memcmp (l -> address.address, local_addr.
address,
1032 return ISC_R_SUCCESS;
1035 status = dhcp_failover_listener_allocate (&obj,
MDL);
1036 if (status != ISC_R_SUCCESS)
1038 obj -> address = local_addr;
1041 if (status != ISC_R_SUCCESS)
1046 if (status != ISC_R_SUCCESS) {
1047 dhcp_failover_listener_dereference (&obj,
MDL);
1051 if (status != ISC_R_SUCCESS) {
1052 dhcp_failover_listener_dereference (&obj,
MDL);
1057 if (failover_listeners) {
1058 dhcp_failover_listener_reference (&obj -> next,
1059 failover_listeners,
MDL);
1060 dhcp_failover_listener_dereference (&failover_listeners,
MDL);
1062 dhcp_failover_listener_reference (&failover_listeners, obj,
MDL);
1064 return dhcp_failover_listener_dereference (&obj,
MDL);
1071 const char *name, va_list ap)
1073 isc_result_t status;
1075 dhcp_failover_link_t *obj;
1077 dhcp_failover_state_t *s, *state = (dhcp_failover_state_t *)0;
1084 if (strcmp (name,
"connect")) {
1085 if (p -> inner && p -> inner -> type -> signal_handler)
1086 return (*(p -> inner -> type -> signal_handler))
1087 (p -> inner, name, ap);
1088 return ISC_R_NOTFOUND;
1099 (s, (u_int8_t *)&c -> remote_addr.sin_addr,
1100 sizeof c -> remote_addr.sin_addr)) {
1106 log_info (
"failover: listener: no matching state");
1108 return(ISC_R_NOTFOUND);
1111 obj = (dhcp_failover_link_t *)0;
1112 status = dhcp_failover_link_allocate (&obj,
MDL);
1113 if (status != ISC_R_SUCCESS)
1115 obj -> peer_port = ntohs (c -> remote_addr.sin_port);
1119 if (status != ISC_R_SUCCESS) {
1121 dhcp_failover_link_dereference (&obj,
MDL);
1122 log_info (
"failover: listener: picayune failure.");
1129 if (status != ISC_R_SUCCESS)
1132 status = dhcp_failover_state_reference (&obj -> state_object,
1134 if (status != ISC_R_SUCCESS)
1139 return dhcp_failover_link_dereference (&obj,
MDL);
1150 if (h -> inner && h -> inner -> type -> set_value)
1151 return (*(h -> inner -> type -> set_value))
1152 (h -> inner, id, name, value);
1153 return ISC_R_NOTFOUND;
1164 if (h -> inner && h -> inner -> type -> get_value)
1165 return (*(h -> inner -> type -> get_value))
1166 (h -> inner, id, name, value);
1167 return ISC_R_NOTFOUND;
1171 const char *file,
int line)
1179 dhcp_failover_listener_dereference (&l -> next, file, line);
1181 return ISC_R_SUCCESS;
1194 if (p -> inner && p -> inner -> type -> stuff_values)
1195 return (*(p -> inner -> type -> stuff_values)) (c, id,
1197 return ISC_R_SUCCESS;
1204 isc_result_t status;
1205 dhcp_failover_state_t *obj;
1210 "local-port", &value);
1211 if (status != ISC_R_SUCCESS)
1213 if (!value -> value) {
1220 if (status != ISC_R_SUCCESS)
1223 obj = (dhcp_failover_state_t *)0;
1224 dhcp_failover_state_allocate (&obj,
MDL);
1225 obj -> me.port = port;
1228 if (status != ISC_R_SUCCESS) {
1229 dhcp_failover_state_dereference (&obj,
MDL);
1235 if (status != ISC_R_SUCCESS) {
1236 dhcp_failover_state_dereference (&obj,
MDL);
1240 dhcp_failover_state_dereference (&obj,
MDL);
1247 const char *name, va_list ap)
1249 isc_result_t status;
1250 dhcp_failover_state_t *state;
1251 dhcp_failover_link_t *link;
1256 state = (dhcp_failover_state_t *)o;
1259 if (strcmp (name,
"disconnect") &&
1260 strcmp (name,
"message")) {
1261 if (state -> inner && state -> inner -> type -> signal_handler)
1262 return (*(state -> inner -> type -> signal_handler))
1263 (state -> inner, name, ap);
1264 return ISC_R_NOTFOUND;
1269 if (!strcmp (name,
"disconnect")) {
1270 link = va_arg (ap, dhcp_failover_link_t *);
1272 dhcp_failover_link_dereference (&state -> link_to_peer,
MDL);
1274 if (state -> i_am == primary) {
1275 #if defined (DEBUG_FAILOVER_TIMING) 1277 "dhcp_failover_reconnect");
1283 (
tvref_t)dhcp_failover_state_reference,
1285 dhcp_failover_state_dereference);
1287 }
else if (!strcmp (name,
"message")) {
1288 link = va_arg (ap, dhcp_failover_link_t *);
1290 if (link -> imsg -> type == FTM_CONNECT) {
1296 if (state -> link_to_peer) {
1300 "already connected");
1302 return ISC_R_SUCCESS;
1304 if (!(link -> imsg -> options_present & FTB_MCLT)) {
1308 "no MCLT provided");
1310 return ISC_R_SUCCESS;
1313 dhcp_failover_link_reference (&state -> link_to_peer,
1317 if (status != ISC_R_SUCCESS) {
1318 dhcp_failover_link_dereference
1319 (&state -> link_to_peer,
MDL);
1320 log_info (
"dhcp_failover_send_connectack: %s",
1321 isc_result_totext (status));
1323 return ISC_R_SUCCESS;
1325 if (link -> imsg -> options_present & FTB_MAX_UNACKED)
1326 state -> partner.max_flying_updates =
1327 link -> imsg -> max_unacked;
1328 if (link -> imsg -> options_present & FTB_RECEIVE_TIMER)
1329 state -> partner.max_response_delay =
1330 link -> imsg -> receive_timer;
1331 state -> mclt = link -> imsg -> mclt;
1335 }
else if (link -> imsg -> type == FTM_CONNECTACK) {
1343 if (!(link->imsg->options_present &
1344 FTB_RELATIONSHIP_NAME)) {
1345 errmsg =
"missing relationship-name";
1346 reason = FTR_INVALID_PARTNER;
1350 if (link->imsg->options_present & FTB_REJECT_REASON) {
1352 log_error (
"Failover CONNECT to %s rejected: %s",
1353 state ? state->name :
"unknown",
1355 (link -> imsg -> reject_reason)));
1358 return ISC_R_SUCCESS;
1362 &link->imsg->relationship_name)) {
1364 snprintf(errbuf,
sizeof(errbuf),
"remote failover " 1365 "relationship name %.*s does not match",
1366 (
int)link->imsg->relationship_name.count,
1367 link->imsg->relationship_name.data);
1369 reason = FTR_INVALID_PARTNER;
1371 log_error(
"Failover CONNECTACK from %s: %s",
1372 state->name, errmsg);
1376 return ISC_R_SUCCESS;
1379 if (state -> link_to_peer) {
1380 errmsg =
"already connected";
1381 reason = FTR_DUP_CONNECTION;
1385 if ((
cur_time > link -> imsg -> time &&
1386 cur_time - link -> imsg -> time > 60) ||
1387 (cur_time < link -> imsg -> time &&
1388 link -> imsg -> time -
cur_time > 60)) {
1389 errmsg =
"time offset too large";
1390 reason = FTR_TIMEMISMATCH;
1394 dhcp_failover_link_reference (&state -> link_to_peer,
1401 if (state -> me.state ==
startup)
1403 state -> saved_state);
1408 if (link -> imsg -> options_present & FTB_MAX_UNACKED)
1409 state -> partner.max_flying_updates =
1410 link -> imsg -> max_unacked;
1411 if (link -> imsg -> options_present & FTB_RECEIVE_TIMER)
1412 state -> partner.max_response_delay =
1413 link -> imsg -> receive_timer;
1414 #if defined (DEBUG_FAILOVER_CONTACT_TIMING) 1416 (
int)state -> partner.max_response_delay / 3,
1417 "dhcp_failover_send_contact");
1420 (
int)state -> partner.max_response_delay / 3;
1424 (
tvref_t)dhcp_failover_state_reference,
1425 (
tvunref_t)dhcp_failover_state_dereference);
1426 #if defined (DEBUG_FAILOVER_CONTACT_TIMING) 1428 (
int)state -> me.max_response_delay,
1429 "dhcp_failover_timeout");
1432 (
int)state -> me.max_response_delay;
1436 (
tvref_t)dhcp_failover_state_reference,
1437 (
tvunref_t)dhcp_failover_state_dereference);
1438 }
else if (link -> imsg -> type == FTM_DISCONNECT) {
1439 if (link -> imsg -> reject_reason) {
1440 log_error (
"Failover DISCONNECT from %s: %s",
1441 state ? state->name :
"unknown",
1443 (link -> imsg -> reject_reason)));
1446 }
else if (link -> imsg -> type == FTM_BNDUPD) {
1449 }
else if (link -> imsg -> type == FTM_BNDACK) {
1451 }
else if (link -> imsg -> type == FTM_UPDREQ) {
1454 }
else if (link -> imsg -> type == FTM_UPDREQALL) {
1456 (state, link -> imsg);
1457 }
else if (link -> imsg -> type == FTM_UPDDONE) {
1460 }
else if (link -> imsg -> type == FTM_POOLREQ) {
1461 dhcp_failover_pool_reqbalance(state);
1462 }
else if (link -> imsg -> type == FTM_POOLRESP) {
1463 log_info (
"pool response: %ld leases",
1465 link -> imsg -> addresses_transferred);
1466 }
else if (link -> imsg -> type == FTM_STATE) {
1475 if (state -> link_to_peer &&
1476 state -> link_to_peer == link &&
1477 state -> link_to_peer -> state != dhcp_flink_disconnected)
1479 #if defined (DEBUG_FAILOVER_CONTACT_TIMING) 1481 (
int)state -> me.max_response_delay,
1482 "dhcp_failover_timeout");
1485 (
int)state -> me.max_response_delay;
1489 (
tvref_t)dhcp_failover_state_reference,
1490 (
tvunref_t)dhcp_failover_state_dereference);
1496 return ISC_R_SUCCESS;
1502 isc_result_t status;
1505 if (!strcmp (name,
"disconnect")) {
1506 if (state -> link_to_peer) {
1507 log_info (
"peer %s: disconnected", state -> name);
1508 if (state -> link_to_peer -> state_object)
1509 dhcp_failover_state_dereference
1510 (&state -> link_to_peer -> state_object,
MDL);
1511 dhcp_failover_link_dereference (&state -> link_to_peer,
1518 switch (state -> me.state ==
startup ?
1519 state -> saved_state : state -> me.state) {
1541 if (state -> me.state ==
startup)
1543 (state, state -> saved_state));
1544 return ISC_R_SUCCESS;
1562 }
else if (!strcmp (name,
"connect")) {
1563 switch (state -> me.state) {
1590 }
else if (!strcmp (name,
"startup")) {
1592 return ISC_R_SUCCESS;
1593 }
else if (!strcmp (name,
"connect-timeout")) {
1594 switch (state -> me.state) {
1602 return ISC_R_SUCCESS;
1626 switch (state -> me.state) {
1629 state -> nrr =
" (my state unknown)";
1651 state -> nrr =
" (resolving conflicts)";
1656 state -> nrr =
" (recovering)";
1661 state -> nrr =
" (shut down)";
1666 state -> nrr =
" (paused)";
1671 state -> nrr =
" (recover wait)";
1676 state -> nrr =
" (recover done)";
1681 state -> nrr =
" (startup)";
1693 switch (state -> partner.state) {
1696 state -> nrr =
" (peer demands: recovering)";
1703 state -> nrr =
" (peer demands: resolving conflicts)";
1712 return ISC_R_SUCCESS;
1731 if (state->ack_queue_tail == NULL)
1735 for (lp = state->ack_queue_head; lp; lp = lp->
next_pending)
1739 if (state->update_queue_head) {
1740 lease_reference(&state->ack_queue_tail->next_pending,
1741 state->update_queue_head,
MDL);
1742 lease_dereference(&state->update_queue_head,
MDL);
1744 lease_reference(&state->update_queue_head, state->ack_queue_head,
MDL);
1746 if (!state->update_queue_tail) {
1747 #if defined (POINTER_DEBUG) 1748 if (state->ack_queue_tail->next_pending) {
1749 log_error(
"next pending on ack queue tail.");
1753 lease_reference(&state->update_queue_tail,
1754 state->ack_queue_tail,
MDL);
1756 lease_dereference(&state->ack_queue_tail,
MDL);
1757 lease_dereference(&state->ack_queue_head,
MDL);
1758 state->cur_unacked_updates = 0;
1775 switch (state -> me.state) {
1791 saved_state = state -> me.state;
1792 saved_stos = state -> me.stos;
1807 !state -> update_queue_head && !state -> ack_queue_head)
1808 state -> me.stos =
cur_time - state -> mclt;
1810 state -> me.state = new_state;
1812 state -> saved_state = saved_state;
1816 log_error (
"Unable to record current failover state for %s",
1818 state -> me.state = saved_state;
1819 state -> me.stos = saved_stos;
1820 return ISC_R_IOERROR;
1823 log_info (
"failover peer %s: I move from %s to %s",
1828 if ((state->me.state ==
normal) && (state->partner.state ==
normal))
1829 log_info(
"failover peer %s: Both servers normal", state->name);
1845 if (state -> link_to_peer)
1848 switch (new_state) {
1858 if (state->auto_partner_down == 0)
1861 #if defined (DEBUG_FAILOVER_TIMING) 1862 log_info(
"add_timeout +%lu dhcp_failover_auto_partner_down",
1863 (
unsigned long)state->auto_partner_down);
1865 tv.tv_sec =
cur_time + state->auto_partner_down;
1878 dhcp_failover_pool_balance(state);
1881 if (state->update_queue_tail != NULL) {
1883 log_info(
"Sending updates to %s.", state->name);
1889 if ((state->i_am == primary) ||
1890 ((state->i_am == secondary) &&
1896 #if defined (DEBUG_FAILOVER_TIMING) 1898 "dhcp_failover_startup_timeout");
1905 (
tvref_t)omapi_object_reference,
1913 if (state -> me.stos + state -> mclt >
cur_time) {
1914 #if defined (DEBUG_FAILOVER_TIMING) 1917 state -> me.stos + state -> mclt),
1918 "dhcp_failover_startup_timeout");
1920 tv . tv_sec = (
int)(state -> me.stos + state -> mclt);
1925 (
tvref_t)omapi_object_reference,
1937 if (state -> link_to_peer)
1945 #if defined (BINARY_LEASES) 1946 long int tiebreaker = 0;
1952 l->
tsfp = state->me.stos + state->mclt;
1960 if (tiebreaker != LONG_MAX)
1970 #if defined (DEBUG_FAILOVER_TIMING) 1990 return ISC_R_SUCCESS;
1994 failover_message_t *msg)
2000 new_state = msg -> server_state;
2001 startupp = (msg -> server_flags & FTF_SERVER_STARTUP) ? 1 : 0;
2003 if (state -> partner.state == new_state && state -> me.state) {
2004 switch (state -> me.state) {
2017 state->saved_state);
2018 return ISC_R_SUCCESS;
2027 return ISC_R_SUCCESS;
2044 state -> partner.state = new_state;
2047 log_info (
"failover peer %s: peer moves from %s to %s",
2053 if ((state->me.state ==
normal) && (state->partner.state ==
normal))
2054 log_info(
"failover peer %s: Both servers normal", state->name);
2060 log_error (
"Unable to record current failover state for %s",
2067 switch (new_state) {
2084 log_error(
"failover peer %s: Invalid state: %d", state->name,
2087 return ISC_R_SUCCESS;
2093 switch (state -> me.state ==
startup ?
2094 state -> saved_state : state -> me.state) {
2096 switch (new_state) {
2102 if (state -> me.state ==
startup)
2113 log_error(
"Peer %s: Invalid state transition %s " 2114 "to %s.", state->name,
2139 switch (new_state) {
2141 log_info (
"failover peer %s: requesting %s",
2142 state -> name,
"full update from peer");
2146 if (state -> me.state ==
recover)
2172 if (state -> me.state ==
recover)
2193 switch (new_state) {
2196 log_error(
"Peer %s moves to normal during conflict " 2197 "resolution - panic, shutting down.",
2206 log_error(
"Peer %s: Unexpected move to " 2207 "conflict-done.", state->name);
2234 switch (new_state) {
2252 log_fatal(
"Peer %s: Invalid attempt to move from %s " 2253 "to %s while local state is conflict-done.",
2265 switch (new_state) {
2291 switch (new_state) {
2331 switch (new_state) {
2359 switch (new_state) {
2361 log_error(
"Both servers have entered recover-done!");
2402 if (state -> me.state ==
startup && state -> saved_state !=
startup)
2409 return ISC_R_SUCCESS;
2418 dhcp_failover_pool_balance(dhcp_failover_state_t *state)
2422 state->sched_balance = 0;
2424 dhcp_failover_pool_dobalance(state, NULL);
2435 dhcp_failover_state_t *state;
2436 isc_boolean_t sendreq = ISC_FALSE;
2438 state = (dhcp_failover_state_t *)failover_state;
2441 state->sched_balance = 0;
2443 if (dhcp_failover_pool_dobalance(state, &sendreq))
2455 dhcp_failover_pool_reqbalance(dhcp_failover_state_t *state)
2461 state->sched_balance = 0;
2463 queued = dhcp_failover_pool_dobalance(state, NULL);
2470 log_info(
"peer %s: Got POOLREQ, answering negatively! " 2471 "Peer may be out of leases or database inconsistent.",
2483 dhcp_failover_pool_dobalance(dhcp_failover_state_t *state,
2484 isc_boolean_t *sendreq)
2486 int lts, total, thresh, hold, panic, pass;
2487 int leases_queued = 0;
2488 struct lease *lp = NULL;
2490 struct lease *ltemp = NULL;
2497 int (*log_func)(
const char *, ...);
2498 const char *result, *reqlog;
2500 if (state -> me.state !=
normal)
2530 thresh = ((total * state->max_lease_misbalance) + 50) / 100;
2531 hold = ((total * state->max_lease_ownership) + 50) / 100;
2546 panic = thresh * -2;
2551 if ((sendreq != NULL) && (lts < panic)) {
2552 reqlog =
" (requesting peer rebalance!)";
2553 *sendreq = ISC_TRUE;
2557 log_info(
"balancing pool %lx %s total %d free %d " 2558 "backup %d lts %d max-own (+/-)%d%s",
2560 (p->shared_network ?
2562 p->free_leases, p->backup_leases, lts, hold,
2582 lease_dereference(&next,
MDL);
2585 lease_reference(&next, ltemp,
MDL);
2612 }
else if (lts <= -hold)
2629 lease_dereference(&lp,
MDL);
2631 lease_reference(&lp, next,
MDL);
2639 lease_dereference(&next,
MDL);
2641 lease_dereference(&lp,
MDL);
2644 result =
"IMBALANCED";
2647 result =
"balanced";
2651 log_func(
"%s pool %lx %s total %d free %d backup %d " 2652 "lts %d max-misbal %d", result, (
unsigned long)p,
2653 (p->shared_network ?
2654 p->shared_network->name :
""), p->lease_count,
2655 p->free_leases, p->backup_leases, lts, thresh);
2665 return leases_queued;
2675 dhcp_failover_state_t *peer;
2678 struct lease *ltemp;
2682 if(!peer || peer->me.state !=
normal)
2711 est1 = ((est1 * peer->max_lease_misbalance) + 50) / 100;
2712 est2 = ((est2 * peer->max_lease_misbalance) + 50) / 100;
2717 if(peer->i_am == primary)
2727 if(est1 > peer->max_balance)
2728 est1 = peer->max_balance;
2734 est2 = peer->last_balance + peer->min_balance;
2735 if(peer->last_balance && (est1 < est2))
2739 est1 += random() % 5;
2742 if(peer->sched_balance) {
2743 if (est1 >= peer->sched_balance)
2753 peer->sched_balance = est1;
2755 #if defined(DEBUG_FAILOVER_TIMING) 2756 log_info(
"add_timeout +%d dhcp_failover_pool_rebalance",
2762 (
tvref_t)dhcp_failover_state_reference,
2763 (
tvunref_t)dhcp_failover_state_dereference);
2772 for (p = s ->
pools; p; p = p ->
next) {
2784 isc_result_t status;
2787 if (!state -> link_to_peer)
2788 return ISC_R_SUCCESS;
2793 if (state->toack_queue_head != NULL)
2796 while ((state -> partner.max_flying_updates >
2797 state -> cur_unacked_updates) && state -> update_queue_head) {
2799 lease_reference (&lp, state -> update_queue_head,
MDL);
2803 if (status != ISC_R_SUCCESS) {
2804 lease_dereference (&lp,
MDL);
2811 lease_dereference (&state -> update_queue_head,
MDL);
2813 lease_reference (&state -> update_queue_head,
2817 lease_dereference (&state -> update_queue_tail,
MDL);
2820 if (state -> ack_queue_head) {
2824 lease_dereference (&state -> ack_queue_tail,
MDL);
2826 lease_reference (&state -> ack_queue_head, lp,
MDL);
2828 #if defined (POINTER_DEBUG) 2830 log_error (
"ack_queue_tail: lp -> next_pending");
2834 lease_reference (&state -> ack_queue_tail, lp,
MDL);
2836 lease_dereference (&lp,
MDL);
2839 state -> cur_unacked_updates++;
2841 return ISC_R_SUCCESS;
2850 dhcp_failover_state_t *
state;
2852 if (!lease -> pool ||
2853 !lease -> pool -> failover_peer)
2861 state = lease -> pool -> failover_peer;
2867 if (state -> update_queue_head) {
2868 lease_reference (&state -> update_queue_tail ->
next_pending,
2870 lease_dereference (&state -> update_queue_tail,
MDL);
2872 lease_reference (&state -> update_queue_head, lease,
MDL);
2874 #if defined (POINTER_DEBUG) 2876 log_error (
"next pending on update queue lease.");
2877 #if defined (DEBUG_RC_HISTORY) 2878 dump_rc_history (lease);
2883 lease_reference (&state -> update_queue_tail, lease,
MDL);
2892 failover_message_t *msg = (failover_message_t *)0;
2898 while (state -> toack_queue_head) {
2899 failover_message_reference
2900 (&msg, state -> toack_queue_head,
MDL);
2901 failover_message_dereference
2902 (&state -> toack_queue_head,
MDL);
2904 failover_message_reference
2905 (&state -> toack_queue_head, msg -> next,
MDL);
2910 failover_message_dereference (&msg,
MDL);
2913 if (state -> toack_queue_tail)
2914 failover_message_dereference (&state -> toack_queue_tail,
MDL);
2915 state -> pending_acks = 0;
2922 dhcp_failover_state_t *state = vs;
2924 #if defined (DEBUG_FAILOVER_TIMING) 2925 log_info (
"dhcp_failover_toack_queue_timeout");
2935 failover_message_t *msg)
2939 if (state -> toack_queue_head) {
2940 failover_message_reference
2941 (&state -> toack_queue_tail -> next, msg,
MDL);
2942 failover_message_dereference (&state -> toack_queue_tail,
MDL);
2944 failover_message_reference (&state -> toack_queue_head,
2947 failover_message_reference (&state -> toack_queue_tail, msg,
MDL);
2949 state -> pending_acks++;
2953 if (state -> pending_acks >= state -> partner.max_flying_updates / 2) {
2958 if (state -> pending_acks > 0) {
2959 #if defined (DEBUG_FAILOVER_TIMING) 2961 "dhcp_failover_toack_queue_timeout");
2967 (
tvref_t)dhcp_failover_state_reference,
2968 (
tvunref_t)dhcp_failover_state_dereference);
2975 struct lease *lease)
2979 if (!(lease ->
flags & ON_ACK_QUEUE))
2982 if (state -> ack_queue_head == lease) {
2983 lease_dereference (&state -> ack_queue_head,
MDL);
2985 lease_reference (&state -> ack_queue_head,
2989 lease_dereference (&state -> ack_queue_tail,
MDL);
2992 for (lp = state -> ack_queue_head;
3006 lease_dereference (&state -> ack_queue_tail,
MDL);
3011 lease_reference (&state -> ack_queue_tail, lp,
MDL);
3015 lease ->
flags &= ~ON_ACK_QUEUE;
3022 state -> cur_unacked_updates--;
3029 if (state -> cur_unacked_updates == 0) {
3039 isc_result_t status;
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;
3067 return ISC_R_SUCCESS;
3071 if (status != 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;
3089 return ISC_R_SUCCESS;
3092 if (h -> inner && h -> inner -> type -> set_value)
3093 return (*(h -> inner -> type -> set_value))
3094 (h -> inner, id, name, value);
3095 return ISC_R_NOTFOUND;
3104 dhcp_failover_state_t *state = vs;
3105 isc_result_t status;
3108 #if defined (DEBUG_FAILOVER_TIMING) 3109 log_info (
"dhcp_failover_reconnect");
3113 if (state -> link_to_peer)
3118 log_info (
"failover peer %s: %s", state -> name,
3119 isc_result_totext (status));
3120 #if defined (DEBUG_FAILOVER_TIMING) 3121 log_info(
"add_timeout +90 dhcp_failover_reconnect");
3126 (
tvref_t)dhcp_failover_state_reference,
3127 (
tvunref_t)dhcp_failover_state_dereference);
3133 dhcp_failover_state_t *state = vs;
3135 #if defined (DEBUG_FAILOVER_TIMING) 3136 log_info (
"dhcp_failover_startup_timeout");
3144 dhcp_failover_link_t *link = vl;
3149 for (; p; p = p -> outer)
3153 log_info (
"failover: link startup timeout");
3160 dhcp_failover_state_t *state = vs;
3161 isc_result_t status;
3164 #if defined (DEBUG_FAILOVER_TIMING) 3165 log_info (
"dhcp_failover_listener_restart");
3169 if (status != ISC_R_SUCCESS) {
3170 log_info (
"failover peer %s: %s", state -> name,
3171 isc_result_totext (status));
3172 #if defined (DEBUG_FAILOVER_TIMING) 3174 "dhcp_failover_listener_restart");
3180 (
tvref_t)dhcp_failover_state_reference,
3181 (
tvunref_t)dhcp_failover_state_dereference);
3188 dhcp_failover_state_t *state = vs;
3190 #if defined (DEBUG_FAILOVER_TIMING) 3191 log_info(
"dhcp_failover_auto_partner_down");
3202 dhcp_failover_state_t *s;
3205 isc_result_t status;
3209 s = (dhcp_failover_state_t *)h;
3214 name, s -> name,
MDL);
3215 return ISC_R_NOTFOUND;
3217 oc = s -> partner.address;
3219 memset (&ds, 0,
sizeof ds);
3226 return ISC_R_NOTFOUND;
3229 name, ds.data, ds.
len,
MDL);
3236 oc = s -> me.address;
3240 s -> partner.port,
MDL);
3243 name, s -> me.port,
MDL);
3246 s -> me.max_flying_updates,
3252 s -> load_balance_max_secs,
MDL);
3257 return ISC_R_NOTFOUND;
3260 s -> partner.state,
MDL);
3263 s -> me.state,
MDL);
3266 s -> partner.stos,
MDL);
3274 s -> last_packet_sent,
MDL);
3277 s -> last_timestamp_received,
3283 s -> me.max_response_delay,
3287 s -> cur_unacked_updates,
MDL);
3290 if (h -> inner && h -> inner -> type -> get_value)
3291 return (*(h -> inner -> type -> get_value))
3292 (h -> inner, id, name, value);
3293 return ISC_R_NOTFOUND;
3297 const char *file,
int line)
3299 dhcp_failover_state_t *s;
3303 s = (dhcp_failover_state_t *)h;
3305 if (s -> link_to_peer)
3306 dhcp_failover_link_dereference (&s -> link_to_peer, file, line);
3309 s -> name = (
char *)0;
3311 if (s -> partner.address)
3313 if (s -> me.address)
3316 dfree (s -> hba, file, line);
3317 s -> hba = (u_int8_t *)0;
3319 if (s -> update_queue_head)
3320 lease_dereference (&s -> update_queue_head, file, line);
3321 if (s -> update_queue_tail)
3322 lease_dereference (&s -> update_queue_tail, file, line);
3323 if (s -> ack_queue_head)
3324 lease_dereference (&s -> ack_queue_head, file, line);
3325 if (s -> ack_queue_tail)
3326 lease_dereference (&s -> ack_queue_tail, file, line);
3327 if (s -> send_update_done)
3328 lease_dereference (&s -> send_update_done, file, line);
3329 if (s -> toack_queue_head)
3330 failover_message_dereference (&s -> toack_queue_head,
3332 if (s -> toack_queue_tail)
3333 failover_message_dereference (&s -> toack_queue_tail,
3335 return ISC_R_SUCCESS;
3347 dhcp_failover_state_t *s;
3348 isc_result_t status;
3355 s = (dhcp_failover_state_t *)h;
3358 if (status != ISC_R_SUCCESS)
3361 if (status != ISC_R_SUCCESS)
3365 if (status != ISC_R_SUCCESS)
3368 if (status != ISC_R_SUCCESS)
3371 sizeof s -> partner.address);
3372 if (status != ISC_R_SUCCESS)
3376 if (status != ISC_R_SUCCESS)
3379 if (status != ISC_R_SUCCESS)
3382 if (status != ISC_R_SUCCESS)
3386 if (status != ISC_R_SUCCESS)
3389 if (status != ISC_R_SUCCESS)
3392 sizeof s -> me.address);
3393 if (status != ISC_R_SUCCESS)
3397 if (status != ISC_R_SUCCESS)
3400 if (status != ISC_R_SUCCESS)
3403 if (status != ISC_R_SUCCESS)
3407 if (status != ISC_R_SUCCESS)
3410 if (status != ISC_R_SUCCESS)
3413 s -> me.max_flying_updates);
3414 if (status != ISC_R_SUCCESS)
3418 if (status != ISC_R_SUCCESS)
3421 if (status != ISC_R_SUCCESS)
3424 if (status != ISC_R_SUCCESS)
3428 if (status != ISC_R_SUCCESS)
3431 if (status != ISC_R_SUCCESS)
3434 (c, (u_int32_t)s -> load_balance_max_secs));
3435 if (status != ISC_R_SUCCESS)
3441 if (status != ISC_R_SUCCESS)
3444 if (status != ISC_R_SUCCESS)
3447 if (status != ISC_R_SUCCESS)
3452 if (status != ISC_R_SUCCESS)
3455 if (status != ISC_R_SUCCESS)
3458 if (status != ISC_R_SUCCESS)
3462 if (status != ISC_R_SUCCESS)
3465 if (status != ISC_R_SUCCESS)
3468 if (status != ISC_R_SUCCESS)
3472 if (status != ISC_R_SUCCESS)
3475 if (status != ISC_R_SUCCESS)
3478 (u_int32_t)s -> partner.stos);
3479 if (status != ISC_R_SUCCESS)
3483 if (status != ISC_R_SUCCESS)
3486 if (status != ISC_R_SUCCESS)
3489 if (status != ISC_R_SUCCESS)
3493 if (status != ISC_R_SUCCESS)
3496 if (status != ISC_R_SUCCESS)
3499 if (status != ISC_R_SUCCESS)
3503 if (status != ISC_R_SUCCESS)
3506 if (status != ISC_R_SUCCESS)
3509 (c, (u_int32_t)s -> last_packet_sent));
3510 if (status != ISC_R_SUCCESS)
3514 if (status != ISC_R_SUCCESS)
3517 if (status != ISC_R_SUCCESS)
3520 (c, (u_int32_t)s -> last_timestamp_received));
3521 if (status != ISC_R_SUCCESS)
3525 if (status != ISC_R_SUCCESS)
3528 if (status != ISC_R_SUCCESS)
3531 if (status != ISC_R_SUCCESS)
3535 if (status != ISC_R_SUCCESS)
3538 if (status != ISC_R_SUCCESS)
3541 (c, (u_int32_t)s -> me.max_response_delay));
3542 if (status != ISC_R_SUCCESS)
3546 if (status != ISC_R_SUCCESS)
3549 if (status != ISC_R_SUCCESS)
3552 (c, (u_int32_t)s -> cur_unacked_updates));
3553 if (status != ISC_R_SUCCESS)
3556 if (h -> inner && h -> inner -> type -> stuff_values)
3557 return (*(h -> inner -> type -> stuff_values)) (c,
id,
3559 return ISC_R_SUCCESS;
3567 isc_result_t status;
3568 dhcp_failover_state_t *s;
3575 if (status == ISC_R_SUCCESS) {
3579 if (status != ISC_R_SUCCESS)
3591 if (status == ISC_R_SUCCESS) {
3593 unsigned l = strlen (s -> name);
3594 if (l == tv -> value -> u.buffer.len &&
3596 tv -> value -> u.buffer.
value, l))
3609 return ISC_R_NOTFOUND;
3620 return ISC_R_SUCCESS;
3626 return ISC_R_NOTIMPLEMENTED;
3632 return ISC_R_NOTIMPLEMENTED;
3636 u_int8_t *addr,
unsigned addrlen)
3641 memset (&ds, 0,
sizeof ds);
3648 state -> partner.address,
MDL)) {
3649 for (i = 0; i + addrlen - 1 < ds.len; i += addrlen) {
3650 if (!memcmp (&ds.data [i],
3663 dhcp_failover_state_t *state;
3664 failover_option_t *name;
3666 if ((strlen(state->name) == name->count) &&
3667 (memcmp(state->name, name->data, name->count) == 0))
3675 static char resbuf[
sizeof(
"Undefined-255: This reason code is not defined " 3676 "in the protocol standard.")];
3678 if ((reason > 0xff) || (reason < 0))
3679 return "Reason code out of range.";
3682 case FTR_ILLEGAL_IP_ADDR:
3683 return "Illegal IP address (not part of any address pool).";
3685 case FTR_FATAL_CONFLICT:
3686 return "Fatal conflict exists: address in use by other client.";
3688 case FTR_MISSING_BINDINFO:
3689 return "Missing binding information.";
3691 case FTR_TIMEMISMATCH:
3692 return "Connection rejected, time mismatch too great.";
3694 case FTR_INVALID_MCLT:
3695 return "Connection rejected, invalid MCLT.";
3697 case FTR_MISC_REJECT:
3698 return "Connection rejected, unknown reason.";
3700 case FTR_DUP_CONNECTION:
3701 return "Connection rejected, duplicate connection.";
3703 case FTR_INVALID_PARTNER:
3704 return "Connection rejected, invalid failover partner.";
3706 case FTR_TLS_UNSUPPORTED:
3707 return "TLS not supported.";
3709 case FTR_TLS_UNCONFIGURED:
3710 return "TLS supported but not configured.";
3712 case FTR_TLS_REQUIRED:
3713 return "TLS required but not supported by partner.";
3715 case FTR_DIGEST_UNSUPPORTED:
3716 return "Message digest not supported.";
3718 case FTR_DIGEST_UNCONFIGURED:
3719 return "Message digest not configured.";
3721 case FTR_VERSION_MISMATCH:
3722 return "Protocol version mismatch.";
3724 case FTR_OUTDATED_BIND_INFO:
3725 return "Outdated binding information.";
3727 case FTR_LESS_CRIT_BIND_INFO:
3728 return "Less critical binding information.";
3730 case FTR_NO_TRAFFIC:
3731 return "No traffic within sufficient time.";
3733 case FTR_HBA_CONFLICT:
3734 return "Hash bucket assignment conflict.";
3736 case FTR_IP_NOT_RESERVED:
3737 return "IP not reserved on this server.";
3739 case FTR_IP_DIGEST_FAILURE:
3740 return "Message digest failed to compare.";
3742 case FTR_IP_MISSING_DIGEST:
3743 return "Missing message digest.";
3746 return "Unknown Error.";
3749 sprintf(resbuf,
"Undefined-%d: This reason code is not defined in the " 3750 "protocol standard.", reason);
3760 return "unknown-state";
3763 return "partner-down";
3769 return "conflict-done";
3772 return "communications-interrupted";
3775 return "resolution-interrupted";
3778 return "potential-conflict";
3784 return "recover-done";
3787 return "recover-wait";
3802 static char messbuf[
sizeof(
"unknown-message-255")];
3805 return "invalid-message";
3809 return "pool-request";
3812 return "pool-response";
3815 return "bind-update";
3823 case FTM_CONNECTACK:
3824 return "connect-ack";
3827 return "update-request";
3830 return "update-done";
3833 return "update-request-all";
3841 case FTM_DISCONNECT:
3842 return "disconnect";
3845 sprintf(messbuf,
"unknown-message-%u", type);
3852 static char optbuf[
sizeof(
"unknown-option-65535")];
3855 return "invalid-option";
3858 case FTO_ADDRESSES_TRANSFERRED:
3859 return "addresses-transferred";
3861 case FTO_ASSIGNED_IP_ADDRESS:
3862 return "assigned-ip-address";
3864 case FTO_BINDING_STATUS:
3865 return "binding-status";
3867 case FTO_CLIENT_IDENTIFIER:
3868 return "client-identifier";
3879 case FTO_DELAYED_SERVICE:
3880 return "delayed-service";
3888 case FTO_LEASE_EXPIRY:
3889 return "lease-expiry";
3891 case FTO_MAX_UNACKED:
3892 return "max-unacked";
3900 case FTO_MESSAGE_DIGEST:
3901 return "message-digest";
3903 case FTO_POTENTIAL_EXPIRY:
3904 return "potential-expiry";
3906 case FTO_PROTOCOL_VERSION:
3907 return "protocol-version";
3909 case FTO_RECEIVE_TIMER:
3910 return "receive-timer";
3912 case FTO_REJECT_REASON:
3913 return "reject-reason";
3915 case FTO_RELATIONSHIP_NAME:
3916 return "relationship-name";
3918 case FTO_REPLY_OPTIONS:
3919 return "reply-options";
3921 case FTO_REQUEST_OPTIONS:
3922 return "request-options";
3924 case FTO_SERVER_FLAGS:
3925 return "server-flags";
3927 case FTO_SERVER_STATE:
3928 return "server-state";
3936 case FTO_TLS_REQUEST:
3937 return "tls-request";
3939 case FTO_VENDOR_CLASS:
3940 return "vendor-class";
3942 case FTO_VENDOR_OPTIONS:
3943 return "vendor-options";
3946 sprintf(optbuf,
"unknown-option-%u", type);
3955 const char *fmt, ...)
3968 if (vsnprintf (tbuf,
sizeof tbuf, fmt, va) >=
sizeof tbuf)
3969 log_fatal (
"%s: vsnprintf would truncate",
3970 "dhcp_failover_make_option");
3974 strlen (tbuf), tbuf);
3978 char *obuf,
unsigned *obufix,
3979 unsigned obufmax, ...)
3982 struct failover_option_info *info;
3984 unsigned size, count;
3990 #if defined (DEBUG_FAILOVER_MESSAGES) 3998 failover_option_t
option, *op;
4002 if (code < 1 || code > FTO_MAX || ft_options [code].type == FT_UNDEF) {
4005 info = &ft_options [code];
4007 va_start (va, obufmax);
4011 if (info -> type == FT_DDNS || info -> type == FT_DDNS1) {
4012 count = info -> type == FT_DDNS ? 1 : 2;
4013 size = va_arg (va,
int) + count;
4016 if (info -> num_present)
4017 count = info -> num_present;
4019 count = va_arg (va,
int);
4022 switch (info -> type) {
4029 case FT_TEXT_OR_BYTES:
4031 txt = va_arg (va,
char *);
4036 ilen = va_arg (va,
unsigned);
4037 size = count * ilen;
4050 log_fatal (
"bogus type in failover_make_option: %d",
4059 option.count = size;
4070 #if defined (DEBUG_FAILOVER_MESSAGES) 4078 if (snprintf (tbuf,
sizeof tbuf,
" (%s<%d>", info -> name,
4079 option.count) >=
sizeof tbuf)
4080 log_fatal (
"dhcp_failover_make_option: tbuf overflow");
4085 switch (info -> type) {
4087 for (i = 0; i < count; i++) {
4088 val = va_arg (va,
unsigned);
4089 #if defined (DEBUG_FAILOVER_MESSAGES) 4091 sprintf (tbuf,
" %d", val);
4094 option.data [i + 4] = val;
4099 for (i = 0; i < count; i++) {
4100 iaddr = va_arg (va, u_int8_t *);
4103 log_error (
"IP addrlen=%d, should be 4.",
4109 #if defined (DEBUG_FAILOVER_MESSAGES) 4111 sprintf (tbuf,
" %u.%u.%u.%u",
4112 iaddr [0], iaddr [1], iaddr [2], iaddr [3]);
4115 memcpy (&option.data [4 + i * ilen], iaddr, ilen);
4120 for (i = 0; i < count; i++) {
4121 val = va_arg (va,
unsigned);
4122 #if defined (DEBUG_FAILOVER_MESSAGES) 4124 sprintf (tbuf,
" %d", val);
4127 putULong (&option.data [4 + i * 4], val);
4133 bval = va_arg (va, u_int8_t *);
4134 #if defined (DEBUG_FAILOVER_MESSAGES) 4135 for (i = 0; i < count; i++) {
4137 sprintf (tbuf,
" %d", bval [i]);
4141 memcpy (&option.data [4], bval, count);
4148 case FT_TEXT_OR_BYTES:
4150 #if defined (DEBUG_FAILOVER_MESSAGES) 4158 if (snprintf (tbuf,
sizeof tbuf,
"\"%s\"", txt) >=
sizeof tbuf)
4159 log_fatal (
"dhcp_failover_make_option: tbuf overflow");
4162 memcpy (&option.data [4], txt, count);
4167 option.data [4] = va_arg (va,
unsigned);
4169 option.data [5] = va_arg (va,
unsigned);
4170 bval = va_arg (va, u_int8_t *);
4171 memcpy (&option.data [4 + count], bval, size - count - 4);
4172 #if defined (DEBUG_FAILOVER_MESSAGES) 4173 for (i = 4; i < size; i++) {
4175 sprintf (tbuf,
" %d", option.data [i]);
4182 for (i = 0; i < count; i++) {
4183 val = va_arg (va, u_int32_t);
4184 #if defined (DEBUG_FAILOVER_MESSAGES) 4186 sprintf (tbuf,
" %d", val);
4189 putUShort (&option.data [4 + i * 2], val);
4198 #if defined DEBUG_FAILOVER_MESSAGES 4204 op =
dmalloc (
sizeof (failover_option_t),
MDL);
4218 int msg_type, u_int32_t xid, ...)
4224 failover_option_t *option;
4225 unsigned char *opbuf;
4226 isc_result_t status = ISC_R_SUCCESS;
4232 va_start (list, xid);
4233 while ((option = va_arg (list, failover_option_t *))) {
4235 size += option -> count;
4242 if (!bad_option && size) {
4245 status = ISC_R_NOMEMORY;
4247 opbuf = (
unsigned char *)0;
4249 va_start (list, xid);
4250 while ((option = va_arg (list, failover_option_t *))) {
4253 if (!bad_option && opbuf)
4254 memcpy (&opbuf [opix],
4255 option -> data, option -> count);
4258 opix += option -> count;
4272 if (status != ISC_R_SUCCESS)
4278 if (status != ISC_R_SUCCESS)
4284 if (status != ISC_R_SUCCESS)
4289 if (status != ISC_R_SUCCESS)
4294 if (status != ISC_R_SUCCESS)
4300 if (status != ISC_R_SUCCESS)
4304 if (link -> state_object &&
4305 link -> state_object -> link_to_peer == link) {
4306 #if defined (DEBUG_FAILOVER_CONTACT_TIMING) 4308 (
int)(link -> state_object ->
4309 partner.max_response_delay) / 3,
4310 "dhcp_failover_send_contact");
4313 (
int)(link -> state_object ->
4314 partner.max_response_delay) / 3;
4318 (
tvref_t)dhcp_failover_state_reference,
4319 (
tvunref_t)dhcp_failover_state_dereference);
4326 log_info (
"dhcp_failover_put_message: something went wrong.");
4333 dhcp_failover_state_t *state = vstate;
4334 dhcp_failover_link_t *link;
4336 #if defined (DEBUG_FAILOVER_TIMING) 4337 log_info (
"dhcp_failover_timeout");
4342 link = state -> link_to_peer;
4348 log_error (
"timeout waiting for failover peer %s", state -> name);
4357 dhcp_failover_state_t *state = vstate;
4358 dhcp_failover_link_t *link;
4359 isc_result_t status;
4361 #if defined(DEBUG_FAILOVER_MESSAGES) && \ 4362 defined(DEBUG_FAILOVER_CONTACT_MESSAGES) 4364 unsigned obufix = 0;
4369 #if defined (DEBUG_FAILOVER_CONTACT_TIMING) 4370 log_info (
"dhcp_failover_send_contact");
4375 link = state -> link_to_peer;
4382 (link, link -> outer,
4383 FTM_CONTACT, link->xid++,
4384 (failover_option_t *)0));
4386 #if defined(DEBUG_FAILOVER_MESSAGES) && \ 4387 defined(DEBUG_FAILOVER_CONTACT_MESSAGES) 4388 if (status != ISC_R_SUCCESS)
4402 dhcp_failover_link_t *link;
4403 isc_result_t status;
4405 #if defined (DEBUG_FAILOVER_MESSAGES) 4407 unsigned obufix = 0;
4409 # define FMA obuf, &obufix, sizeof obuf 4412 # define FMA (char *)0, (unsigned *)0, 0 4417 link = state -> link_to_peer;
4424 (link, link -> outer,
4425 FTM_STATE, link->xid++,
4428 ? state -> saved_state
4429 : state -> me.state)),
4431 (FTO_SERVER_FLAGS, FMA,
4433 ? FTF_SERVER_STARTUP : 0)),
4435 (failover_option_t *)0));
4437 #if defined (DEBUG_FAILOVER_MESSAGES) 4438 if (status != ISC_R_SUCCESS)
4447 return ISC_R_SUCCESS;
4454 dhcp_failover_link_t *link;
4455 dhcp_failover_state_t *state;
4456 isc_result_t status;
4457 #if defined (DEBUG_FAILOVER_MESSAGES) 4459 unsigned obufix = 0;
4461 # define FMA obuf, &obufix, sizeof obuf 4464 # define FMA (char *)0, (unsigned *)0, 0 4469 link = (dhcp_failover_link_t *)l;
4470 state = link -> state_object;
4477 FTM_CONNECT, link->xid++,
4479 strlen(state->name), state->name),
4481 state -> me.max_flying_updates),
4483 state -> me.max_response_delay),
4487 DHCP_FAILOVER_VERSION),
4495 (failover_option_t *)0));
4497 #if defined (DEBUG_FAILOVER_MESSAGES) 4498 if (status != ISC_R_SUCCESS)
4509 dhcp_failover_state_t *state,
4510 int reason,
const char *errmsg)
4512 dhcp_failover_link_t *link;
4513 isc_result_t status;
4514 #if defined (DEBUG_FAILOVER_MESSAGES) 4516 unsigned obufix = 0;
4518 # define FMA obuf, &obufix, sizeof obuf 4521 # define FMA (char *)0, (unsigned *)0, 0 4526 link = (dhcp_failover_link_t *)l;
4533 FTM_CONNECTACK, link->imsg->xid,
4536 strlen(state->name), state->name)
4537 : (link->imsg->options_present & FTB_RELATIONSHIP_NAME)
4539 link->imsg->relationship_name.count,
4540 link->imsg->relationship_name.data)
4541 : &skip_failover_option,
4544 state -> me.max_flying_updates)
4545 : &skip_failover_option,
4548 state -> me.max_response_delay)
4549 : &skip_failover_option,
4553 DHCP_FAILOVER_VERSION),
4554 (link->imsg->options_present & FTB_TLS_REQUEST)
4557 : &skip_failover_option,
4561 : &skip_failover_option,
4564 strlen (errmsg), errmsg)
4565 : &skip_failover_option,
4566 (failover_option_t *)0));
4568 #if defined (DEBUG_FAILOVER_MESSAGES) 4569 if (status != ISC_R_SUCCESS)
4581 const char *message)
4583 dhcp_failover_link_t *link;
4584 isc_result_t status;
4585 #if defined (DEBUG_FAILOVER_MESSAGES) 4587 unsigned obufix = 0;
4589 # define FMA obuf, &obufix, sizeof obuf 4592 # define FMA (char *)0, (unsigned *)0, 0 4597 link = (dhcp_failover_link_t *)l;
4601 if (!message && reason)
4606 FTM_DISCONNECT, link->xid++,
4611 strlen (message), message)
4612 : &skip_failover_option),
4613 (failover_option_t *)0));
4615 #if defined (DEBUG_FAILOVER_MESSAGES) 4616 if (status != ISC_R_SUCCESS)
4629 struct lease *lease)
4631 dhcp_failover_link_t *link;
4632 isc_result_t status;
4635 #if defined (DEBUG_FAILOVER_MESSAGES) 4637 unsigned obufix = 0;
4639 # define FMA obuf, &obufix, sizeof obuf 4642 # define FMA (char *)0, (unsigned *)0, 0 4645 if (!state -> link_to_peer ||
4648 link = (dhcp_failover_link_t *)state -> link_to_peer;
4660 if ((state->i_am == primary) && (transmit_state ==
FTS_FREE))
4662 else if ((state->i_am == secondary) &&
4666 flags |= FTF_IP_FLAG_RESERVE;
4669 flags |= FTF_IP_FLAG_BOOTP;
4709 (link, link -> outer,
4715 lease -> desired_binding_state),
4720 : &skip_failover_option,
4721 lease -> hardware_addr.hlen
4723 lease -> hardware_addr.hlen,
4724 lease -> hardware_addr.hbuf)
4725 : &skip_failover_option,
4732 (lease->
cltt != 0) ?
4734 &skip_failover_option,
4737 &skip_failover_option,
4738 &skip_failover_option,
4739 &skip_failover_option,
4740 &skip_failover_option,
4741 (failover_option_t *)0));
4743 #if defined (DEBUG_FAILOVER_MESSAGES) 4744 if (status != ISC_R_SUCCESS)
4757 failover_message_t *msg,
4758 int reason,
const char *message)
4760 dhcp_failover_link_t *link;
4761 isc_result_t status;
4762 #if defined (DEBUG_FAILOVER_MESSAGES) 4764 unsigned obufix = 0;
4766 # define FMA obuf, &obufix, sizeof obuf 4769 # define FMA (char *)0, (unsigned *)0, 0 4772 if (!state -> link_to_peer ||
4775 link = (dhcp_failover_link_t *)state -> link_to_peer;
4780 if (!message && reason)
4785 (link, link -> outer,
4786 FTM_BNDACK, msg->xid,
4788 sizeof msg -> assigned_addr,
4789 &msg -> assigned_addr),
4790 #ifdef DO_BNDACK_SHOULD_NOT
4792 msg -> binding_status),
4793 (msg -> options_present & FTB_CLIENT_IDENTIFIER)
4795 msg -> client_identifier.count,
4796 msg -> client_identifier.data)
4797 : &skip_failover_option,
4798 (msg -> options_present & FTB_CHADDR)
4800 msg -> chaddr.count,
4802 : &skip_failover_option,
4806 msg -> potential_expiry),
4809 (msg->options_present & FTB_CLTT) ?
4811 &skip_failover_option,
4812 ((msg->options_present & FTB_IP_FLAGS) && msg->ip_flags) ?
4815 : &skip_failover_option,
4819 : &skip_failover_option,
4822 strlen (message), message)
4823 : &skip_failover_option,
4824 #ifdef DO_BNDACK_SHOULD_NOT
4825 &skip_failover_option,
4826 &skip_failover_option,
4827 &skip_failover_option,
4829 (failover_option_t *)0));
4831 #if defined (DEBUG_FAILOVER_MESSAGES) 4832 if (status != ISC_R_SUCCESS)
4844 dhcp_failover_link_t *link;
4845 isc_result_t status;
4846 #if defined (DEBUG_FAILOVER_MESSAGES) 4848 unsigned obufix = 0;
4850 # define FMA obuf, &obufix, sizeof obuf 4853 # define FMA (char *)0, (unsigned *)0, 0 4856 if (!state -> link_to_peer ||
4859 link = (dhcp_failover_link_t *)state -> link_to_peer;
4865 (link, link -> outer,
4866 FTM_POOLREQ, link->xid++,
4867 (failover_option_t *)0));
4869 #if defined (DEBUG_FAILOVER_MESSAGES) 4870 if (status != ISC_R_SUCCESS)
4883 dhcp_failover_link_t *link;
4884 isc_result_t status;
4885 #if defined (DEBUG_FAILOVER_MESSAGES) 4887 unsigned obufix = 0;
4889 # define FMA obuf, &obufix, sizeof obuf 4892 # define FMA (char *)0, (unsigned *)0, 0 4895 if (!state -> link_to_peer ||
4898 link = (dhcp_failover_link_t *)state -> link_to_peer;
4904 (link, link -> outer,
4905 FTM_POOLRESP, link->imsg->xid,
4908 (failover_option_t *)0));
4910 #if defined (DEBUG_FAILOVER_MESSAGES) 4911 if (status != ISC_R_SUCCESS)
4923 dhcp_failover_link_t *link;
4924 isc_result_t status;
4925 #if defined (DEBUG_FAILOVER_MESSAGES) 4927 unsigned obufix = 0;
4929 # define FMA obuf, &obufix, sizeof obuf 4932 # define FMA (char *)0, (unsigned *)0, 0 4935 if (!state->link_to_peer ||
4938 link = (dhcp_failover_link_t *)state->link_to_peer;
4946 if (state->curUPD == FTM_UPDREQALL) {
4951 link->xid++, NULL));
4953 state->curUPD = FTM_UPDREQ;
4955 #if defined (DEBUG_FAILOVER_MESSAGES) 4956 if (status != ISC_R_SUCCESS)
4964 if (status == ISC_R_SUCCESS) {
4965 log_info(
"Sent update request message to %s", state->name);
4967 log_error(
"Failed to send update request all message to %s: %s",
4968 state->name, isc_result_totext(status));
4976 dhcp_failover_link_t *link;
4977 isc_result_t status;
4978 #if defined (DEBUG_FAILOVER_MESSAGES) 4980 unsigned obufix = 0;
4982 # define FMA obuf, &obufix, sizeof obuf 4985 # define FMA (char *)0, (unsigned *)0, 0 4988 if (!state->link_to_peer ||
4991 link = (dhcp_failover_link_t *)state->link_to_peer;
5001 link->xid++, NULL));
5003 state->curUPD = FTM_UPDREQALL;
5005 #if defined (DEBUG_FAILOVER_MESSAGES) 5006 if (status != ISC_R_SUCCESS)
5014 if (status == ISC_R_SUCCESS) {
5015 log_info(
"Sent update request all message to %s", state->name);
5017 log_error(
"Failed to send update request all message to %s: %s",
5018 state->name, isc_result_totext(status));
5025 dhcp_failover_link_t *link;
5026 isc_result_t status;
5027 #if defined (DEBUG_FAILOVER_MESSAGES) 5029 unsigned obufix = 0;
5031 # define FMA obuf, &obufix, sizeof obuf 5034 # define FMA (char *)0, (unsigned *)0, 0 5037 if (!state -> link_to_peer ||
5040 link = (dhcp_failover_link_t *)state -> link_to_peer;
5046 (link, link -> outer,
5047 FTM_UPDDONE, state->updxid,
5048 (failover_option_t *)0));
5050 #if defined (DEBUG_FAILOVER_MESSAGES) 5051 if (status != ISC_R_SUCCESS)
5059 log_info (
"Sent update done message to %s", state -> name);
5083 static isc_boolean_t
5084 failover_lease_is_better(dhcp_failover_state_t *state,
struct lease *lease,
5085 failover_message_t *msg)
5095 if ((msg->options_present & FTB_CLTT) != 0)
5096 msg_cltt = msg->cltt;
5100 switch(local_state) {
5103 if (msg_cltt < lease->cltt)
5105 else if (msg_cltt > lease->
cltt)
5107 else if (state->i_am == primary)
5124 else if (state->i_am == primary)
5140 failover_message_t *msg)
5142 struct lease *lt = NULL, *lease = NULL;
5144 int reason = FTR_MISC_REJECT;
5145 const char *message;
5146 int new_binding_state;
5147 int send_to_backup = 0;
5148 int required_options;
5149 isc_boolean_t chaddr_changed = ISC_FALSE;
5150 isc_boolean_t ident_changed = ISC_FALSE;
5153 required_options = FTB_ASSIGNED_IP_ADDRESS | FTB_BINDING_STATUS;
5154 if ((msg->options_present & required_options) != required_options) {
5155 message =
"binding update lacks required options";
5156 reason = FTR_MISSING_BINDINFO;
5160 ia.len =
sizeof msg -> assigned_addr;
5161 memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
5164 message =
"unknown IP address";
5165 reason = FTR_ILLEGAL_IP_ADDR;
5173 if ((lease->pool == NULL) || (lease->pool->failover_peer == NULL) ||
5174 (lease->pool->failover_peer != state)) {
5175 message =
"IP address is covered by a different failover " 5176 "relationship state";
5177 reason = FTR_ILLEGAL_IP_ADDR;
5191 if ((lease->flags & ON_ACK_QUEUE) != 0) {
5192 if (failover_lease_is_better(state, lease, msg)) {
5193 message =
"incoming update is less critical than " 5195 reason = FTR_LESS_CRIT_BIND_INFO;
5205 message =
"no memory";
5209 if (msg -> options_present & FTB_CHADDR) {
5211 message =
"BNDUPD to ABANDONED with a CHADDR";
5214 if (msg -> chaddr.count >
sizeof lt -> hardware_addr.hbuf) {
5215 message =
"chaddr too long";
5221 msg->chaddr.count) != 0))
5222 chaddr_changed = ISC_TRUE;
5224 lt -> hardware_addr.hlen = msg -> chaddr.count;
5225 memcpy (lt -> hardware_addr.hbuf, msg -> chaddr.data,
5226 msg -> chaddr.count);
5227 }
else if (msg->binding_status ==
FTS_ACTIVE ||
5230 message =
"BNDUPD without CHADDR";
5231 reason = FTR_MISSING_BINDINFO;
5234 chaddr_changed = ISC_TRUE;
5244 if (msg->options_present & FTB_CLIENT_IDENTIFIER) {
5246 message =
"BNDUPD to ABANDONED with client-id";
5250 if ((lt->
uid_len != msg->client_identifier.count) ||
5251 (lt->
uid == NULL) ||
5252 (memcmp(lt->
uid, msg->client_identifier.data,
5254 ident_changed = ISC_TRUE;
5256 lt->
uid_len = msg->client_identifier.count;
5271 message =
"no memory";
5280 msg -> client_identifier.data, lt -> uid_len);
5281 }
else if (lt->
uid && msg->binding_status !=
FTS_RESET &&
5284 ident_changed = ISC_TRUE;
5317 (chaddr_changed || ident_changed)) {
5318 #if defined (NSUPDATE) 5322 if (lease->scope != NULL)
5327 if (msg -> options_present & FTB_STOS) {
5328 lt -> starts = msg -> stos;
5330 if (msg -> options_present & FTB_LEASE_EXPIRY) {
5331 lt -> ends = msg -> expiry;
5333 if (msg->options_present & FTB_POTENTIAL_EXPIRY) {
5334 lt->
atsfp = lt->
tsfp = msg->potential_expiry;
5336 if (msg->options_present & FTB_IP_FLAGS) {
5337 if (msg->ip_flags & FTF_IP_FLAG_RESERVE) {
5338 if ((((state->i_am == primary) &&
5339 (lease->binding_state ==
FTS_FREE)) ||
5340 ((state->i_am == secondary) &&
5343 message =
"Address is not reserved.";
5344 reason = FTR_IP_NOT_RESERVED;
5352 if (msg->ip_flags & FTF_IP_FLAG_BOOTP) {
5353 if ((((state->i_am == primary) &&
5354 (lease->binding_state ==
FTS_FREE)) ||
5355 ((state->i_am == secondary) &&
5358 message =
"Address is not allocated to BOOTP.";
5365 if (msg->ip_flags & ~(FTF_IP_FLAG_RESERVE | FTF_IP_FLAG_BOOTP))
5366 log_info(
"Unknown IP-flags set in BNDUPD (0x%x).",
5371 #if defined (DEBUG_LEASE_STATE_TRANSITIONS) 5372 log_info (
"processing state transition for %s: %s to %s",
5380 if (state -> me.state ==
normal) {
5383 (lease, state, msg -> binding_status,
5384 msg -> potential_expiry));
5391 (lease, state, msg -> binding_status,
5392 msg -> potential_expiry));
5394 if (new_binding_state != msg -> binding_status) {
5397 if (snprintf (outbuf,
sizeof outbuf,
5398 "%s: invalid state transition: %s to %s",
5403 log_fatal (
"%s: impossible outbuf overflow",
5404 "dhcp_failover_process_bind_update");
5414 lt -> next_binding_state =
FTS_FREE;
5421 if ((state->i_am == primary) &&
5425 lt -> next_binding_state = new_binding_state;
5427 msg -> binding_status = lt -> next_binding_state;
5438 message =
"database update failed";
5449 if (send_to_backup && secondary_not_hoarding(state, lease->pool)) {
5456 log_error(
"can't commit lease %s for mac addr " 5457 "affinity",
piaddr(lease->ip_addr));
5464 lease_dereference (<,
MDL);
5466 lease_dereference (&lease,
MDL);
5468 return ISC_R_SUCCESS;
5477 secondary_not_hoarding(dhcp_failover_state_t *state,
struct pool *p) {
5485 hold = ((total * state->max_lease_ownership) + 50) / 100;
5496 return(lts > -hold);
5500 failover_message_t *msg)
5502 struct lease *lease = NULL;
5504 const char *message =
"no memory";
5505 u_int32_t pot_expire;
5506 int send_to_backup = ISC_FALSE;
5509 ia.len =
sizeof msg -> assigned_addr;
5510 memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
5513 message =
"no such lease";
5518 if (msg -> options_present & FTB_REJECT_REASON) {
5519 log_error (
"bind update on %s from %s rejected: %.*s",
5520 piaddr (ia), state -> name,
5521 (
int)((msg -> options_present & FTB_MESSAGE)
5522 ? msg -> message.count
5524 (msg -> reject_reason))),
5525 (msg -> options_present & FTB_MESSAGE)
5526 ? (
const char *)(msg -> message.data)
5528 (msg -> reject_reason)));
5539 message =
"xid mismatch";
5544 if (msg->options_present & FTO_POTENTIAL_EXPIRY)
5545 pot_expire = msg->potential_expiry;
5547 pot_expire = lease->
tstp;
5567 lease->
atsfp = lease->
tsfp = pot_expire;
5568 if ((state->i_am == secondary) &&
5590 if (state->i_am == primary &&
5593 send_to_backup = ISC_TRUE;
5595 if (!send_to_backup && state->me.state ==
normal)
5601 lease->
atsfp = lease->
tsfp = pot_expire;
5623 if (state -> send_update_done == lease) {
5624 lease_dereference (&state -> send_update_done,
MDL);
5631 if (send_to_backup && secondary_not_hoarding(state, lease->
pool)) {
5640 if (state->me.state ==
normal)
5649 lease_dereference (&lease,
MDL);
5650 return ISC_R_SUCCESS;
5653 log_info (
"bind update on %s got ack from %s: %s.",
5654 piaddr (ia), state -> name, message);
5665 #define FREE_LEASES 0 5666 #define ACTIVE_LEASES 1 5667 #define EXPIRED_LEASES 2 5668 #define ABANDONED_LEASES 3 5669 #define BACKUP_LEASES 4 5670 #define RESERVED_LEASES 5 5676 for (p = s ->
pools; p; p = p ->
next) {
5702 return ISC_R_SUCCESS;
5707 failover_message_t *msg)
5709 if (state->send_update_done) {
5710 log_info(
"Received update request while old update still " 5711 "flying! Silently discarding old request.");
5712 lease_dereference(&state->send_update_done,
MDL);
5718 state->updxid = msg->xid;
5723 if (state -> update_queue_tail) {
5724 lease_reference (&state -> send_update_done,
5725 state -> update_queue_tail,
MDL);
5727 log_info (
"Update request from %s: sending update",
5733 log_info (
"Update request from %s: nothing pending",
5737 return ISC_R_SUCCESS;
5742 failover_message_t *msg)
5744 if (state->send_update_done) {
5745 log_info(
"Received update request while old update still " 5746 "flying! Silently discarding old request.");
5747 lease_dereference(&state->send_update_done,
MDL);
5753 state->updxid = msg->xid;
5755 if (state -> update_queue_tail) {
5756 lease_reference (&state -> send_update_done,
5757 state -> update_queue_tail,
MDL);
5759 log_info (
"Update request all from %s: sending update",
5765 log_info (
"Update request all from %s: nothing pending",
5769 return ISC_R_SUCCESS;
5774 failover_message_t *msg)
5778 log_info (
"failover peer %s: peer update completed.",
5781 state -> curUPD = 0;
5783 switch (state -> me.state) {
5799 if (state->i_am == secondary) {
5802 log_error(
"Secondary is in conflict_done " 5803 "state after conflict resolution, " 5804 "this is illegal.");
5808 if (state->i_am == primary)
5811 log_error(
"Spurious update-done message.");
5817 log_error(
"Spurious update-done message.");
5826 if (state -> me.stos + state -> mclt >
cur_time &&
5827 state -> partner.state !=
recover &&
5830 #if defined (DEBUG_FAILOVER_TIMING) 5833 state -> me.stos + state -> mclt),
5834 "dhcp_failover_recover_done");
5836 tv . tv_sec = (
int)(state -> me.stos + state -> mclt);
5841 (
tvref_t)omapi_object_reference,
5848 return ISC_R_SUCCESS;
5853 dhcp_failover_state_t *state = sp;
5855 #if defined (DEBUG_FAILOVER_TIMING) 5856 log_info (
"dhcp_failover_recover_done");
5862 #if defined (DEBUG_FAILOVER_MESSAGES) 5869 unsigned *obufix,
unsigned obufmax,
const char *s)
5871 int len = strlen (s);
5873 while (len + *obufix + 1 >= obufmax) {
5882 strcpy (&obuf [*obufix], s);
5889 unsigned char loadb_mx_tbl[256] = {
5890 251, 175, 119, 215, 81, 14, 79, 191, 103, 49,
5891 181, 143, 186, 157, 0, 232, 31, 32, 55, 60,
5892 152, 58, 17, 237, 174, 70, 160, 144, 220, 90,
5893 57, 223, 59, 3, 18, 140, 111, 166, 203, 196,
5894 134, 243, 124, 95, 222, 179, 197, 65, 180, 48,
5895 36, 15, 107, 46, 233, 130, 165, 30, 123, 161,
5896 209, 23, 97, 16, 40, 91, 219, 61, 100, 10,
5897 210, 109, 250, 127, 22, 138, 29, 108, 244, 67,
5898 207, 9, 178, 204, 74, 98, 126, 249, 167, 116,
5899 34, 77, 193, 200, 121, 5, 20, 113, 71, 35,
5900 128, 13, 182, 94, 25, 226, 227, 199, 75, 27,
5901 41, 245, 230, 224, 43, 225, 177, 26, 155, 150,
5902 212, 142, 218, 115, 241, 73, 88, 105, 39, 114,
5903 62, 255, 192, 201, 145, 214, 168, 158, 221, 148,
5904 154, 122, 12, 84, 82, 163, 44, 139, 228, 236,
5905 205, 242, 217, 11, 187, 146, 159, 64, 86, 239,
5906 195, 42, 106, 198, 118, 112, 184, 172, 87, 2,
5907 173, 117, 176, 229, 247, 253, 137, 185, 99, 164,
5908 102, 147, 45, 66, 231, 52, 141, 211, 194, 206,
5909 246, 238, 56, 110, 78, 248, 63, 240, 189, 93,
5910 92, 51, 53, 183, 19, 171, 72, 50, 33, 104,
5911 101, 69, 8, 252, 83, 120, 76, 135, 85, 54,
5912 202, 125, 188, 213, 96, 235, 136, 208, 162, 129,
5913 190, 132, 156, 38, 47, 1, 7, 254, 24, 4,
5914 216, 131, 89, 21, 28, 133, 37, 153, 149, 80,
5915 170, 68, 6, 169, 234, 151 };
5917 static unsigned char loadb_p_hash (
const unsigned char *,
unsigned);
5918 static unsigned char loadb_p_hash (
const unsigned char *key,
unsigned len)
5920 unsigned char hash = len;
5922 for(i = len; i > 0; )
5923 hash = loadb_mx_tbl [hash ^ (key [--i])];
5931 unsigned char hbaix;
5935 ec = ntohs(packet->
raw->
secs);
5937 #if defined(SECS_BYTEORDER) 5944 if ((ec > 255) && ((ec & 0xff) == 0)) {
5945 ec = (ec >> 8) | (ec << 8);
5949 if (state->load_balance_max_secs < ec) {
5963 memset(&ds, 0,
sizeof ds);
5968 hbaix = loadb_p_hash(ds.data, ds.len);
5972 hbaix = loadb_p_hash(packet->
raw->
chaddr,
5976 hm = state->hba[(hbaix >> 3) & 0x1F] & (1 << (hbaix & 0x07));
5978 if (state->i_am == primary)
5992 dhcp_failover_state_t *state;
5993 unsigned char hbaix;
6001 if (!state || !state->hba)
6018 hm = state->hba[(hbaix >> 3) & 0x1F] & (1 << (hbaix & 0x07));
6020 if (state->i_am == primary)
6034 dhcp_failover_state_t *state,
6041 if (binding_state == lease -> binding_state)
6042 return binding_state;
6044 switch (lease -> binding_state) {
6047 switch (binding_state) {
6058 if (state -> i_am == secondary)
6059 return binding_state;
6067 new_state = binding_state;
6077 if (state -> i_am == primary) {
6083 return binding_state;
6085 new_state = lease -> binding_state;
6090 switch (binding_state) {
6096 new_state = lease -> binding_state;
6099 return binding_state;
6107 if (lease -> ends - 65 >
cur_time) {
6108 new_state = lease -> binding_state;
6116 return binding_state;
6124 switch (binding_state) {
6130 new_state = lease -> binding_state;
6133 return binding_state;
6140 return binding_state;
6147 switch (binding_state) {
6158 return binding_state;
6165 switch (binding_state) {
6171 new_state = lease -> binding_state;
6174 return binding_state;
6181 return binding_state;
6188 switch (binding_state) {
6197 if (state -> i_am == primary)
6198 return binding_state;
6204 return binding_state;
6207 new_state = lease -> binding_state;
6227 dhcp_failover_state_t *state,
6234 if (binding_state == lease -> binding_state)
6235 new_state = binding_state;
6237 switch (lease -> binding_state) {
6247 new_state = binding_state;
6254 switch (binding_state) {
6257 new_state = lease -> binding_state;
6269 new_state = binding_state;
6280 new_state = binding_state;
6315 dhcp_failover_state_t *peer;
6317 if (lease && lease->
pool &&
6341 if (peer -> i_am == primary)
6345 ((lease->
tsfp < peer->me.stos) ?
6346 (peer->me.stos + peer->mclt <
cur_time) :
6365 if ((peer->i_am == primary) &&
6368 if ((peer->i_am == secondary) &&
6399 if (peer->i_am == secondary)
6403 ((lease->
tsfp < peer->me.stos) ?
6404 (peer->me.stos + peer->mclt <
cur_time) :
6421 static isc_result_t failover_message_reference (failover_message_t **mp,
6422 failover_message_t *m,
6423 const char *file,
int line)
6427 return ISC_R_SUCCESS;
6430 static isc_result_t failover_message_dereference (failover_message_t **mp,
6431 const char *file,
int line)
6433 failover_message_t *m;
6436 if (m -> refcnt == 0) {
6438 failover_message_dereference (&m -> next,
6440 if (m -> chaddr.data)
6441 dfree (m -> chaddr.data, file, line);
6442 if (m -> client_identifier.data)
6443 dfree (m -> client_identifier.data, file, line);
6445 dfree (m -> hba.data, file, line);
6446 if (m -> message.data)
6447 dfree (m -> message.data, file, line);
6448 if (m -> relationship_name.data)
6449 dfree (m -> relationship_name.data, file, line);
6450 if (m -> reply_options.data)
6451 dfree (m -> reply_options.data, file, line);
6452 if (m -> request_options.data)
6453 dfree (m -> request_options.data, file, line);
6454 if (m -> vendor_class.data)
6455 dfree (m -> vendor_class.data, file, line);
6456 if (m -> vendor_options.data)
6457 dfree (m -> vendor_options.data, file, line);
6460 dfree (*mp, file, line);
6463 return ISC_R_SUCCESS;
6525 const char *print_value =
"<none>";
6527 if ((strlen (value) <= 64) &&
6529 print_value = value;
6532 print_value =
"<unsuitable for printing>";
6536 return (print_value);
6547 log_debug (
"%s(%d):scrubbing lease for %s, hostname: %s", file, line,
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
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__
void * dmalloc(size_t, const char *, int)
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)
const char * printable(const char *value)
Given a char pointer, return always return a printable value.
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 db_printable(const unsigned char *)
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)
void scrub_lease(struct lease *lease, const char *file, int line)
Remove information from a prior use of a lease.
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)