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,
68 dhcp_failover_state_t *state;
72 if (state->pool_count == 0) {
73 log_error (
"ERROR: Failover peer, %s, has no referring" 74 " pools. You must refer to each peer in at" 75 " least one pool declaration.",
82 log_fatal (
"Failover configuration sanity check failed");
88 dhcp_failover_state_t *state;
98 #if defined (DEBUG_FAILOVER_TIMING) 99 log_info (
"add_timeout +90 dhcp_failover_reconnect");
106 dhcp_failover_state_reference,
108 dhcp_failover_state_dereference);
109 log_error (
"failover peer %s: %s", state -> name,
110 isc_result_totext (status));
115 if (status != ISC_R_SUCCESS) {
116 #if defined (DEBUG_FAILOVER_TIMING) 118 "dhcp_failover_listener_restart");
133 dhcp_failover_state_t *state;
143 dhcp_failover_state_t *peer;
145 dhcp_failover_state_t *dup = (dhcp_failover_state_t *)0;
149 if (status == ISC_R_NOTFOUND) {
151 dhcp_failover_state_reference (&peer -> next,
157 return ISC_R_SUCCESS;
159 dhcp_failover_state_dereference (&dup,
MDL);
160 if (status == ISC_R_SUCCESS)
166 dhcp_failover_state_t **peer;
171 dhcp_failover_state_t *p;
174 if (!strcmp (name, p -> name))
177 return dhcp_failover_state_reference (peer, p,
file,
line);
178 return ISC_R_NOTFOUND;
200 dhcp_failover_link_t *obj;
201 dhcp_failover_state_t *state;
209 for (o = h; o -> outer; o = o -> outer)
211 for (; o; o = o -> inner) {
217 state = (dhcp_failover_state_t *)o;
219 obj = (dhcp_failover_link_t *)0;
220 status = dhcp_failover_link_allocate (&obj,
MDL);
221 if (status != ISC_R_SUCCESS)
224 state -> partner.address,
MDL);
225 obj -> peer_port = state -> partner.port;
226 dhcp_failover_state_reference (&obj -> state_object, state,
MDL);
228 memset (&ds, 0,
sizeof ds);
234 dhcp_failover_link_dereference (&obj,
MDL);
235 return ISC_R_UNEXPECTED;
241 if (status != ISC_R_SUCCESS) {
242 dhcp_failover_link_dereference (&obj,
MDL);
246 for (i = 0; i < addrs -> count; i++) {
247 addrs -> addresses [i].addrtype = AF_INET;
248 addrs -> addresses [i].addrlen =
sizeof (
struct in_addr);
249 memcpy (addrs -> addresses [i].address,
250 &ds.data [i * 4], sizeof (
struct in_addr));
251 addrs -> addresses [i].port = obj -> peer_port;
256 if (!state -> me.address ||
264 memset (&local_addr, 0,
sizeof local_addr);
266 local_addr.
addrlen =
sizeof (
struct in_addr);
268 log_fatal (
"failover peer %s: no local address.",
272 if (ds.len != sizeof (
struct in_addr)) {
273 log_error(
"failover peer %s: 'address' parameter " 274 "fails to resolve to an IPv4 address",
277 dhcp_failover_link_dereference (&obj,
MDL);
283 memcpy (local_addr.
address, ds.data, ds.len);
295 dhcp_failover_link_dereference (&obj,
MDL);
300 const char *name, va_list ap)
303 dhcp_failover_link_t *link;
305 dhcp_failover_state_t *s, *state = (dhcp_failover_state_t *)0;
312 return ISC_R_UNEXPECTED;
314 link = (dhcp_failover_link_t *)h;
316 if (!strcmp (name,
"connect")) {
317 if (link -> state_object -> i_am == primary) {
319 if (status != ISC_R_SUCCESS) {
320 log_info (
"dhcp_failover_send_connect: %s",
321 isc_result_totext (status));
325 status = ISC_R_SUCCESS;
328 #if defined (DEBUG_FAILOVER_TIMING) 330 "dhcp_failover_link_startup_timeout");
337 (
tvref_t)dhcp_failover_link_reference,
338 (
tvunref_t)dhcp_failover_link_dereference);
342 if (!strcmp (name,
"disconnect")) {
343 if (link -> state_object) {
344 dhcp_failover_state_reference (&state,
345 link -> state_object,
MDL);
346 link -> state = dhcp_flink_disconnected;
349 if (state->link_to_peer == link)
353 #if defined (DEBUG_FAILOVER_TIMING) 354 log_info(
"add_timeout +5 dhcp_failover_reconnect");
357 tv.tv_usec =
cur_tv.tv_usec;
359 (
tvref_t)dhcp_failover_state_reference,
360 (
tvunref_t)dhcp_failover_state_dereference);
362 dhcp_failover_state_dereference (&state,
MDL);
364 return ISC_R_SUCCESS;
367 if (!strcmp (name,
"status")) {
368 if (link -> state_object) {
371 status = va_arg(ap, isc_result_t);
373 if ((status == ISC_R_HOSTUNREACH) || (status == ISC_R_TIMEDOUT)) {
374 dhcp_failover_state_reference (&state,
375 link -> state_object,
MDL);
376 link -> state = dhcp_flink_disconnected;
383 #if defined (DEBUG_FAILOVER_TIMING) 385 "dhcp_failover_reconnect");
391 (
tvref_t)dhcp_failover_state_reference,
392 (
tvunref_t)dhcp_failover_state_dereference);
394 dhcp_failover_state_dereference (&state,
MDL);
396 return ISC_R_SUCCESS;
400 if (strcmp (name,
"ready")) {
401 if (h -> inner && h -> inner -> type -> signal_handler)
402 return (*(h -> inner -> type -> signal_handler))
403 (h -> inner, name, ap);
404 return ISC_R_NOTFOUND;
414 switch (link -> state) {
415 case dhcp_flink_start:
416 link -> state = dhcp_flink_message_length_wait;
419 case dhcp_flink_message_length_wait:
421 link -> state = dhcp_flink_message_wait;
422 link -> imsg =
dmalloc (
sizeof (failover_message_t),
MDL);
424 status = ISC_R_NOMEMORY;
427 failover_message_dereference (&link->imsg,
430 link -> state = dhcp_flink_disconnected;
431 log_info (
"message length wait: %s",
432 isc_result_totext (status));
436 return ISC_R_UNEXPECTED;
438 memset (link -> imsg, 0,
sizeof (failover_message_t));
439 link -> imsg -> refcnt = 1;
442 link -> imsg_count = 0;
445 if (link->imsg_len < DHCP_FAILOVER_MIN_MESSAGE_SIZE ||
446 link->imsg_len > DHCP_FAILOVER_MAX_MESSAGE_SIZE) {
447 status = ISC_R_UNEXPECTED;
448 goto dhcp_flink_fail;
454 case dhcp_flink_message_wait:
464 link -> imsg_count += 2;
468 link -> imsg_count++;
472 link -> imsg_count++;
476 link -> imsg_count += 4;
480 link -> imsg_count += 4;
482 #if defined (DEBUG_FAILOVER_MESSAGES) 483 # if !defined(DEBUG_FAILOVER_CONTACT_MESSAGES) 484 if (link->imsg->type == FTM_CONTACT)
487 log_info (
"link: message %s payoff %d time %ld xid %ld",
490 (
unsigned long)link -> imsg -> time,
491 (
unsigned long)link -> imsg -> xid);
492 # if !defined(DEBUG_FAILOVER_CONTACT_MESSAGES) 498 if (link -> imsg_payoff - link -> imsg_count) {
500 (link -> imsg_payoff -
501 link -> imsg_count));
502 link -> imsg_count = link -> imsg_payoff;
506 while (link -> imsg_count < link -> imsg_len) {
507 status = do_a_failover_option (c, link);
508 if (status != ISC_R_SUCCESS)
509 goto dhcp_flink_fail;
515 if (link -> imsg -> type == FTM_CONNECT) {
519 if (!(link->imsg->options_present &
520 FTB_RELATIONSHIP_NAME)) {
521 errmsg =
"missing relationship-name";
522 reason = FTR_INVALID_PARTNER;
531 &link->imsg->relationship_name))
538 errmsg =
"unknown failover relationship name";
539 reason = FTR_INVALID_PARTNER;
547 slen = strlen(sname);
548 }
else if (link->imsg->options_present &
549 FTB_RELATIONSHIP_NAME) {
550 sname = (
char *)link->imsg->
551 relationship_name.data;
552 slen = link->imsg->relationship_name.count;
555 slen = strlen(sname);
558 log_error(
"Failover CONNECT from %.*s: %s",
559 slen, sname, errmsg);
563 log_info (
"failover: disconnect: %s", errmsg);
565 link -> state = dhcp_flink_disconnected;
566 return ISC_R_SUCCESS;
569 if ((
cur_time > link -> imsg -> time &&
570 cur_time - link -> imsg -> time > 60) ||
571 (cur_time < link -> imsg -> time &&
572 link -> imsg -> time -
cur_time > 60)) {
573 errmsg =
"time offset too large";
574 reason = FTR_TIMEMISMATCH;
578 if (!(link -> imsg -> options_present & FTB_HBA) ||
579 link -> imsg -> hba.count != 32) {
580 errmsg =
"invalid HBA";
581 reason = FTR_HBA_CONFLICT;
588 errmsg =
"no memory";
589 reason = FTR_MISC_REJECT;
592 memcpy (state -> hba, link -> imsg -> hba.data, 32);
594 if (!link -> state_object)
595 dhcp_failover_state_reference
596 (&link -> state_object, state,
MDL);
597 if (!link -> peer_address)
599 (&link -> peer_address,
600 state -> partner.address,
MDL);
606 if (!link -> state_object) {
607 log_info (
"failover: connect: no matching state.");
609 link -> state = dhcp_flink_disconnected;
617 link -> state = dhcp_flink_message_length_wait;
619 failover_message_dereference (&link -> imsg,
MDL);
633 return ISC_R_SUCCESS;
636 static isc_result_t do_a_failover_option (c, link)
638 dhcp_failover_link_t *link;
640 u_int16_t option_code;
641 u_int16_t option_len;
647 if (link -> imsg_count + 2 > link -> imsg_len) {
648 log_error (
"FAILOVER: message overflow at option code.");
652 if (link->imsg->type > FTM_MAX) {
653 log_error (
"FAILOVER: invalid message type: %d",
660 link -> imsg_count += 2;
662 if (link -> imsg_count + 2 > link -> imsg_len) {
663 log_error (
"FAILOVER: message overflow at length.");
669 link -> imsg_count += 2;
671 if (link -> imsg_count + option_len > link -> imsg_len) {
672 log_error (
"FAILOVER: message overflow at data.");
677 if ((option_code > FTO_MAX) ||
679 #if defined (DEBUG_FAILOVER_MESSAGES) 680 log_debug (
" option code %d (%s) len %d (not recognized)",
686 link -> imsg_count += option_len;
687 return ISC_R_SUCCESS;
691 if (
ft_options [option_code].type == FT_DIGEST) {
692 link -> imsg_count += option_len;
693 if (link -> imsg_count != link -> imsg_len) {
694 log_error (
"FAILOVER: digest not at end of message");
697 #if defined (DEBUG_FAILOVER_MESSAGES) 703 return ISC_R_SUCCESS;
707 if (link -> imsg -> options_present &
ft_options [option_code].bit) {
708 log_error (
"FAILOVER: duplicate option %s",
723 link -> imsg_count += option_len;
724 return ISC_R_SUCCESS;
734 op = ((
unsigned char *)link -> imsg) +
737 op_count =
ft_options [option_code].num_present;
739 if (option_len != op_size * op_count) {
740 log_error (
"FAILOVER: option size (%d:%d), option %s",
748 failover_option_t *fo;
755 if (
ft_options [option_code].type == FT_DDNS ||
759 (((
char *)link -> imsg) +
762 op_count = (
ft_options [option_code].type == FT_DDNS1
767 link -> imsg_count += op_count;
769 ddns -> codes [1] = 0;
771 op_count = option_len - op_count;
773 ddns -> length = op_count;
776 log_error (
"FAILOVER: no memory getting%s(%d)",
777 " DNS data ", op_count);
796 if (op_size > 1 && option_len % op_size) {
797 log_error (
"FAILOVER: option_len %d not %s%d",
798 option_len,
"multiple of ", op_size);
802 op_count = option_len / op_size;
804 fo = ((failover_option_t *)
805 (((
char *)link -> imsg) +
808 fo -> count = op_count;
811 log_error (
"FAILOVER: no memory getting %s (%d)",
812 "option data", op_count);
821 if (op_size == 1 ||
ft_options [option_code].type == FT_IPADDR) {
823 link -> imsg_count += option_len;
846 if ((option_code == 11) && (option_len > 9) &&
847 (strncmp((
const char *)op,
"isc-V3.0.", 9) == 0)) {
848 log_error(
"WARNING: failover as of versions 3.1.0 and " 849 "on are not reverse compatible with " 858 for (i = 0; i < op_count; i++) {
863 link -> imsg_count += 4;
869 link -> imsg_count += 2;
875 log_error (
"FAILOVER: option %s: bad type %d",
883 link -> imsg -> options_present |=
ft_options [option_code].bit;
884 return ISC_R_SUCCESS;
901 if (h -> inner && h -> inner -> type -> set_value)
902 return (*(h -> inner -> type -> set_value))
903 (h -> inner, id, name, value);
904 return ISC_R_NOTFOUND;
912 dhcp_failover_link_t *link;
916 link = (dhcp_failover_link_t *)h;
920 (
int)link -> peer_port,
MDL);
922 if (link -> state >= dhcp_flink_state_max)
924 "invalid link state",
931 if (h -> inner && h -> inner -> type -> get_value)
932 return (*(h -> inner -> type -> get_value))
933 (h -> inner, id, name, value);
934 return ISC_R_NOTFOUND;
940 dhcp_failover_link_t *link;
943 link = (dhcp_failover_link_t *)h;
945 if (link -> peer_address)
948 failover_message_dereference (&link -> imsg,
file,
line);
949 if (link -> state_object)
950 dhcp_failover_state_dereference (&link -> state_object,
952 return ISC_R_SUCCESS;
962 dhcp_failover_link_t *link;
967 link = (dhcp_failover_link_t *)l;
970 if (status != ISC_R_SUCCESS)
973 if (status != ISC_R_SUCCESS)
976 if (status != ISC_R_SUCCESS)
980 if (status != ISC_R_SUCCESS)
982 if (link -> state >= dhcp_flink_state_max)
987 if (status != ISC_R_SUCCESS)
990 if (link -> inner && link -> inner -> type -> stuff_values)
991 return (*(link -> inner -> type -> stuff_values)) (c,
id,
993 return ISC_R_SUCCESS;
1001 isc_result_t status;
1008 "local-port", &value);
1009 if (status != ISC_R_SUCCESS)
1011 if (!value -> value) {
1018 if (status != ISC_R_SUCCESS)
1020 local_addr.
port = port;
1023 "local-address", &value);
1024 if (status != ISC_R_SUCCESS)
1026 if (!value -> value) {
1033 value -> value -> u.buffer.len != sizeof (
struct in_addr))
1036 memcpy (local_addr.
address, value -> value -> u.buffer.
value,
1037 value -> value -> u.buffer.len);
1038 local_addr.
addrlen = value -> value -> u.buffer.len;
1044 for (l = failover_listeners; l; l = l -> next) {
1045 if (l -> address.port == local_addr.
port &&
1046 l -> address.addrtype == local_addr.
addrtype &&
1047 l -> address.addrlen == local_addr.
addrlen &&
1048 !memcmp (l -> address.address, local_addr.
address,
1054 return ISC_R_SUCCESS;
1057 status = dhcp_failover_listener_allocate (&obj,
MDL);
1058 if (status != ISC_R_SUCCESS)
1060 obj -> address = local_addr;
1063 if (status != ISC_R_SUCCESS)
1068 if (status != ISC_R_SUCCESS) {
1069 dhcp_failover_listener_dereference (&obj,
MDL);
1073 if (status != ISC_R_SUCCESS) {
1074 dhcp_failover_listener_dereference (&obj,
MDL);
1079 if (failover_listeners) {
1080 dhcp_failover_listener_reference (&obj -> next,
1081 failover_listeners,
MDL);
1082 dhcp_failover_listener_dereference (&failover_listeners,
MDL);
1084 dhcp_failover_listener_reference (&failover_listeners, obj,
MDL);
1086 return dhcp_failover_listener_dereference (&obj,
MDL);
1093 const char *name, va_list ap)
1095 isc_result_t status;
1097 dhcp_failover_link_t *obj;
1099 dhcp_failover_state_t *s, *state = (dhcp_failover_state_t *)0;
1106 if (strcmp (name,
"connect")) {
1107 if (p -> inner && p -> inner -> type -> signal_handler)
1108 return (*(p -> inner -> type -> signal_handler))
1109 (p -> inner, name, ap);
1110 return ISC_R_NOTFOUND;
1121 (s, (u_int8_t *)&c -> remote_addr.sin_addr,
1122 sizeof c -> remote_addr.sin_addr)) {
1128 log_info (
"failover: listener: no matching state");
1130 return(ISC_R_NOTFOUND);
1133 obj = (dhcp_failover_link_t *)0;
1134 status = dhcp_failover_link_allocate (&obj,
MDL);
1135 if (status != ISC_R_SUCCESS)
1137 obj -> peer_port = ntohs (c -> remote_addr.sin_port);
1141 if (status != ISC_R_SUCCESS) {
1143 dhcp_failover_link_dereference (&obj,
MDL);
1144 log_info (
"failover: listener: picayune failure.");
1151 if (status != ISC_R_SUCCESS)
1154 status = dhcp_failover_state_reference (&obj -> state_object,
1156 if (status != ISC_R_SUCCESS)
1161 return dhcp_failover_link_dereference (&obj,
MDL);
1172 if (h -> inner && h -> inner -> type -> set_value)
1173 return (*(h -> inner -> type -> set_value))
1174 (h -> inner, id, name, value);
1175 return ISC_R_NOTFOUND;
1186 if (h -> inner && h -> inner -> type -> get_value)
1187 return (*(h -> inner -> type -> get_value))
1188 (h -> inner, id, name, value);
1189 return ISC_R_NOTFOUND;
1201 dhcp_failover_listener_dereference (&l -> next,
file,
line);
1203 return ISC_R_SUCCESS;
1216 if (p -> inner && p -> inner -> type -> stuff_values)
1217 return (*(p -> inner -> type -> stuff_values)) (c, id,
1219 return ISC_R_SUCCESS;
1226 isc_result_t status;
1227 dhcp_failover_state_t *obj;
1232 "local-port", &value);
1233 if (status != ISC_R_SUCCESS)
1235 if (!value -> value) {
1242 if (status != ISC_R_SUCCESS)
1245 obj = (dhcp_failover_state_t *)0;
1246 dhcp_failover_state_allocate (&obj,
MDL);
1247 obj -> me.port = port;
1250 if (status != ISC_R_SUCCESS) {
1251 dhcp_failover_state_dereference (&obj,
MDL);
1257 if (status != ISC_R_SUCCESS) {
1258 dhcp_failover_state_dereference (&obj,
MDL);
1262 dhcp_failover_state_dereference (&obj,
MDL);
1269 const char *name, va_list ap)
1271 isc_result_t status;
1272 dhcp_failover_state_t *state;
1273 dhcp_failover_link_t *link;
1278 state = (dhcp_failover_state_t *)o;
1281 if (strcmp (name,
"disconnect") &&
1282 strcmp (name,
"message")) {
1283 if (state -> inner && state -> inner -> type -> signal_handler)
1284 return (*(state -> inner -> type -> signal_handler))
1285 (state -> inner, name, ap);
1286 return ISC_R_NOTFOUND;
1291 if (!strcmp (name,
"disconnect")) {
1292 link = va_arg (ap, dhcp_failover_link_t *);
1294 dhcp_failover_link_dereference (&state -> link_to_peer,
MDL);
1296 if (state -> i_am == primary) {
1297 #if defined (DEBUG_FAILOVER_TIMING) 1299 "dhcp_failover_reconnect");
1305 (
tvref_t)dhcp_failover_state_reference,
1307 dhcp_failover_state_dereference);
1309 }
else if (!strcmp (name,
"message")) {
1310 link = va_arg (ap, dhcp_failover_link_t *);
1312 if (link -> imsg -> type == FTM_CONNECT) {
1318 if (state -> link_to_peer) {
1322 "already connected");
1324 return ISC_R_SUCCESS;
1326 if (!(link -> imsg -> options_present & FTB_MCLT)) {
1330 "no MCLT provided");
1332 return ISC_R_SUCCESS;
1335 dhcp_failover_link_reference (&state -> link_to_peer,
1339 if (status != ISC_R_SUCCESS) {
1340 dhcp_failover_link_dereference
1341 (&state -> link_to_peer,
MDL);
1342 log_info (
"dhcp_failover_send_connectack: %s",
1343 isc_result_totext (status));
1345 return ISC_R_SUCCESS;
1347 if (link -> imsg -> options_present & FTB_MAX_UNACKED)
1348 state -> partner.max_flying_updates =
1349 link -> imsg -> max_unacked;
1350 if (link -> imsg -> options_present & FTB_RECEIVE_TIMER)
1351 state -> partner.max_response_delay =
1352 link -> imsg -> receive_timer;
1353 state -> mclt = link -> imsg -> mclt;
1357 }
else if (link -> imsg -> type == FTM_CONNECTACK) {
1365 if (!(link->imsg->options_present &
1366 FTB_RELATIONSHIP_NAME)) {
1367 errmsg =
"missing relationship-name";
1368 reason = FTR_INVALID_PARTNER;
1372 if (link->imsg->options_present & FTB_REJECT_REASON) {
1374 log_error (
"Failover CONNECT to %s rejected: %s",
1375 state ? state->name :
"unknown",
1377 (link -> imsg -> reject_reason)));
1380 return ISC_R_SUCCESS;
1384 &link->imsg->relationship_name)) {
1386 snprintf(errbuf,
sizeof(errbuf),
"remote failover " 1387 "relationship name %.*s does not match",
1388 (
int)link->imsg->relationship_name.count,
1389 link->imsg->relationship_name.data);
1391 reason = FTR_INVALID_PARTNER;
1393 log_error(
"Failover CONNECTACK from %s: %s",
1394 state->name, errmsg);
1398 return ISC_R_SUCCESS;
1401 if (state -> link_to_peer) {
1402 errmsg =
"already connected";
1403 reason = FTR_DUP_CONNECTION;
1407 if ((
cur_time > link -> imsg -> time &&
1408 cur_time - link -> imsg -> time > 60) ||
1409 (cur_time < link -> imsg -> time &&
1410 link -> imsg -> time -
cur_time > 60)) {
1411 errmsg =
"time offset too large";
1412 reason = FTR_TIMEMISMATCH;
1416 dhcp_failover_link_reference (&state -> link_to_peer,
1423 if (state -> me.state ==
startup)
1425 state -> saved_state);
1430 if (link -> imsg -> options_present & FTB_MAX_UNACKED)
1431 state -> partner.max_flying_updates =
1432 link -> imsg -> max_unacked;
1433 if (link -> imsg -> options_present & FTB_RECEIVE_TIMER)
1434 state -> partner.max_response_delay =
1435 link -> imsg -> receive_timer;
1436 #if defined (DEBUG_FAILOVER_CONTACT_TIMING) 1438 (
int)state -> partner.max_response_delay / 3,
1439 "dhcp_failover_send_contact");
1442 (
int)state -> partner.max_response_delay / 3;
1446 (
tvref_t)dhcp_failover_state_reference,
1447 (
tvunref_t)dhcp_failover_state_dereference);
1448 #if defined (DEBUG_FAILOVER_CONTACT_TIMING) 1450 (
int)state -> me.max_response_delay,
1451 "dhcp_failover_timeout");
1454 (
int)state -> me.max_response_delay;
1458 (
tvref_t)dhcp_failover_state_reference,
1459 (
tvunref_t)dhcp_failover_state_dereference);
1460 }
else if (link -> imsg -> type == FTM_DISCONNECT) {
1461 if (link -> imsg -> reject_reason) {
1462 log_error (
"Failover DISCONNECT from %s: %s",
1463 state ? state->name :
"unknown",
1465 (link -> imsg -> reject_reason)));
1468 }
else if (link -> imsg -> type == FTM_BNDUPD) {
1471 }
else if (link -> imsg -> type == FTM_BNDACK) {
1473 }
else if (link -> imsg -> type == FTM_UPDREQ) {
1476 }
else if (link -> imsg -> type == FTM_UPDREQALL) {
1478 (state, link -> imsg);
1479 }
else if (link -> imsg -> type == FTM_UPDDONE) {
1482 }
else if (link -> imsg -> type == FTM_POOLREQ) {
1483 dhcp_failover_pool_reqbalance(state);
1484 }
else if (link -> imsg -> type == FTM_POOLRESP) {
1485 log_info (
"pool response: %ld leases",
1487 link -> imsg -> addresses_transferred);
1488 }
else if (link -> imsg -> type == FTM_STATE) {
1497 if (state -> link_to_peer &&
1498 state -> link_to_peer == link &&
1499 state -> link_to_peer -> state != dhcp_flink_disconnected)
1501 #if defined (DEBUG_FAILOVER_CONTACT_TIMING) 1503 (
int)state -> me.max_response_delay,
1504 "dhcp_failover_timeout");
1507 (
int)state -> me.max_response_delay;
1511 (
tvref_t)dhcp_failover_state_reference,
1512 (
tvunref_t)dhcp_failover_state_dereference);
1518 return ISC_R_SUCCESS;
1524 isc_result_t status;
1527 if (!strcmp (name,
"disconnect")) {
1528 if (state -> link_to_peer) {
1529 log_info (
"peer %s: disconnected", state -> name);
1530 if (state -> link_to_peer -> state_object)
1531 dhcp_failover_state_dereference
1532 (&state -> link_to_peer -> state_object,
MDL);
1533 dhcp_failover_link_dereference (&state -> link_to_peer,
1540 switch (state -> me.state ==
startup ?
1541 state -> saved_state : state -> me.state) {
1563 if (state -> me.state ==
startup)
1565 (state, state -> saved_state));
1566 return ISC_R_SUCCESS;
1584 }
else if (!strcmp (name,
"connect")) {
1585 switch (state -> me.state) {
1612 }
else if (!strcmp (name,
"startup")) {
1614 return ISC_R_SUCCESS;
1615 }
else if (!strcmp (name,
"connect-timeout")) {
1616 switch (state -> me.state) {
1624 return ISC_R_SUCCESS;
1648 switch (state -> me.state) {
1651 state -> nrr =
" (my state unknown)";
1673 state -> nrr =
" (resolving conflicts)";
1678 state -> nrr =
" (recovering)";
1683 state -> nrr =
" (shut down)";
1688 state -> nrr =
" (paused)";
1693 state -> nrr =
" (recover wait)";
1698 state -> nrr =
" (recover done)";
1703 state -> nrr =
" (startup)";
1715 switch (state -> partner.state) {
1718 state -> nrr =
" (peer demands: recovering)";
1725 state -> nrr =
" (peer demands: resolving conflicts)";
1734 return ISC_R_SUCCESS;
1753 if (
state->ack_queue_tail == NULL)
1761 if (
state->update_queue_head) {
1762 lease_reference(&
state->ack_queue_tail->next_pending,
1764 lease_dereference(&
state->update_queue_head,
MDL);
1766 lease_reference(&
state->update_queue_head,
state->ack_queue_head,
MDL);
1768 if (!
state->update_queue_tail) {
1769 #if defined (POINTER_DEBUG) 1770 if (
state->ack_queue_tail->next_pending) {
1771 log_error(
"next pending on ack queue tail.");
1775 lease_reference(&
state->update_queue_tail,
1778 lease_dereference(&
state->ack_queue_tail,
MDL);
1779 lease_dereference(&
state->ack_queue_head,
MDL);
1780 state->cur_unacked_updates = 0;
1797 switch (state -> me.state) {
1813 saved_state = state -> me.state;
1814 saved_stos = state -> me.stos;
1829 !state -> update_queue_head && !state -> ack_queue_head)
1830 state -> me.stos =
cur_time - state -> mclt;
1832 state -> me.state = new_state;
1834 state -> saved_state = saved_state;
1838 log_error (
"Unable to record current failover state for %s",
1840 state -> me.state = saved_state;
1841 state -> me.stos = saved_stos;
1842 return ISC_R_IOERROR;
1845 log_info (
"failover peer %s: I move from %s to %s",
1850 if ((state->me.state ==
normal) && (state->partner.state ==
normal))
1851 log_info(
"failover peer %s: Both servers normal", state->name);
1867 if (state -> link_to_peer)
1870 switch (new_state) {
1880 if (state->auto_partner_down == 0)
1883 #if defined (DEBUG_FAILOVER_TIMING) 1884 log_info(
"add_timeout +%lu dhcp_failover_auto_partner_down",
1885 (
unsigned long)state->auto_partner_down);
1887 tv.tv_sec =
cur_time + state->auto_partner_down;
1900 dhcp_failover_pool_balance(state);
1903 if (state->update_queue_tail != NULL) {
1905 log_info(
"Sending updates to %s.", state->name);
1911 if ((state->i_am == primary) ||
1912 ((state->i_am == secondary) &&
1918 #if defined (DEBUG_FAILOVER_TIMING) 1920 "dhcp_failover_startup_timeout");
1935 if (state -> me.stos + state -> mclt >
cur_time) {
1936 #if defined (DEBUG_FAILOVER_TIMING) 1939 state -> me.stos + state -> mclt),
1940 "dhcp_failover_startup_timeout");
1942 tv . tv_sec = (
int)(state -> me.stos + state -> mclt);
1959 if (state -> link_to_peer)
1967 #if defined (BINARY_LEASES) 1968 long int tiebreaker = 0;
1974 l->
tsfp = state->me.stos + state->mclt;
1982 if (tiebreaker != LONG_MAX)
1992 #if defined (DEBUG_FAILOVER_TIMING) 2012 return ISC_R_SUCCESS;
2016 failover_message_t *msg)
2022 new_state = msg -> server_state;
2023 startupp = (msg -> server_flags & FTF_SERVER_STARTUP) ? 1 : 0;
2025 if (state -> partner.state == new_state && state -> me.state) {
2026 switch (state -> me.state) {
2039 state->saved_state);
2040 return ISC_R_SUCCESS;
2049 return ISC_R_SUCCESS;
2066 state -> partner.state = new_state;
2069 log_info (
"failover peer %s: peer moves from %s to %s",
2075 if ((state->me.state ==
normal) && (state->partner.state ==
normal))
2076 log_info(
"failover peer %s: Both servers normal", state->name);
2082 log_error (
"Unable to record current failover state for %s",
2089 switch (new_state) {
2106 log_error(
"failover peer %s: Invalid state: %d", state->name,
2109 return ISC_R_SUCCESS;
2115 switch (state -> me.state ==
startup ?
2116 state -> saved_state : state -> me.state) {
2118 switch (new_state) {
2124 if (state -> me.state ==
startup)
2135 log_error(
"Peer %s: Invalid state transition %s " 2136 "to %s.", state->name,
2161 switch (new_state) {
2163 log_info (
"failover peer %s: requesting %s",
2164 state -> name,
"full update from peer");
2168 if (state -> me.state ==
recover)
2194 if (state -> me.state ==
recover)
2215 switch (new_state) {
2218 log_error(
"Peer %s moves to normal during conflict " 2219 "resolution - panic, shutting down.",
2228 log_error(
"Peer %s: Unexpected move to " 2229 "conflict-done.", state->name);
2256 switch (new_state) {
2274 log_fatal(
"Peer %s: Invalid attempt to move from %s " 2275 "to %s while local state is conflict-done.",
2287 switch (new_state) {
2313 switch (new_state) {
2353 switch (new_state) {
2381 switch (new_state) {
2383 log_error(
"Both servers have entered recover-done!");
2424 if (state -> me.state ==
startup && state -> saved_state !=
startup)
2431 return ISC_R_SUCCESS;
2440 dhcp_failover_pool_balance(dhcp_failover_state_t *state)
2444 state->sched_balance = 0;
2446 dhcp_failover_pool_dobalance(state, NULL);
2457 dhcp_failover_state_t *state;
2458 isc_boolean_t sendreq = ISC_FALSE;
2463 state->sched_balance = 0;
2465 if (dhcp_failover_pool_dobalance(state, &sendreq))
2477 dhcp_failover_pool_reqbalance(dhcp_failover_state_t *state)
2483 state->sched_balance = 0;
2485 queued = dhcp_failover_pool_dobalance(state, NULL);
2492 log_info(
"peer %s: Got POOLREQ, answering negatively! " 2493 "Peer may be out of leases or database inconsistent.",
2505 dhcp_failover_pool_dobalance(dhcp_failover_state_t *state,
2506 isc_boolean_t *sendreq)
2508 int lts, total, thresh, hold, panic, pass;
2509 int leases_queued = 0;
2510 struct lease *lp = NULL;
2512 struct lease *ltemp = NULL;
2519 int (*log_func)(
const char *, ...);
2520 const char *result, *reqlog;
2522 if (state -> me.state !=
normal)
2552 thresh = ((total * state->max_lease_misbalance) + 50) / 100;
2553 hold = ((total * state->max_lease_ownership) + 50) / 100;
2568 panic = thresh * -2;
2573 if ((sendreq != NULL) && (lts < panic)) {
2574 reqlog =
" (requesting peer rebalance!)";
2575 *sendreq = ISC_TRUE;
2579 log_info(
"balancing pool %lx %s total %d free %d " 2580 "backup %d lts %d max-own (+/-)%d%s",
2582 (p->shared_network ?
2583 p->shared_network->name :
""), p->lease_count,
2584 p->free_leases, p->backup_leases, lts, hold,
2604 lease_dereference(&
next,
MDL);
2607 lease_reference(&
next, ltemp,
MDL);
2634 }
else if (lts <= -hold)
2651 lease_dereference(&lp,
MDL);
2653 lease_reference(&lp,
next,
MDL);
2661 lease_dereference(&
next,
MDL);
2663 lease_dereference(&lp,
MDL);
2666 result =
"IMBALANCED";
2669 result =
"balanced";
2673 log_func(
"%s pool %lx %s total %d free %d backup %d " 2674 "lts %d max-misbal %d", result, (
unsigned long)p,
2675 (p->shared_network ?
2676 p->shared_network->name :
""), p->lease_count,
2677 p->free_leases, p->backup_leases, lts, thresh);
2687 return leases_queued;
2697 dhcp_failover_state_t *peer;
2700 struct lease *ltemp;
2704 if(!peer || peer->me.state !=
normal)
2733 est1 = ((est1 * peer->max_lease_misbalance) + 50) / 100;
2734 est2 = ((est2 * peer->max_lease_misbalance) + 50) / 100;
2739 if(peer->i_am == primary)
2749 if(est1 > peer->max_balance)
2750 est1 = peer->max_balance;
2756 est2 = peer->last_balance + peer->min_balance;
2757 if(peer->last_balance && (est1 < est2))
2761 est1 += random() % 5;
2764 if(peer->sched_balance) {
2765 if (est1 >= peer->sched_balance)
2775 peer->sched_balance = est1;
2777 #if defined(DEBUG_FAILOVER_TIMING) 2778 log_info(
"add_timeout +%d dhcp_failover_pool_rebalance",
2784 (
tvref_t)dhcp_failover_state_reference,
2785 (
tvunref_t)dhcp_failover_state_dereference);
2794 for (p = s ->
pools; p; p = p ->
next) {
2806 isc_result_t status;
2809 if (!
state -> link_to_peer)
2810 return ISC_R_SUCCESS;
2815 if (
state->toack_queue_head != NULL)
2818 while ((
state -> partner.max_flying_updates >
2819 state -> cur_unacked_updates) &&
state -> update_queue_head) {
2821 lease_reference (&lp,
state -> update_queue_head,
MDL);
2825 if (status != ISC_R_SUCCESS) {
2826 lease_dereference (&lp,
MDL);
2833 lease_dereference (&
state -> update_queue_head,
MDL);
2835 lease_reference (&
state -> update_queue_head,
2839 lease_dereference (&
state -> update_queue_tail,
MDL);
2842 if (
state -> ack_queue_head) {
2846 lease_dereference (&
state -> ack_queue_tail,
MDL);
2848 lease_reference (&
state -> ack_queue_head, lp,
MDL);
2850 #if defined (POINTER_DEBUG) 2852 log_error (
"ack_queue_tail: lp -> next_pending");
2856 lease_reference (&
state -> ack_queue_tail, lp,
MDL);
2858 lease_dereference (&lp,
MDL);
2861 state -> cur_unacked_updates++;
2863 return ISC_R_SUCCESS;
2872 dhcp_failover_state_t *
state;
2889 if (
state -> update_queue_head) {
2892 lease_dereference (&
state -> update_queue_tail,
MDL);
2896 #if defined (POINTER_DEBUG) 2898 log_error (
"next pending on update queue lease.");
2899 #if defined (DEBUG_RC_HISTORY) 2900 dump_rc_history (
lease);
2914 failover_message_t *msg = (failover_message_t *)0;
2920 while (
state -> toack_queue_head) {
2921 failover_message_reference
2922 (&msg,
state -> toack_queue_head,
MDL);
2923 failover_message_dereference
2926 failover_message_reference
2932 failover_message_dereference (&msg,
MDL);
2935 if (
state -> toack_queue_tail)
2936 failover_message_dereference (&
state -> toack_queue_tail,
MDL);
2937 state -> pending_acks = 0;
2944 dhcp_failover_state_t *
state = vs;
2946 #if defined (DEBUG_FAILOVER_TIMING) 2947 log_info (
"dhcp_failover_toack_queue_timeout");
2957 failover_message_t *msg)
2961 if (state -> toack_queue_head) {
2962 failover_message_reference
2963 (&state -> toack_queue_tail -> next, msg,
MDL);
2964 failover_message_dereference (&state -> toack_queue_tail,
MDL);
2966 failover_message_reference (&state -> toack_queue_head,
2969 failover_message_reference (&state -> toack_queue_tail, msg,
MDL);
2971 state -> pending_acks++;
2975 if (state -> pending_acks >= state -> partner.max_flying_updates / 2) {
2980 if (state -> pending_acks > 0) {
2981 #if defined (DEBUG_FAILOVER_TIMING) 2983 "dhcp_failover_toack_queue_timeout");
2989 (
tvref_t)dhcp_failover_state_reference,
2990 (
tvunref_t)dhcp_failover_state_dereference);
3005 lease_dereference (&
state -> ack_queue_head,
MDL);
3007 lease_reference (&
state -> ack_queue_head,
3011 lease_dereference (&
state -> ack_queue_tail,
MDL);
3014 for (lp =
state -> ack_queue_head;
3028 lease_dereference (&
state -> ack_queue_tail,
MDL);
3033 lease_reference (&
state -> ack_queue_tail, lp,
MDL);
3044 state -> cur_unacked_updates--;
3051 if (
state -> cur_unacked_updates == 0) {
3061 isc_result_t status;
3071 return ISC_R_SUCCESS;
3073 return ISC_R_SUCCESS;
3075 return ISC_R_SUCCESS;
3077 return ISC_R_SUCCESS;
3079 return ISC_R_SUCCESS;
3081 return ISC_R_SUCCESS;
3083 return ISC_R_SUCCESS;
3085 return ISC_R_SUCCESS;
3087 return ISC_R_SUCCESS;
3089 return ISC_R_SUCCESS;
3093 if (status != ISC_R_SUCCESS)
3097 return ISC_R_SUCCESS;
3099 return ISC_R_SUCCESS;
3101 return ISC_R_SUCCESS;
3103 return ISC_R_SUCCESS;
3105 return ISC_R_SUCCESS;
3107 return ISC_R_SUCCESS;
3109 return ISC_R_SUCCESS;
3111 return ISC_R_SUCCESS;
3114 if (h -> inner && h -> inner -> type -> set_value)
3115 return (*(h -> inner -> type -> set_value))
3116 (h -> inner, id, name, value);
3117 return ISC_R_NOTFOUND;
3126 dhcp_failover_state_t *
state = vs;
3127 isc_result_t status;
3130 #if defined (DEBUG_FAILOVER_TIMING) 3131 log_info (
"dhcp_failover_reconnect");
3135 if (state -> link_to_peer)
3140 log_info (
"failover peer %s: %s", state -> name,
3141 isc_result_totext (status));
3142 #if defined (DEBUG_FAILOVER_TIMING) 3143 log_info(
"add_timeout +90 dhcp_failover_reconnect");
3148 (
tvref_t)dhcp_failover_state_reference,
3149 (
tvunref_t)dhcp_failover_state_dereference);
3155 dhcp_failover_state_t *state = vs;
3157 #if defined (DEBUG_FAILOVER_TIMING) 3158 log_info (
"dhcp_failover_startup_timeout");
3166 dhcp_failover_link_t *link = vl;
3171 for (; p; p = p -> outer)
3175 log_info (
"failover: link startup timeout");
3182 dhcp_failover_state_t *state = vs;
3183 isc_result_t status;
3186 #if defined (DEBUG_FAILOVER_TIMING) 3187 log_info (
"dhcp_failover_listener_restart");
3191 if (status != ISC_R_SUCCESS) {
3192 log_info (
"failover peer %s: %s", state -> name,
3193 isc_result_totext (status));
3194 #if defined (DEBUG_FAILOVER_TIMING) 3196 "dhcp_failover_listener_restart");
3202 (
tvref_t)dhcp_failover_state_reference,
3203 (
tvunref_t)dhcp_failover_state_dereference);
3210 dhcp_failover_state_t *state = vs;
3212 #if defined (DEBUG_FAILOVER_TIMING) 3213 log_info(
"dhcp_failover_auto_partner_down");
3224 dhcp_failover_state_t *s;
3227 isc_result_t status;
3231 s = (dhcp_failover_state_t *)h;
3236 name, s -> name,
MDL);
3237 return ISC_R_NOTFOUND;
3239 oc = s -> partner.address;
3241 memset (&ds, 0,
sizeof ds);
3248 return ISC_R_NOTFOUND;
3251 name, ds.data, ds.len,
MDL);
3258 oc = s -> me.address;
3262 s -> partner.port,
MDL);
3265 name, s -> me.port,
MDL);
3268 s -> me.max_flying_updates,
3274 s -> load_balance_max_secs,
MDL);
3279 return ISC_R_NOTFOUND;
3282 s -> partner.state,
MDL);
3285 s -> me.state,
MDL);
3288 s -> partner.stos,
MDL);
3296 s -> last_packet_sent,
MDL);
3299 s -> last_timestamp_received,
3305 s -> me.max_response_delay,
3309 s -> cur_unacked_updates,
MDL);
3312 if (h -> inner && h -> inner -> type -> get_value)
3313 return (*(h -> inner -> type -> get_value))
3314 (h -> inner, id, name, value);
3315 return ISC_R_NOTFOUND;
3321 dhcp_failover_state_t *s;
3325 s = (dhcp_failover_state_t *)h;
3327 if (s -> link_to_peer)
3328 dhcp_failover_link_dereference (&s -> link_to_peer,
file,
line);
3331 s -> name = (
char *)0;
3333 if (s -> partner.address)
3335 if (s -> me.address)
3339 s -> hba = (u_int8_t *)0;
3341 if (s -> update_queue_head)
3342 lease_dereference (&s -> update_queue_head,
file,
line);
3343 if (s -> update_queue_tail)
3344 lease_dereference (&s -> update_queue_tail,
file,
line);
3345 if (s -> ack_queue_head)
3346 lease_dereference (&s -> ack_queue_head,
file,
line);
3347 if (s -> ack_queue_tail)
3348 lease_dereference (&s -> ack_queue_tail,
file,
line);
3349 if (s -> send_update_done)
3350 lease_dereference (&s -> send_update_done,
file,
line);
3351 if (s -> toack_queue_head)
3352 failover_message_dereference (&s -> toack_queue_head,
3354 if (s -> toack_queue_tail)
3355 failover_message_dereference (&s -> toack_queue_tail,
3357 return ISC_R_SUCCESS;
3369 dhcp_failover_state_t *s;
3370 isc_result_t status;
3377 s = (dhcp_failover_state_t *)h;
3380 if (status != ISC_R_SUCCESS)
3383 if (status != ISC_R_SUCCESS)
3387 if (status != ISC_R_SUCCESS)
3390 if (status != ISC_R_SUCCESS)
3393 sizeof s -> partner.address);
3394 if (status != ISC_R_SUCCESS)
3398 if (status != ISC_R_SUCCESS)
3401 if (status != ISC_R_SUCCESS)
3404 if (status != ISC_R_SUCCESS)
3408 if (status != ISC_R_SUCCESS)
3411 if (status != ISC_R_SUCCESS)
3414 sizeof s -> me.address);
3415 if (status != ISC_R_SUCCESS)
3419 if (status != ISC_R_SUCCESS)
3422 if (status != ISC_R_SUCCESS)
3425 if (status != ISC_R_SUCCESS)
3429 if (status != ISC_R_SUCCESS)
3432 if (status != ISC_R_SUCCESS)
3435 s -> me.max_flying_updates);
3436 if (status != ISC_R_SUCCESS)
3440 if (status != ISC_R_SUCCESS)
3443 if (status != ISC_R_SUCCESS)
3446 if (status != ISC_R_SUCCESS)
3450 if (status != ISC_R_SUCCESS)
3453 if (status != ISC_R_SUCCESS)
3456 (c, (u_int32_t)s -> load_balance_max_secs));
3457 if (status != ISC_R_SUCCESS)
3463 if (status != ISC_R_SUCCESS)
3466 if (status != ISC_R_SUCCESS)
3469 if (status != ISC_R_SUCCESS)
3474 if (status != ISC_R_SUCCESS)
3477 if (status != ISC_R_SUCCESS)
3480 if (status != ISC_R_SUCCESS)
3484 if (status != ISC_R_SUCCESS)
3487 if (status != ISC_R_SUCCESS)
3490 if (status != ISC_R_SUCCESS)
3494 if (status != ISC_R_SUCCESS)
3497 if (status != ISC_R_SUCCESS)
3500 (u_int32_t)s -> partner.stos);
3501 if (status != ISC_R_SUCCESS)
3505 if (status != ISC_R_SUCCESS)
3508 if (status != ISC_R_SUCCESS)
3511 if (status != ISC_R_SUCCESS)
3515 if (status != ISC_R_SUCCESS)
3518 if (status != ISC_R_SUCCESS)
3521 if (status != ISC_R_SUCCESS)
3525 if (status != ISC_R_SUCCESS)
3528 if (status != ISC_R_SUCCESS)
3531 (c, (u_int32_t)s -> last_packet_sent));
3532 if (status != ISC_R_SUCCESS)
3536 if (status != ISC_R_SUCCESS)
3539 if (status != ISC_R_SUCCESS)
3542 (c, (u_int32_t)s -> last_timestamp_received));
3543 if (status != ISC_R_SUCCESS)
3547 if (status != ISC_R_SUCCESS)
3550 if (status != ISC_R_SUCCESS)
3553 if (status != ISC_R_SUCCESS)
3557 if (status != ISC_R_SUCCESS)
3560 if (status != ISC_R_SUCCESS)
3563 (c, (u_int32_t)s -> me.max_response_delay));
3564 if (status != ISC_R_SUCCESS)
3568 if (status != ISC_R_SUCCESS)
3571 if (status != ISC_R_SUCCESS)
3574 (c, (u_int32_t)s -> cur_unacked_updates));
3575 if (status != ISC_R_SUCCESS)
3578 if (h -> inner && h -> inner -> type -> stuff_values)
3579 return (*(h -> inner -> type -> stuff_values)) (c,
id,
3581 return ISC_R_SUCCESS;
3589 isc_result_t status;
3590 dhcp_failover_state_t *s;
3597 if (status == ISC_R_SUCCESS) {
3601 if (status != ISC_R_SUCCESS)
3613 if (status == ISC_R_SUCCESS) {
3615 unsigned l = strlen (s -> name);
3616 if (l == tv -> value -> u.buffer.len &&
3618 tv -> value -> u.buffer.value, l))
3631 return ISC_R_NOTFOUND;
3642 return ISC_R_SUCCESS;
3648 return ISC_R_NOTIMPLEMENTED;
3654 return ISC_R_NOTIMPLEMENTED;
3658 u_int8_t *addr,
unsigned addrlen)
3663 memset (&ds, 0,
sizeof ds);
3670 state -> partner.address,
MDL)) {
3671 for (i = 0; i + addrlen - 1 < ds.len; i += addrlen) {
3672 if (!memcmp (&ds.data [i],
3685 dhcp_failover_state_t *state;
3686 failover_option_t *name;
3688 if ((strlen(state->name) == name->count) &&
3689 (memcmp(state->name, name->data, name->count) == 0))
3697 static char resbuf[
sizeof(
"Undefined-255: This reason code is not defined " 3698 "in the protocol standard.")];
3700 if ((reason > 0xff) || (reason < 0))
3701 return "Reason code out of range.";
3704 case FTR_ILLEGAL_IP_ADDR:
3705 return "Illegal IP address (not part of any address pool).";
3707 case FTR_FATAL_CONFLICT:
3708 return "Fatal conflict exists: address in use by other client.";
3710 case FTR_MISSING_BINDINFO:
3711 return "Missing binding information.";
3713 case FTR_TIMEMISMATCH:
3714 return "Connection rejected, time mismatch too great.";
3716 case FTR_INVALID_MCLT:
3717 return "Connection rejected, invalid MCLT.";
3719 case FTR_MISC_REJECT:
3720 return "Connection rejected, unknown reason.";
3722 case FTR_DUP_CONNECTION:
3723 return "Connection rejected, duplicate connection.";
3725 case FTR_INVALID_PARTNER:
3726 return "Connection rejected, invalid failover partner.";
3728 case FTR_TLS_UNSUPPORTED:
3729 return "TLS not supported.";
3731 case FTR_TLS_UNCONFIGURED:
3732 return "TLS supported but not configured.";
3734 case FTR_TLS_REQUIRED:
3735 return "TLS required but not supported by partner.";
3737 case FTR_DIGEST_UNSUPPORTED:
3738 return "Message digest not supported.";
3740 case FTR_DIGEST_UNCONFIGURED:
3741 return "Message digest not configured.";
3743 case FTR_VERSION_MISMATCH:
3744 return "Protocol version mismatch.";
3746 case FTR_OUTDATED_BIND_INFO:
3747 return "Outdated binding information.";
3749 case FTR_LESS_CRIT_BIND_INFO:
3750 return "Less critical binding information.";
3752 case FTR_NO_TRAFFIC:
3753 return "No traffic within sufficient time.";
3755 case FTR_HBA_CONFLICT:
3756 return "Hash bucket assignment conflict.";
3758 case FTR_IP_NOT_RESERVED:
3759 return "IP not reserved on this server.";
3761 case FTR_IP_DIGEST_FAILURE:
3762 return "Message digest failed to compare.";
3764 case FTR_IP_MISSING_DIGEST:
3765 return "Missing message digest.";
3768 return "Unknown Error.";
3771 sprintf(resbuf,
"Undefined-%d: This reason code is not defined in the " 3772 "protocol standard.", reason);
3782 return "unknown-state";
3785 return "partner-down";
3791 return "conflict-done";
3794 return "communications-interrupted";
3797 return "resolution-interrupted";
3800 return "potential-conflict";
3806 return "recover-done";
3809 return "recover-wait";
3824 static char messbuf[
sizeof(
"unknown-message-255")];
3827 return "invalid-message";
3831 return "pool-request";
3834 return "pool-response";
3837 return "bind-update";
3845 case FTM_CONNECTACK:
3846 return "connect-ack";
3849 return "update-request";
3852 return "update-done";
3855 return "update-request-all";
3863 case FTM_DISCONNECT:
3864 return "disconnect";
3867 sprintf(messbuf,
"unknown-message-%u", type);
3874 static char optbuf[
sizeof(
"unknown-option-65535")];
3877 return "invalid-option";
3880 case FTO_ADDRESSES_TRANSFERRED:
3881 return "addresses-transferred";
3883 case FTO_ASSIGNED_IP_ADDRESS:
3884 return "assigned-ip-address";
3886 case FTO_BINDING_STATUS:
3887 return "binding-status";
3889 case FTO_CLIENT_IDENTIFIER:
3890 return "client-identifier";
3901 case FTO_DELAYED_SERVICE:
3902 return "delayed-service";
3910 case FTO_LEASE_EXPIRY:
3911 return "lease-expiry";
3913 case FTO_MAX_UNACKED:
3914 return "max-unacked";
3922 case FTO_MESSAGE_DIGEST:
3923 return "message-digest";
3925 case FTO_POTENTIAL_EXPIRY:
3926 return "potential-expiry";
3928 case FTO_PROTOCOL_VERSION:
3929 return "protocol-version";
3931 case FTO_RECEIVE_TIMER:
3932 return "receive-timer";
3934 case FTO_REJECT_REASON:
3935 return "reject-reason";
3937 case FTO_RELATIONSHIP_NAME:
3938 return "relationship-name";
3940 case FTO_REPLY_OPTIONS:
3941 return "reply-options";
3943 case FTO_REQUEST_OPTIONS:
3944 return "request-options";
3946 case FTO_SERVER_FLAGS:
3947 return "server-flags";
3949 case FTO_SERVER_STATE:
3950 return "server-state";
3958 case FTO_TLS_REQUEST:
3959 return "tls-request";
3961 case FTO_VENDOR_CLASS:
3962 return "vendor-class";
3964 case FTO_VENDOR_OPTIONS:
3965 return "vendor-options";
3968 sprintf(optbuf,
"unknown-option-%u", type);
3977 const char *fmt, ...)
3990 if (vsnprintf (tbuf,
sizeof tbuf, fmt, va) >=
sizeof tbuf)
3991 log_fatal (
"%s: vsnprintf would truncate",
3992 "dhcp_failover_make_option");
3996 strlen (tbuf), tbuf);
4000 char *obuf,
unsigned *obufix,
4001 unsigned obufmax, ...)
4004 struct failover_option_info *info;
4006 unsigned size, count;
4012 #if defined (DEBUG_FAILOVER_MESSAGES) 4020 failover_option_t
option, *op;
4024 if (code < 1 || code > FTO_MAX ||
ft_options [code].type == FT_UNDEF) {
4029 va_start (va, obufmax);
4033 if (info -> type == FT_DDNS || info -> type == FT_DDNS1) {
4034 count = info -> type == FT_DDNS ? 1 : 2;
4035 size = va_arg (va,
int) + count;
4038 if (info -> num_present)
4039 count = info -> num_present;
4041 count = va_arg (va,
int);
4044 switch (info -> type) {
4051 case FT_TEXT_OR_BYTES:
4053 txt = va_arg (va,
char *);
4058 ilen = va_arg (va,
unsigned);
4059 size = count * ilen;
4072 log_fatal (
"bogus type in failover_make_option: %d",
4092 #if defined (DEBUG_FAILOVER_MESSAGES) 4100 if (snprintf (tbuf,
sizeof tbuf,
" (%s<%d>", info -> name,
4101 option.count) >=
sizeof tbuf)
4102 log_fatal (
"dhcp_failover_make_option: tbuf overflow");
4107 switch (info -> type) {
4109 for (i = 0; i < count; i++) {
4110 val = va_arg (va,
unsigned);
4111 #if defined (DEBUG_FAILOVER_MESSAGES) 4113 sprintf (tbuf,
" %d", val);
4116 option.data [i + 4] = val;
4121 for (i = 0; i < count; i++) {
4122 iaddr = va_arg (va, u_int8_t *);
4125 log_error (
"IP addrlen=%d, should be 4.",
4131 #if defined (DEBUG_FAILOVER_MESSAGES) 4133 sprintf (tbuf,
" %u.%u.%u.%u",
4137 memcpy (&
option.data [4 + i * ilen],
iaddr, ilen);
4142 for (i = 0; i < count; i++) {
4143 val = va_arg (va,
unsigned);
4144 #if defined (DEBUG_FAILOVER_MESSAGES) 4146 sprintf (tbuf,
" %d", val);
4155 bval = va_arg (va, u_int8_t *);
4156 #if defined (DEBUG_FAILOVER_MESSAGES) 4157 for (i = 0; i < count; i++) {
4159 sprintf (tbuf,
" %d", bval [i]);
4163 memcpy (&
option.data [4], bval, count);
4170 case FT_TEXT_OR_BYTES:
4172 #if defined (DEBUG_FAILOVER_MESSAGES) 4180 if (snprintf (tbuf,
sizeof tbuf,
"\"%s\"", txt) >=
sizeof tbuf)
4181 log_fatal (
"dhcp_failover_make_option: tbuf overflow");
4184 memcpy (&
option.data [4], txt, count);
4189 option.data [4] = va_arg (va,
unsigned);
4191 option.data [5] = va_arg (va,
unsigned);
4192 bval = va_arg (va, u_int8_t *);
4193 memcpy (&
option.data [4 + count], bval, size - count - 4);
4194 #if defined (DEBUG_FAILOVER_MESSAGES) 4195 for (i = 4; i < size; i++) {
4197 sprintf (tbuf,
" %d",
option.data [i]);
4204 for (i = 0; i < count; i++) {
4205 val = va_arg (va, u_int32_t);
4206 #if defined (DEBUG_FAILOVER_MESSAGES) 4208 sprintf (tbuf,
" %d", val);
4220 #if defined DEBUG_FAILOVER_MESSAGES 4226 op =
dmalloc (
sizeof (failover_option_t),
MDL);
4240 int msg_type, u_int32_t xid, ...)
4246 failover_option_t *
option;
4247 unsigned char *opbuf;
4248 isc_result_t status = ISC_R_SUCCESS;
4254 va_start (list, xid);
4255 while ((
option = va_arg (list, failover_option_t *))) {
4264 if (!bad_option && size) {
4267 status = ISC_R_NOMEMORY;
4269 opbuf = (
unsigned char *)0;
4271 va_start (list, xid);
4272 while ((
option = va_arg (list, failover_option_t *))) {
4275 if (!bad_option && opbuf)
4276 memcpy (&opbuf [opix],
4294 if (status != ISC_R_SUCCESS)
4300 if (status != ISC_R_SUCCESS)
4306 if (status != ISC_R_SUCCESS)
4311 if (status != ISC_R_SUCCESS)
4316 if (status != ISC_R_SUCCESS)
4322 if (status != ISC_R_SUCCESS)
4326 if (link -> state_object &&
4327 link -> state_object -> link_to_peer == link) {
4328 #if defined (DEBUG_FAILOVER_CONTACT_TIMING) 4330 (
int)(link -> state_object ->
4331 partner.max_response_delay) / 3,
4332 "dhcp_failover_send_contact");
4335 (
int)(link -> state_object ->
4336 partner.max_response_delay) / 3;
4340 (
tvref_t)dhcp_failover_state_reference,
4341 (
tvunref_t)dhcp_failover_state_dereference);
4348 log_info (
"dhcp_failover_put_message: something went wrong.");
4355 dhcp_failover_state_t *state = vstate;
4356 dhcp_failover_link_t *link;
4358 #if defined (DEBUG_FAILOVER_TIMING) 4359 log_info (
"dhcp_failover_timeout");
4364 link = state -> link_to_peer;
4370 log_error (
"timeout waiting for failover peer %s", state -> name);
4379 dhcp_failover_state_t *state = vstate;
4380 dhcp_failover_link_t *link;
4381 isc_result_t status;
4383 #if defined(DEBUG_FAILOVER_MESSAGES) && \ 4384 defined(DEBUG_FAILOVER_CONTACT_MESSAGES) 4386 unsigned obufix = 0;
4391 #if defined (DEBUG_FAILOVER_CONTACT_TIMING) 4392 log_info (
"dhcp_failover_send_contact");
4397 link = state -> link_to_peer;
4404 (link, link -> outer,
4405 FTM_CONTACT, link->xid++,
4406 (failover_option_t *)0));
4408 #if defined(DEBUG_FAILOVER_MESSAGES) && \ 4409 defined(DEBUG_FAILOVER_CONTACT_MESSAGES) 4410 if (status != ISC_R_SUCCESS)
4424 dhcp_failover_link_t *link;
4425 isc_result_t status;
4427 #if defined (DEBUG_FAILOVER_MESSAGES) 4429 unsigned obufix = 0;
4431 # define FMA obuf, &obufix, sizeof obuf 4434 # define FMA (char *)0, (unsigned *)0, 0 4439 link = state -> link_to_peer;
4446 (link, link -> outer,
4447 FTM_STATE, link->xid++,
4450 ? state -> saved_state
4451 : state -> me.state)),
4453 (FTO_SERVER_FLAGS, FMA,
4455 ? FTF_SERVER_STARTUP : 0)),
4457 (failover_option_t *)0));
4459 #if defined (DEBUG_FAILOVER_MESSAGES) 4460 if (status != ISC_R_SUCCESS)
4469 return ISC_R_SUCCESS;
4476 dhcp_failover_link_t *link;
4477 dhcp_failover_state_t *state;
4478 isc_result_t status;
4479 #if defined (DEBUG_FAILOVER_MESSAGES) 4481 unsigned obufix = 0;
4483 # define FMA obuf, &obufix, sizeof obuf 4486 # define FMA (char *)0, (unsigned *)0, 0 4491 link = (dhcp_failover_link_t *)l;
4492 state = link -> state_object;
4499 FTM_CONNECT, link->xid++,
4501 strlen(state->name), state->name),
4503 state -> me.max_flying_updates),
4505 state -> me.max_response_delay),
4509 DHCP_FAILOVER_VERSION),
4517 (failover_option_t *)0));
4519 #if defined (DEBUG_FAILOVER_MESSAGES) 4520 if (status != ISC_R_SUCCESS)
4531 dhcp_failover_state_t *state,
4532 int reason,
const char *errmsg)
4534 dhcp_failover_link_t *link;
4535 isc_result_t status;
4536 #if defined (DEBUG_FAILOVER_MESSAGES) 4538 unsigned obufix = 0;
4540 # define FMA obuf, &obufix, sizeof obuf 4543 # define FMA (char *)0, (unsigned *)0, 0 4548 link = (dhcp_failover_link_t *)l;
4555 FTM_CONNECTACK, link->imsg->xid,
4558 strlen(state->name), state->name)
4559 : (link->imsg->options_present & FTB_RELATIONSHIP_NAME)
4561 link->imsg->relationship_name.count,
4562 link->imsg->relationship_name.data)
4566 state -> me.max_flying_updates)
4570 state -> me.max_response_delay)
4575 DHCP_FAILOVER_VERSION),
4576 (link->imsg->options_present & FTB_TLS_REQUEST)
4586 strlen (errmsg), errmsg)
4588 (failover_option_t *)0));
4590 #if defined (DEBUG_FAILOVER_MESSAGES) 4591 if (status != ISC_R_SUCCESS)
4603 const char *message)
4605 dhcp_failover_link_t *link;
4606 isc_result_t status;
4607 #if defined (DEBUG_FAILOVER_MESSAGES) 4609 unsigned obufix = 0;
4611 # define FMA obuf, &obufix, sizeof obuf 4614 # define FMA (char *)0, (unsigned *)0, 0 4619 link = (dhcp_failover_link_t *)l;
4623 if (!message && reason)
4628 FTM_DISCONNECT, link->xid++,
4633 strlen (message), message)
4635 (failover_option_t *)0));
4637 #if defined (DEBUG_FAILOVER_MESSAGES) 4638 if (status != ISC_R_SUCCESS)
4653 dhcp_failover_link_t *link;
4654 isc_result_t status;
4657 #if defined (DEBUG_FAILOVER_MESSAGES) 4659 unsigned obufix = 0;
4661 # define FMA obuf, &obufix, sizeof obuf 4664 # define FMA (char *)0, (unsigned *)0, 0 4667 if (!state -> link_to_peer ||
4670 link = (dhcp_failover_link_t *)state -> link_to_peer;
4682 if ((state->i_am == primary) && (transmit_state ==
FTS_FREE))
4684 else if ((state->i_am == secondary) &&
4688 flags |= FTF_IP_FLAG_RESERVE;
4691 flags |= FTF_IP_FLAG_BOOTP;
4731 (link, link -> outer,
4737 lease -> desired_binding_state),
4743 lease -> hardware_addr.hlen
4745 lease -> hardware_addr.hlen,
4746 lease -> hardware_addr.hbuf)
4763 (failover_option_t *)0));
4765 #if defined (DEBUG_FAILOVER_MESSAGES) 4766 if (status != ISC_R_SUCCESS)
4779 failover_message_t *msg,
4780 int reason,
const char *message)
4782 dhcp_failover_link_t *link;
4783 isc_result_t status;
4784 #if defined (DEBUG_FAILOVER_MESSAGES) 4786 unsigned obufix = 0;
4788 # define FMA obuf, &obufix, sizeof obuf 4791 # define FMA (char *)0, (unsigned *)0, 0 4794 if (!state -> link_to_peer ||
4797 link = (dhcp_failover_link_t *)state -> link_to_peer;
4802 if (!message && reason)
4807 (link, link -> outer,
4808 FTM_BNDACK, msg->xid,
4810 sizeof msg -> assigned_addr,
4811 &msg -> assigned_addr),
4812 #ifdef DO_BNDACK_SHOULD_NOT
4814 msg -> binding_status),
4815 (msg -> options_present & FTB_CLIENT_IDENTIFIER)
4817 msg -> client_identifier.count,
4818 msg -> client_identifier.data)
4820 (msg -> options_present & FTB_CHADDR)
4822 msg -> chaddr.count,
4828 msg -> potential_expiry),
4831 (msg->options_present & FTB_CLTT) ?
4834 ((msg->options_present & FTB_IP_FLAGS) && msg->ip_flags) ?
4844 strlen (message), message)
4846 #ifdef DO_BNDACK_SHOULD_NOT
4851 (failover_option_t *)0));
4853 #if defined (DEBUG_FAILOVER_MESSAGES) 4854 if (status != ISC_R_SUCCESS)
4866 dhcp_failover_link_t *link;
4867 isc_result_t status;
4868 #if defined (DEBUG_FAILOVER_MESSAGES) 4870 unsigned obufix = 0;
4872 # define FMA obuf, &obufix, sizeof obuf 4875 # define FMA (char *)0, (unsigned *)0, 0 4878 if (!state -> link_to_peer ||
4881 link = (dhcp_failover_link_t *)state -> link_to_peer;
4887 (link, link -> outer,
4888 FTM_POOLREQ, link->xid++,
4889 (failover_option_t *)0));
4891 #if defined (DEBUG_FAILOVER_MESSAGES) 4892 if (status != ISC_R_SUCCESS)
4905 dhcp_failover_link_t *link;
4906 isc_result_t status;
4907 #if defined (DEBUG_FAILOVER_MESSAGES) 4909 unsigned obufix = 0;
4911 # define FMA obuf, &obufix, sizeof obuf 4914 # define FMA (char *)0, (unsigned *)0, 0 4917 if (!state -> link_to_peer ||
4920 link = (dhcp_failover_link_t *)state -> link_to_peer;
4926 (link, link -> outer,
4927 FTM_POOLRESP, link->imsg->xid,
4930 (failover_option_t *)0));
4932 #if defined (DEBUG_FAILOVER_MESSAGES) 4933 if (status != ISC_R_SUCCESS)
4945 dhcp_failover_link_t *link;
4946 isc_result_t status;
4947 #if defined (DEBUG_FAILOVER_MESSAGES) 4949 unsigned obufix = 0;
4951 # define FMA obuf, &obufix, sizeof obuf 4954 # define FMA (char *)0, (unsigned *)0, 0 4957 if (!state->link_to_peer ||
4960 link = (dhcp_failover_link_t *)state->link_to_peer;
4968 if (state->curUPD == FTM_UPDREQALL) {
4973 link->xid++, NULL));
4975 state->curUPD = FTM_UPDREQ;
4977 #if defined (DEBUG_FAILOVER_MESSAGES) 4978 if (status != ISC_R_SUCCESS)
4986 if (status == ISC_R_SUCCESS) {
4987 log_info(
"Sent update request message to %s", state->name);
4989 log_error(
"Failed to send update request all message to %s: %s",
4990 state->name, isc_result_totext(status));
4998 dhcp_failover_link_t *link;
4999 isc_result_t status;
5000 #if defined (DEBUG_FAILOVER_MESSAGES) 5002 unsigned obufix = 0;
5004 # define FMA obuf, &obufix, sizeof obuf 5007 # define FMA (char *)0, (unsigned *)0, 0 5010 if (!state->link_to_peer ||
5013 link = (dhcp_failover_link_t *)state->link_to_peer;
5023 link->xid++, NULL));
5025 state->curUPD = FTM_UPDREQALL;
5027 #if defined (DEBUG_FAILOVER_MESSAGES) 5028 if (status != ISC_R_SUCCESS)
5036 if (status == ISC_R_SUCCESS) {
5037 log_info(
"Sent update request all message to %s", state->name);
5039 log_error(
"Failed to send update request all message to %s: %s",
5040 state->name, isc_result_totext(status));
5047 dhcp_failover_link_t *link;
5048 isc_result_t status;
5049 #if defined (DEBUG_FAILOVER_MESSAGES) 5051 unsigned obufix = 0;
5053 # define FMA obuf, &obufix, sizeof obuf 5056 # define FMA (char *)0, (unsigned *)0, 0 5059 if (!state -> link_to_peer ||
5062 link = (dhcp_failover_link_t *)state -> link_to_peer;
5068 (link, link -> outer,
5069 FTM_UPDDONE, state->updxid,
5070 (failover_option_t *)0));
5072 #if defined (DEBUG_FAILOVER_MESSAGES) 5073 if (status != ISC_R_SUCCESS)
5081 log_info (
"Sent update done message to %s", state -> name);
5105 static isc_boolean_t
5106 failover_lease_is_better(dhcp_failover_state_t *state,
struct lease *
lease,
5107 failover_message_t *msg)
5117 if ((msg->options_present & FTB_CLTT) != 0)
5118 msg_cltt = msg->cltt;
5122 switch(local_state) {
5125 if (msg_cltt < lease->cltt)
5129 else if (state->i_am == primary)
5146 else if (state->i_am == primary)
5162 failover_message_t *msg)
5166 int reason = FTR_MISC_REJECT;
5167 const char *message;
5168 int new_binding_state;
5169 int send_to_backup = 0;
5170 int required_options;
5171 isc_boolean_t chaddr_changed = ISC_FALSE;
5172 isc_boolean_t ident_changed = ISC_FALSE;
5175 required_options = FTB_ASSIGNED_IP_ADDRESS | FTB_BINDING_STATUS;
5176 if ((msg->options_present & required_options) != required_options) {
5177 message =
"binding update lacks required options";
5178 reason = FTR_MISSING_BINDINFO;
5182 ia.
len =
sizeof msg -> assigned_addr;
5183 memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
5186 message =
"unknown IP address";
5187 reason = FTR_ILLEGAL_IP_ADDR;
5197 message =
"IP address is covered by a different failover " 5198 "relationship state";
5199 reason = FTR_ILLEGAL_IP_ADDR;
5214 if (failover_lease_is_better(state,
lease, msg)) {
5215 message =
"incoming update is less critical than " 5217 reason = FTR_LESS_CRIT_BIND_INFO;
5227 message =
"no memory";
5231 if (msg -> options_present & FTB_CHADDR) {
5233 message =
"BNDUPD to ABANDONED with a CHADDR";
5236 if (msg -> chaddr.count >
sizeof lt -> hardware_addr.hbuf) {
5237 message =
"chaddr too long";
5243 msg->chaddr.count) != 0))
5244 chaddr_changed = ISC_TRUE;
5246 lt -> hardware_addr.hlen = msg -> chaddr.count;
5247 memcpy (lt -> hardware_addr.hbuf, msg -> chaddr.data,
5248 msg -> chaddr.count);
5249 }
else if (msg->binding_status ==
FTS_ACTIVE ||
5252 message =
"BNDUPD without CHADDR";
5253 reason = FTR_MISSING_BINDINFO;
5256 chaddr_changed = ISC_TRUE;
5266 if (msg->options_present & FTB_CLIENT_IDENTIFIER) {
5268 message =
"BNDUPD to ABANDONED with client-id";
5272 if ((lt->
uid_len != msg->client_identifier.count) ||
5273 (lt->
uid == NULL) ||
5274 (memcmp(lt->
uid, msg->client_identifier.data,
5276 ident_changed = ISC_TRUE;
5278 lt->
uid_len = msg->client_identifier.count;
5293 message =
"no memory";
5302 msg -> client_identifier.data, lt -> uid_len);
5303 }
else if (lt->
uid && msg->binding_status !=
FTS_RESET &&
5306 ident_changed = ISC_TRUE;
5339 (chaddr_changed || ident_changed)) {
5340 #if defined (NSUPDATE) 5349 if (msg -> options_present & FTB_STOS) {
5350 lt -> starts = msg -> stos;
5352 if (msg -> options_present & FTB_LEASE_EXPIRY) {
5353 lt -> ends = msg -> expiry;
5355 if (msg->options_present & FTB_POTENTIAL_EXPIRY) {
5356 lt->
atsfp = lt->
tsfp = msg->potential_expiry;
5358 if (msg->options_present & FTB_IP_FLAGS) {
5359 if (msg->ip_flags & FTF_IP_FLAG_RESERVE) {
5360 if ((((state->i_am == primary) &&
5362 ((state->i_am == secondary) &&
5365 message =
"Address is not reserved.";
5366 reason = FTR_IP_NOT_RESERVED;
5374 if (msg->ip_flags & FTF_IP_FLAG_BOOTP) {
5375 if ((((state->i_am == primary) &&
5377 ((state->i_am == secondary) &&
5380 message =
"Address is not allocated to BOOTP.";
5387 if (msg->ip_flags & ~(FTF_IP_FLAG_RESERVE | FTF_IP_FLAG_BOOTP))
5388 log_info(
"Unknown IP-flags set in BNDUPD (0x%x).",
5393 #if defined (DEBUG_LEASE_STATE_TRANSITIONS) 5394 log_info (
"processing state transition for %s: %s to %s",
5402 if (state -> me.state ==
normal) {
5405 (
lease, state, msg -> binding_status,
5406 msg -> potential_expiry));
5413 (
lease, state, msg -> binding_status,
5414 msg -> potential_expiry));
5416 if (new_binding_state != msg -> binding_status) {
5419 if (snprintf (outbuf,
sizeof outbuf,
5420 "%s: invalid state transition: %s to %s",
5425 log_fatal (
"%s: impossible outbuf overflow",
5426 "dhcp_failover_process_bind_update");
5436 lt -> next_binding_state =
FTS_FREE;
5443 if ((state->i_am == primary) &&
5447 lt -> next_binding_state = new_binding_state;
5449 msg -> binding_status = lt -> next_binding_state;
5460 message =
"database update failed";
5471 if (send_to_backup && secondary_not_hoarding(state,
lease->
pool)) {
5478 log_error(
"can't commit lease %s for mac addr " 5486 lease_dereference (<,
MDL);
5490 return ISC_R_SUCCESS;
5499 secondary_not_hoarding(dhcp_failover_state_t *state,
struct pool *p) {
5507 hold = ((total * state->max_lease_ownership) + 50) / 100;
5518 return(lts > -hold);
5522 failover_message_t *msg)
5526 const char *message =
"no memory";
5527 u_int32_t pot_expire;
5528 int send_to_backup = ISC_FALSE;
5531 ia.len =
sizeof msg -> assigned_addr;
5532 memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
5535 message =
"no such lease";
5540 if (msg -> options_present & FTB_REJECT_REASON) {
5541 log_error (
"bind update on %s from %s rejected: %.*s",
5542 piaddr (ia), state -> name,
5543 (
int)((msg -> options_present & FTB_MESSAGE)
5544 ? msg -> message.count
5546 (msg -> reject_reason))),
5547 (msg -> options_present & FTB_MESSAGE)
5548 ? (
const char *)(msg -> message.data)
5550 (msg -> reject_reason)));
5561 message =
"xid mismatch";
5566 if (msg->options_present & FTO_POTENTIAL_EXPIRY)
5567 pot_expire = msg->potential_expiry;
5590 if ((state->i_am == secondary) &&
5612 if (state->i_am == primary &&
5615 send_to_backup = ISC_TRUE;
5617 if (!send_to_backup && state->me.state ==
normal)
5645 if (state -> send_update_done ==
lease) {
5646 lease_dereference (&state -> send_update_done,
MDL);
5653 if (send_to_backup && secondary_not_hoarding(state,
lease->
pool)) {
5662 if (state->me.state ==
normal)
5672 return ISC_R_SUCCESS;
5675 log_info (
"bind update on %s got ack from %s: %s.",
5676 piaddr (ia), state -> name, message);
5687 #define FREE_LEASES 0 5688 #define ACTIVE_LEASES 1 5689 #define EXPIRED_LEASES 2 5690 #define ABANDONED_LEASES 3 5691 #define BACKUP_LEASES 4 5692 #define RESERVED_LEASES 5 5698 for (p = s ->
pools; p; p = p ->
next) {
5724 return ISC_R_SUCCESS;
5729 failover_message_t *msg)
5731 if (
state->send_update_done) {
5732 log_info(
"Received update request while old update still " 5733 "flying! Silently discarding old request.");
5734 lease_dereference(&
state->send_update_done,
MDL);
5745 if (
state -> update_queue_tail) {
5746 lease_reference (&
state -> send_update_done,
5749 log_info (
"Update request from %s: sending update",
5755 log_info (
"Update request from %s: nothing pending",
5759 return ISC_R_SUCCESS;
5764 failover_message_t *msg)
5766 if (
state->send_update_done) {
5767 log_info(
"Received update request while old update still " 5768 "flying! Silently discarding old request.");
5769 lease_dereference(&
state->send_update_done,
MDL);
5777 if (
state -> update_queue_tail) {
5778 lease_reference (&
state -> send_update_done,
5781 log_info (
"Update request all from %s: sending update",
5787 log_info (
"Update request all from %s: nothing pending",
5791 return ISC_R_SUCCESS;
5796 failover_message_t *msg)
5800 log_info (
"failover peer %s: peer update completed.",
5803 state -> curUPD = 0;
5805 switch (state -> me.state) {
5821 if (state->i_am == secondary) {
5824 log_error(
"Secondary is in conflict_done " 5825 "state after conflict resolution, " 5826 "this is illegal.");
5830 if (state->i_am == primary)
5833 log_error(
"Spurious update-done message.");
5839 log_error(
"Spurious update-done message.");
5848 if (state -> me.stos + state -> mclt >
cur_time &&
5849 state -> partner.state !=
recover &&
5852 #if defined (DEBUG_FAILOVER_TIMING) 5855 state -> me.stos + state -> mclt),
5856 "dhcp_failover_recover_done");
5858 tv . tv_sec = (
int)(state -> me.stos + state -> mclt);
5870 return ISC_R_SUCCESS;
5875 dhcp_failover_state_t *state = sp;
5877 #if defined (DEBUG_FAILOVER_TIMING) 5878 log_info (
"dhcp_failover_recover_done");
5884 #if defined (DEBUG_FAILOVER_MESSAGES) 5891 unsigned *obufix,
unsigned obufmax,
const char *s)
5893 int len = strlen (s);
5895 while (len + *obufix + 1 >= obufmax) {
5904 strcpy (&obuf [*obufix], s);
5911 unsigned char loadb_mx_tbl[256] = {
5912 251, 175, 119, 215, 81, 14, 79, 191, 103, 49,
5913 181, 143, 186, 157, 0, 232, 31, 32, 55, 60,
5914 152, 58, 17, 237, 174, 70, 160, 144, 220, 90,
5915 57, 223, 59, 3, 18, 140, 111, 166, 203, 196,
5916 134, 243, 124, 95, 222, 179, 197, 65, 180, 48,
5917 36, 15, 107, 46, 233, 130, 165, 30, 123, 161,
5918 209, 23, 97, 16, 40, 91, 219, 61, 100, 10,
5919 210, 109, 250, 127, 22, 138, 29, 108, 244, 67,
5920 207, 9, 178, 204, 74, 98, 126, 249, 167, 116,
5921 34, 77, 193, 200, 121, 5, 20, 113, 71, 35,
5922 128, 13, 182, 94, 25, 226, 227, 199, 75, 27,
5923 41, 245, 230, 224, 43, 225, 177, 26, 155, 150,
5924 212, 142, 218, 115, 241, 73, 88, 105, 39, 114,
5925 62, 255, 192, 201, 145, 214, 168, 158, 221, 148,
5926 154, 122, 12, 84, 82, 163, 44, 139, 228, 236,
5927 205, 242, 217, 11, 187, 146, 159, 64, 86, 239,
5928 195, 42, 106, 198, 118, 112, 184, 172, 87, 2,
5929 173, 117, 176, 229, 247, 253, 137, 185, 99, 164,
5930 102, 147, 45, 66, 231, 52, 141, 211, 194, 206,
5931 246, 238, 56, 110, 78, 248, 63, 240, 189, 93,
5932 92, 51, 53, 183, 19, 171, 72, 50, 33, 104,
5933 101, 69, 8, 252, 83, 120, 76, 135, 85, 54,
5934 202, 125, 188, 213, 96, 235, 136, 208, 162, 129,
5935 190, 132, 156, 38, 47, 1, 7, 254, 24, 4,
5936 216, 131, 89, 21, 28, 133, 37, 153, 149, 80,
5937 170, 68, 6, 169, 234, 151 };
5939 static unsigned char loadb_p_hash (
const unsigned char *,
unsigned);
5940 static unsigned char loadb_p_hash (
const unsigned char *key,
unsigned len)
5942 unsigned char hash = len;
5944 for(i = len; i > 0; )
5945 hash = loadb_mx_tbl [hash ^ (key [--i])];
5953 unsigned char hbaix;
5959 #if defined(SECS_BYTEORDER) 5966 if ((ec > 255) && ((ec & 0xff) == 0)) {
5967 ec = (ec >> 8) | (ec << 8);
5971 if (state->load_balance_max_secs < ec) {
5985 memset(&ds, 0,
sizeof ds);
5990 hbaix = loadb_p_hash(ds.data, ds.len);
5998 hm = state->hba[(hbaix >> 3) & 0x1F] & (1 << (hbaix & 0x07));
6000 if (state->i_am == primary)
6014 dhcp_failover_state_t *state;
6015 unsigned char hbaix;
6023 if (!state || !state->hba)
6040 hm = state->hba[(hbaix >> 3) & 0x1F] & (1 << (hbaix & 0x07));
6042 if (state->i_am == primary)
6056 dhcp_failover_state_t *state,
6063 if (binding_state ==
lease -> binding_state)
6064 return binding_state;
6066 switch (
lease -> binding_state) {
6069 switch (binding_state) {
6080 if (state -> i_am == secondary)
6081 return binding_state;
6089 new_state = binding_state;
6099 if (state -> i_am == primary) {
6105 return binding_state;
6107 new_state =
lease -> binding_state;
6112 switch (binding_state) {
6118 new_state =
lease -> binding_state;
6121 return binding_state;
6130 new_state =
lease -> binding_state;
6138 return binding_state;
6146 switch (binding_state) {
6152 new_state =
lease -> binding_state;
6155 return binding_state;
6162 return binding_state;
6169 switch (binding_state) {
6180 return binding_state;
6187 switch (binding_state) {
6193 new_state =
lease -> binding_state;
6196 return binding_state;
6203 return binding_state;
6210 switch (binding_state) {
6219 if (state -> i_am == primary)
6220 return binding_state;
6226 return binding_state;
6229 new_state =
lease -> binding_state;
6249 dhcp_failover_state_t *state,
6256 if (binding_state ==
lease -> binding_state)
6257 new_state = binding_state;
6259 switch (
lease -> binding_state) {
6269 new_state = binding_state;
6276 switch (binding_state) {
6279 new_state =
lease -> binding_state;
6291 new_state = binding_state;
6302 new_state = binding_state;
6337 dhcp_failover_state_t *peer;
6363 if (peer -> i_am == primary)
6368 (peer->me.stos + peer->mclt <
cur_time) :
6387 if ((peer->i_am == primary) &&
6390 if ((peer->i_am == secondary) &&
6421 if (peer->i_am == secondary)
6426 (peer->me.stos + peer->mclt <
cur_time) :
6443 static isc_result_t failover_message_reference (failover_message_t **mp,
6444 failover_message_t *m,
6449 return ISC_R_SUCCESS;
6452 static isc_result_t failover_message_dereference (failover_message_t **mp,
6455 failover_message_t *m;
6458 if (m -> refcnt == 0) {
6460 failover_message_dereference (&m -> next,
6462 if (m -> chaddr.data)
6464 if (m -> client_identifier.data)
6468 if (m -> message.data)
6470 if (m -> relationship_name.data)
6472 if (m -> reply_options.data)
6474 if (m -> request_options.data)
6476 if (m -> vendor_class.data)
6478 if (m -> vendor_options.data)
6485 return ISC_R_SUCCESS;
6547 const char *print_value =
"<none>";
6549 if ((strlen (value) <= 64) &&
6551 print_value = value;
6554 print_value =
"<unsuitable for printing>";
6558 return (print_value);
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 *)
void dhcp_failover_sanity_check(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)