33#if defined (FAILOVER_PROTOCOL)
73 if (state->pool_count == 0) {
74 log_error (
"ERROR: Failover peer, %s, has no referring"
75 " pools. You must refer to each peer in at"
76 " least one pool declaration.",
81 if (state->load_balance_max_secs == 0) {
82 log_info (
"WARNING: load balancing will be disabled "
83 "for failover peer, %s, "
84 "because its load balance max secs is 0",
90 log_fatal (
"Failover configuration sanity check failed");
107#if defined (DEBUG_FAILOVER_TIMING)
108 log_info (
"add_timeout +90 dhcp_failover_reconnect");
118 log_error (
"failover peer %s: %s", state -> name,
125#if defined (DEBUG_FAILOVER_TIMING)
127 "dhcp_failover_listener_restart");
218 for (
o = h;
o -> outer;
o =
o -> outer)
255 for (
i = 0;
i < addrs -> count;
i++) {
256 addrs -> addresses [
i].addrtype =
AF_INET;
257 addrs -> addresses [
i].addrlen =
sizeof (
struct in_addr);
258 memcpy (addrs -> addresses [
i].address,
265 if (!state ->
me.address ||
273 memset (&local_addr, 0,
sizeof local_addr);
277 log_fatal (
"failover peer %s: no local address.",
282 log_error(
"failover peer %s: 'address' parameter "
283 "fails to resolve to an IPv4 address",
325 if (!
strcmp (name,
"connect")) {
329 log_info (
"dhcp_failover_send_connect: %s",
337#if defined (DEBUG_FAILOVER_TIMING)
339 "dhcp_failover_link_startup_timeout");
351 if (!
strcmp (name,
"disconnect")) {
358 if (state->link_to_peer ==
link)
362#if defined (DEBUG_FAILOVER_TIMING)
363 log_info(
"add_timeout +5 dhcp_failover_reconnect");
376 if (!
strcmp (name,
"status")) {
392#if defined (DEBUG_FAILOVER_TIMING)
394 "dhcp_failover_reconnect");
409 if (
strcmp (name,
"ready")) {
410 if (h ->
inner && h ->
inner -> type -> signal_handler)
411 return (*(h ->
inner -> type -> signal_handler))
423 switch (
link -> state) {
440 log_info (
"message length wait: %s",
491#if defined (DEBUG_FAILOVER_MESSAGES)
492# if !defined(DEBUG_FAILOVER_CONTACT_MESSAGES)
496 log_info (
"link: message %s payoff %d time %ld xid %ld",
500 (
unsigned long)
link ->
imsg -> xid);
501# if !defined(DEBUG_FAILOVER_CONTACT_MESSAGES)
528 if (!(
link->imsg->options_present &
530 errmsg =
"missing relationship-name";
540 &
link->imsg->relationship_name))
547 errmsg =
"unknown failover relationship name";
557 }
else if (
link->imsg->options_present &
559 sname = (
char *)
link->imsg->
561 slen =
link->imsg->relationship_name.count;
567 log_error(
"Failover CONNECT from %.*s: %s",
582 errmsg =
"time offset too large";
606 if (!
link -> peer_address)
608 (&
link -> peer_address,
616 log_info (
"failover: connect: no matching state.");
657 log_error (
"FAILOVER: message overflow at option code.");
662 log_error (
"FAILOVER: invalid message type: %d",
672 log_error (
"FAILOVER: message overflow at length.");
681 log_error (
"FAILOVER: message overflow at data.");
688#if defined (DEBUG_FAILOVER_MESSAGES)
689 log_debug (
" option code %d (%s) len %d (not recognized)",
703 log_error (
"FAILOVER: digest not at end of message");
706#if defined (DEBUG_FAILOVER_MESSAGES)
717 log_error (
"FAILOVER: duplicate option %s",
743 op = ((
unsigned char *)
link ->
imsg) +
749 log_error (
"FAILOVER: option size (%d:%d), option %s",
778 ddns -> codes [1] = 0;
785 log_error (
"FAILOVER: no memory getting%s(%d)",
806 log_error (
"FAILOVER: option_len %d not %s%d",
820 log_error (
"FAILOVER: no memory getting %s (%d)",
856 (
strncmp((
const char *)op,
"isc-V3.0.", 9) == 0)) {
857 log_error(
"WARNING: failover as of versions 3.1.0 and "
858 "on are not reverse compatible with "
884 log_error (
"FAILOVER: option %s: bad type %d",
910 if (h ->
inner && h ->
inner -> type -> set_value)
911 return (*(h ->
inner -> type -> set_value))
933 "invalid link state",
940 if (h ->
inner && h ->
inner -> type -> get_value)
941 return (*(h ->
inner -> type -> get_value))
954 if (
link -> peer_address)
1000 return (*(
link ->
inner -> type -> stuff_values)) (
c,
id,
1017 "local-port", &
value);
1029 local_addr.
port = port;
1032 "local-address", &
value);
1054 if (
l -> address.port == local_addr.
port &&
1055 l -> address.addrtype == local_addr.
addrtype &&
1056 l -> address.addrlen == local_addr.
addrlen &&
1069 obj -> address = local_addr;
1115 if (
strcmp (name,
"connect")) {
1116 if (
p ->
inner &&
p ->
inner -> type -> signal_handler)
1117 return (*(
p ->
inner -> type -> signal_handler))
1131 sizeof c -> remote_addr.sin_addr)) {
1137 log_info (
"failover: listener: no matching state");
1153 log_info (
"failover: listener: picayune failure.");
1181 if (h ->
inner && h ->
inner -> type -> set_value)
1182 return (*(h ->
inner -> type -> set_value))
1195 if (h ->
inner && h ->
inner -> type -> get_value)
1196 return (*(h ->
inner -> type -> get_value))
1226 return (*(
p ->
inner -> type -> stuff_values)) (
c, id,
1241 "local-port", &
value);
1256 obj ->
me.port = port;
1290 if (
strcmp (name,
"disconnect") &&
1291 strcmp (name,
"message")) {
1292 if (state ->
inner && state ->
inner -> type -> signal_handler)
1293 return (*(state ->
inner -> type -> signal_handler))
1300 if (!
strcmp (name,
"disconnect")) {
1305 if (state ->
i_am == primary) {
1306#if defined (DEBUG_FAILOVER_TIMING)
1308 "dhcp_failover_reconnect");
1318 }
else if (!
strcmp (name,
"message")) {
1331 "already connected");
1339 "no MCLT provided");
1351 log_info (
"dhcp_failover_send_connectack: %s",
1357 state ->
partner.max_flying_updates =
1360 state ->
partner.max_response_delay =
1374 if (!(
link->imsg->options_present &
1376 errmsg =
"missing relationship-name";
1383 log_error (
"Failover CONNECT to %s rejected: %s",
1384 state ? state->name :
"unknown",
1393 &
link->imsg->relationship_name)) {
1396 "relationship name %.*s does not match",
1397 (
int)
link->imsg->relationship_name.count,
1398 link->imsg->relationship_name.data);
1402 log_error(
"Failover CONNECTACK from %s: %s",
1411 errmsg =
"already connected";
1420 errmsg =
"time offset too large";
1434 state -> saved_state);
1440 state ->
partner.max_flying_updates =
1443 state ->
partner.max_response_delay =
1445#if defined (DEBUG_FAILOVER_CONTACT_TIMING)
1447 (
int)state ->
partner.max_response_delay / 3,
1448 "dhcp_failover_send_contact");
1451 (
int)state ->
partner.max_response_delay / 3;
1457#if defined (DEBUG_FAILOVER_CONTACT_TIMING)
1459 (
int)state ->
me.max_response_delay,
1460 "dhcp_failover_timeout");
1463 (
int)state ->
me.max_response_delay;
1471 log_error (
"Failover DISCONNECT from %s: %s",
1472 state ? state->name :
"unknown",
1494 log_info (
"pool response: %ld leases",
1510#if defined (DEBUG_FAILOVER_CONTACT_TIMING)
1512 (
int)state ->
me.max_response_delay,
1513 "dhcp_failover_timeout");
1516 (
int)state ->
me.max_response_delay;
1536 if (!
strcmp (name,
"disconnect")) {
1538 log_info (
"peer %s: disconnected", state -> name);
1550 state -> saved_state : state ->
me.state) {
1574 (state, state -> saved_state));
1593 }
else if (!
strcmp (name,
"connect")) {
1594 switch (state ->
me.state) {
1621 }
else if (!
strcmp (name,
"startup")) {
1624 }
else if (!
strcmp (name,
"connect-timeout")) {
1625 switch (state ->
me.state) {
1657 switch (state ->
me.state) {
1660 state ->
nrr =
" (my state unknown)";
1682 state ->
nrr =
" (resolving conflicts)";
1687 state ->
nrr =
" (recovering)";
1692 state ->
nrr =
" (shut down)";
1697 state ->
nrr =
" (paused)";
1702 state ->
nrr =
" (recover wait)";
1707 state ->
nrr =
" (recover done)";
1712 state ->
nrr =
" (startup)";
1724 switch (state ->
partner.state) {
1727 state ->
nrr =
" (peer demands: recovering)";
1734 state ->
nrr =
" (peer demands: resolving conflicts)";
1770 if (
state->update_queue_head) {
1777 if (!
state->update_queue_tail) {
1778#if defined (POINTER_DEBUG)
1779 if (
state->ack_queue_tail->next_pending) {
1780 log_error(
"next pending on ack queue tail.");
1789 state->cur_unacked_updates = 0;
1806 switch (state ->
me.state) {
1822 saved_state = state ->
me.state;
1843 state -> saved_state = saved_state;
1847 log_error (
"Unable to record current failover state for %s",
1849 state ->
me.state = saved_state;
1854 log_info (
"failover peer %s: I move from %s to %s",
1859 if ((state->me.state ==
normal) && (state->partner.state ==
normal))
1860 log_info(
"failover peer %s: Both servers normal", state->name);
1889 if (state->auto_partner_down == 0)
1892#if defined (DEBUG_FAILOVER_TIMING)
1893 log_info(
"add_timeout +%lu dhcp_failover_auto_partner_down",
1894 (
unsigned long)state->auto_partner_down);
1896 tv.tv_sec =
cur_time + state->auto_partner_down;
1912 if (state->update_queue_tail !=
NULL) {
1914 log_info(
"Sending updates to %s.", state->name);
1920 if ((state->i_am == primary) ||
1921 ((state->i_am == secondary) &&
1927#if defined (DEBUG_FAILOVER_TIMING)
1929 "dhcp_failover_startup_timeout");
1945#if defined (DEBUG_FAILOVER_TIMING)
1948 state ->
me.stos + state ->
mclt),
1949 "dhcp_failover_startup_timeout");
1975 for (
p =
s->pools;
p;
p =
p->next) {
1976#if defined (BINARY_LEASES)
1979 if (
p->failover_peer == state) {
1983 l->tsfp = state->me.stos + state->mclt;
1984 l->sort_time = (
l->tsfp >
l->ends) ?
1986#if defined (BINARY_LEASES)
1998 if (
l && (
l->sort_time <
p->next_event_time)) {
2000 p->next_event_time =
l->sort_time;
2001#if defined (DEBUG_FAILOVER_TIMING)
2006 tv.tv_sec =
p->next_event_time;
2035 switch (state ->
me.state) {
2048 state->saved_state);
2078 log_info (
"failover peer %s: peer moves from %s to %s",
2084 if ((state->me.state ==
normal) && (state->partner.state ==
normal))
2085 log_info(
"failover peer %s: Both servers normal", state->name);
2091 log_error (
"Unable to record current failover state for %s",
2115 log_error(
"failover peer %s: Invalid state: %d", state->name,
2125 state -> saved_state : state ->
me.state) {
2144 log_error(
"Peer %s: Invalid state transition %s "
2145 "to %s.", state->name,
2172 log_info (
"failover peer %s: requesting %s",
2173 state -> name,
"full update from peer");
2227 log_error(
"Peer %s moves to normal during conflict "
2228 "resolution - panic, shutting down.",
2237 log_error(
"Peer %s: Unexpected move to "
2238 "conflict-done.", state->name);
2283 log_fatal(
"Peer %s: Invalid attempt to move from %s "
2284 "to %s while local state is conflict-done.",
2392 log_error(
"Both servers have entered recover-done!");
2453 state->sched_balance = 0;
2472 state->sched_balance = 0;
2492 state->sched_balance = 0;
2501 log_info(
"peer %s: Got POOLREQ, answering negatively! "
2502 "Peer may be out of leases or database inconsistent.",
2537 for (
p =
s->pools ;
p ;
p =
p->next) {
2538 if (
p->failover_peer != state)
2547 if (
p->failover_peer->i_am == primary) {
2548 lts = (
p->free_leases -
p->backup_leases) / 2;
2553 lts = (
p->backup_leases -
p->free_leases) / 2;
2559 total =
p->backup_leases +
p->free_leases;
2561 thresh = ((total * state->max_lease_misbalance) + 50) / 100;
2562 hold = ((total * state->max_lease_ownership) + 50) / 100;
2583 reqlog =
" (requesting peer rebalance!)";
2588 log_info(
"balancing pool %lx %s total %d free %d "
2589 "backup %d lts %d max-own (+/-)%d%s",
2591 (
p->shared_network ?
2682 log_func(
"%s pool %lx %s total %d free %d backup %d "
2683 "lts %d max-misbal %d",
result, (
unsigned long)
p,
2684 (
p->shared_network ?
2742 est1 = ((
est1 *
peer->max_lease_misbalance) + 50) / 100;
2743 est2 = ((
est2 *
peer->max_lease_misbalance) + 50) / 100;
2748 if(
peer->i_am == primary)
2773 if(
peer->sched_balance) {
2786#if defined(DEBUG_FAILOVER_TIMING)
2787 log_info(
"add_timeout +%d dhcp_failover_pool_rebalance",
2859#if defined (POINTER_DEBUG)
2861 log_error (
"ack_queue_tail: lp -> next_pending");
2905#if defined (POINTER_DEBUG)
2907 log_error (
"next pending on update queue lease.");
2908#if defined (DEBUG_RC_HISTORY)
2955#if defined (DEBUG_FAILOVER_TIMING)
2956 log_info (
"dhcp_failover_toack_queue_timeout");
2990#if defined (DEBUG_FAILOVER_TIMING)
2992 "dhcp_failover_toack_queue_timeout");
3123 if (h ->
inner && h ->
inner -> type -> set_value)
3124 return (*(h ->
inner -> type -> set_value))
3139#if defined (DEBUG_FAILOVER_TIMING)
3140 log_info (
"dhcp_failover_reconnect");
3149 log_info (
"failover peer %s: %s", state -> name,
3151#if defined (DEBUG_FAILOVER_TIMING)
3152 log_info(
"add_timeout +90 dhcp_failover_reconnect");
3166#if defined (DEBUG_FAILOVER_TIMING)
3167 log_info (
"dhcp_failover_startup_timeout");
3180 for (;
p;
p =
p -> outer)
3184 log_info (
"failover: link startup timeout");
3195#if defined (DEBUG_FAILOVER_TIMING)
3196 log_info (
"dhcp_failover_listener_restart");
3201 log_info (
"failover peer %s: %s", state -> name,
3203#if defined (DEBUG_FAILOVER_TIMING)
3205 "dhcp_failover_listener_restart");
3221#if defined (DEBUG_FAILOVER_TIMING)
3222 log_info(
"dhcp_failover_auto_partner_down");
3245 name,
s -> name,
MDL);
3267 oc =
s ->
me.address;
3274 name,
s ->
me.port,
MDL);
3277 s ->
me.max_flying_updates,
3314 s ->
me.max_response_delay,
3321 if (h ->
inner && h ->
inner -> type -> get_value)
3322 return (*(h ->
inner -> type -> get_value))
3340 s -> name = (
char *)0;
3344 if (
s ->
me.address)
3423 sizeof s ->
me.address);
3444 s ->
me.max_flying_updates);
3587 if (h ->
inner && h ->
inner -> type -> stuff_values)
3588 return (*(h ->
inner -> type -> stuff_values)) (
c,
id,
3625 if (
l ==
tv ->
value -> u.buffer.len &&
3680 for (
i = 0;
i + addrlen - 1 <
ds.len;
i += addrlen) {
3697 if ((
strlen(state->name) == name->count) &&
3698 (
memcmp(state->name, name->data, name->count) == 0))
3706 static char resbuf[
sizeof(
"Undefined-255: This reason code is not defined "
3707 "in the protocol standard.")];
3710 return "Reason code out of range.";
3714 return "Illegal IP address (not part of any address pool).";
3717 return "Fatal conflict exists: address in use by other client.";
3720 return "Missing binding information.";
3723 return "Connection rejected, time mismatch too great.";
3726 return "Connection rejected, invalid MCLT.";
3729 return "Connection rejected, unknown reason.";
3732 return "Connection rejected, duplicate connection.";
3735 return "Connection rejected, invalid failover partner.";
3738 return "TLS not supported.";
3741 return "TLS supported but not configured.";
3744 return "TLS required but not supported by partner.";
3747 return "Message digest not supported.";
3750 return "Message digest not configured.";
3753 return "Protocol version mismatch.";
3756 return "Outdated binding information.";
3759 return "Less critical binding information.";
3762 return "No traffic within sufficient time.";
3765 return "Hash bucket assignment conflict.";
3768 return "IP not reserved on this server.";
3771 return "Message digest failed to compare.";
3774 return "Missing message digest.";
3777 return "Unknown Error.";
3780 sprintf(
resbuf,
"Undefined-%d: This reason code is not defined in the "
3781 "protocol standard.",
reason);
3791 return "unknown-state";
3794 return "partner-down";
3800 return "conflict-done";
3803 return "communications-interrupted";
3806 return "resolution-interrupted";
3809 return "potential-conflict";
3815 return "recover-done";
3818 return "recover-wait";
3833 static char messbuf[
sizeof(
"unknown-message-255")];
3836 return "invalid-message";
3840 return "pool-request";
3843 return "pool-response";
3846 return "bind-update";
3855 return "connect-ack";
3858 return "update-request";
3861 return "update-done";
3864 return "update-request-all";
3873 return "disconnect";
3883 static char optbuf[
sizeof(
"unknown-option-65535")];
3886 return "invalid-option";
3890 return "addresses-transferred";
3893 return "assigned-ip-address";
3896 return "binding-status";
3899 return "client-identifier";
3911 return "delayed-service";
3920 return "lease-expiry";
3923 return "max-unacked";
3932 return "message-digest";
3935 return "potential-expiry";
3938 return "protocol-version";
3941 return "receive-timer";
3944 return "reject-reason";
3947 return "relationship-name";
3950 return "reply-options";
3953 return "request-options";
3956 return "server-flags";
3959 return "server-state";
3968 return "tls-request";
3971 return "vendor-class";
3974 return "vendor-options";
3986 const char *
fmt, ...)
4000 log_fatal (
"%s: vsnprintf would truncate",
4001 "dhcp_failover_make_option");
4015 unsigned size, count;
4021#if defined (DEBUG_FAILOVER_MESSAGES)
4053 switch (
info -> type) {
4068 size = count *
ilen;
4081 log_fatal (
"bogus type in failover_make_option: %d",
4101#if defined (DEBUG_FAILOVER_MESSAGES)
4111 log_fatal (
"dhcp_failover_make_option: tbuf overflow");
4116 switch (
info -> type) {
4118 for (
i = 0;
i < count;
i++) {
4120#if defined (DEBUG_FAILOVER_MESSAGES)
4130 for (
i = 0;
i < count;
i++) {
4134 log_error (
"IP addrlen=%d, should be 4.",
4140#if defined (DEBUG_FAILOVER_MESSAGES)
4151 for (
i = 0;
i < count;
i++) {
4153#if defined (DEBUG_FAILOVER_MESSAGES)
4165#if defined (DEBUG_FAILOVER_MESSAGES)
4166 for (
i = 0;
i < count;
i++) {
4181#if defined (DEBUG_FAILOVER_MESSAGES)
4190 log_fatal (
"dhcp_failover_make_option: tbuf overflow");
4203#if defined (DEBUG_FAILOVER_MESSAGES)
4204 for (
i = 4;
i < size;
i++) {
4213 for (
i = 0;
i < count;
i++) {
4215#if defined (DEBUG_FAILOVER_MESSAGES)
4229#if defined DEBUG_FAILOVER_MESSAGES
4256 unsigned char *
opbuf;
4278 opbuf = (
unsigned char *)0;
4337#if defined (DEBUG_FAILOVER_CONTACT_TIMING)
4340 partner.max_response_delay) / 3,
4341 "dhcp_failover_send_contact");
4345 partner.max_response_delay) / 3;
4357 log_info (
"dhcp_failover_put_message: something went wrong.");
4367#if defined (DEBUG_FAILOVER_TIMING)
4368 log_info (
"dhcp_failover_timeout");
4379 log_error (
"timeout waiting for failover peer %s", state -> name);
4392#if defined(DEBUG_FAILOVER_MESSAGES) && \
4393 defined(DEBUG_FAILOVER_CONTACT_MESSAGES)
4400#if defined (DEBUG_FAILOVER_CONTACT_TIMING)
4401 log_info (
"dhcp_failover_send_contact");
4417#if defined(DEBUG_FAILOVER_MESSAGES) && \
4418 defined(DEBUG_FAILOVER_CONTACT_MESSAGES)
4436#if defined (DEBUG_FAILOVER_MESSAGES)
4440# define FMA obuf, &obufix, sizeof obuf
4443# define FMA (char *)0, (unsigned *)0, 0
4459 ? state -> saved_state
4460 : state ->
me.state)),
4468#if defined (DEBUG_FAILOVER_MESSAGES)
4488#if defined (DEBUG_FAILOVER_MESSAGES)
4492# define FMA obuf, &obufix, sizeof obuf
4495# define FMA (char *)0, (unsigned *)0, 0
4510 strlen(state->name), state->name),
4512 state ->
me.max_flying_updates),
4514 state ->
me.max_response_delay),
4528#if defined (DEBUG_FAILOVER_MESSAGES)
4545#if defined (DEBUG_FAILOVER_MESSAGES)
4549# define FMA obuf, &obufix, sizeof obuf
4552# define FMA (char *)0, (unsigned *)0, 0
4567 strlen(state->name), state->name)
4599#if defined (DEBUG_FAILOVER_MESSAGES)
4612 const char *message)
4616#if defined (DEBUG_FAILOVER_MESSAGES)
4620# define FMA obuf, &obufix, sizeof obuf
4623# define FMA (char *)0, (unsigned *)0, 0
4642 strlen (message), message)
4646#if defined (DEBUG_FAILOVER_MESSAGES)
4666#if defined (DEBUG_FAILOVER_MESSAGES)
4670# define FMA obuf, &obufix, sizeof obuf
4673# define FMA (char *)0, (unsigned *)0, 0
4693 else if ((state->i_am == secondary) &&
4746 lease -> desired_binding_state),
4752 lease -> hardware_addr.hlen
4754 lease -> hardware_addr.hlen,
4755 lease -> hardware_addr.hbuf)
4763 (
lease->cltt != 0) ?
4774#if defined (DEBUG_FAILOVER_MESSAGES)
4789 int reason,
const char *message)
4793#if defined (DEBUG_FAILOVER_MESSAGES)
4797# define FMA obuf, &obufix, sizeof obuf
4800# define FMA (char *)0, (unsigned *)0, 0
4826 msg -> client_identifier.count,
4827 msg -> client_identifier.data)
4831 msg -> chaddr.count,
4853 strlen (message), message)
4862#if defined (DEBUG_FAILOVER_MESSAGES)
4877#if defined (DEBUG_FAILOVER_MESSAGES)
4881# define FMA obuf, &obufix, sizeof obuf
4884# define FMA (char *)0, (unsigned *)0, 0
4900#if defined (DEBUG_FAILOVER_MESSAGES)
4916#if defined (DEBUG_FAILOVER_MESSAGES)
4920# define FMA obuf, &obufix, sizeof obuf
4923# define FMA (char *)0, (unsigned *)0, 0
4941#if defined (DEBUG_FAILOVER_MESSAGES)
4956#if defined (DEBUG_FAILOVER_MESSAGES)
4960# define FMA obuf, &obufix, sizeof obuf
4963# define FMA (char *)0, (unsigned *)0, 0
4966 if (!state->link_to_peer ||
4986#if defined (DEBUG_FAILOVER_MESSAGES)
4996 log_info(
"Sent update request message to %s", state->name);
4998 log_error(
"Failed to send update request all message to %s: %s",
5009#if defined (DEBUG_FAILOVER_MESSAGES)
5013# define FMA obuf, &obufix, sizeof obuf
5016# define FMA (char *)0, (unsigned *)0, 0
5019 if (!state->link_to_peer ||
5036#if defined (DEBUG_FAILOVER_MESSAGES)
5046 log_info(
"Sent update request all message to %s", state->name);
5048 log_error(
"Failed to send update request all message to %s: %s",
5058#if defined (DEBUG_FAILOVER_MESSAGES)
5062# define FMA obuf, &obufix, sizeof obuf
5065# define FMA (char *)0, (unsigned *)0, 0
5081#if defined (DEBUG_FAILOVER_MESSAGES)
5090 log_info (
"Sent update done message to %s", state -> name);
5138 else if (state->i_am == primary)
5155 else if (state->i_am == primary)
5176 const char *message;
5179 int required_options;
5185 if ((
msg->options_present & required_options) != required_options) {
5186 message =
"binding update lacks required options";
5195 message =
"unknown IP address";
5206 message =
"IP address is covered by a different failover "
5207 "relationship state";
5224 message =
"incoming update is less critical than "
5236 message =
"no memory";
5242 message =
"BNDUPD to ABANDONED with a CHADDR";
5245 if (
msg -> chaddr.count >
sizeof lt -> hardware_addr.hbuf) {
5246 message =
"chaddr too long";
5250 if ((
lt->hardware_addr.hlen !=
msg->chaddr.count) ||
5252 msg->chaddr.count) != 0))
5255 lt -> hardware_addr.hlen =
msg -> chaddr.count;
5256 memcpy (
lt -> hardware_addr.hbuf,
msg -> chaddr.data,
5257 msg -> chaddr.count);
5261 message =
"BNDUPD without CHADDR";
5266 lt->hardware_addr.hlen = 0;
5277 message =
"BNDUPD to ABANDONED with client-id";
5281 if ((
lt->uid_len !=
msg->client_identifier.count) ||
5287 lt->uid_len =
msg->client_identifier.count;
5293 if (!
lt->uid ||
lt->uid ==
lt->uid_buf ||
5294 lt->uid_len >
lt->uid_max) {
5295 if (
lt->uid &&
lt->uid !=
lt->uid_buf)
5298 if (
lt->uid_len >
sizeof(
lt->uid_buf)) {
5299 lt->uid_max =
lt->uid_len;
5302 message =
"no memory";
5306 lt->uid_max =
sizeof(
lt->uid_buf);
5307 lt->uid =
lt->uid_buf;
5311 msg -> client_identifier.data,
lt -> uid_len);
5316 if (
lt->uid !=
lt->uid_buf)
5319 lt->uid_max =
lt->uid_len = 0;
5349#if defined (NSUPDATE)
5362 lt -> ends =
msg -> expiry;
5365 lt->atsfp =
lt->tsfp =
msg->potential_expiry;
5369 if ((((state->i_am == primary) &&
5371 ((state->i_am == secondary) &&
5374 message =
"Address is not reserved.";
5384 if ((((state->i_am == primary) &&
5386 ((state->i_am == secondary) &&
5389 message =
"Address is not allocated to BOOTP.";
5397 log_info(
"Unknown IP-flags set in BNDUPD (0x%x).",
5402#if defined (DEBUG_LEASE_STATE_TRANSITIONS)
5403 log_info (
"processing state transition for %s: %s to %s",
5429 "%s: invalid state transition: %s to %s",
5434 log_fatal (
"%s: impossible outbuf overflow",
5435 "dhcp_failover_process_bind_update");
5452 if ((state->i_am == primary) &&
5469 message =
"database update failed";
5487 log_error(
"can't commit lease %s for mac addr "
5513 total =
p->free_leases +
p->backup_leases;
5516 hold = ((total * state->max_lease_ownership) + 50) / 100;
5521 lts = (
p->free_leases -
p->backup_leases) / 2;
5535 const char *message =
"no memory";
5544 message =
"no such lease";
5550 log_error (
"bind update on %s from %s rejected: %.*s",
5551 piaddr (ia), state -> name,
5553 ?
msg -> message.count
5570 message =
"xid mismatch";
5599 if ((state->i_am == secondary) &&
5621 if (state->i_am == primary &&
5671 if (state->me.state ==
normal)
5684 log_info (
"bind update on %s got ack from %s: %s.",
5685 piaddr (ia), state -> name, message);
5696#define FREE_LEASES 0
5697#define ACTIVE_LEASES 1
5698#define EXPIRED_LEASES 2
5699#define ABANDONED_LEASES 3
5700#define BACKUP_LEASES 4
5701#define RESERVED_LEASES 5
5708 if (
p->failover_peer !=
state)
5724 (
l->tstp >
l->atsfp) ||
5740 if (
state->send_update_done) {
5741 log_info(
"Received update request while old update still "
5742 "flying! Silently discarding old request.");
5758 log_info (
"Update request from %s: sending update",
5764 log_info (
"Update request from %s: nothing pending",
5775 if (
state->send_update_done) {
5776 log_info(
"Received update request while old update still "
5777 "flying! Silently discarding old request.");
5790 log_info (
"Update request all from %s: sending update",
5796 log_info (
"Update request all from %s: nothing pending",
5809 log_info (
"failover peer %s: peer update completed.",
5814 switch (state ->
me.state) {
5830 if (state->i_am == secondary) {
5833 log_error(
"Secondary is in conflict_done "
5834 "state after conflict resolution, "
5835 "this is illegal.");
5839 if (state->i_am == primary)
5842 log_error(
"Spurious update-done message.");
5848 log_error(
"Spurious update-done message.");
5861#if defined (DEBUG_FAILOVER_TIMING)
5864 state ->
me.stos + state ->
mclt),
5865 "dhcp_failover_recover_done");
5886#if defined (DEBUG_FAILOVER_TIMING)
5887 log_info (
"dhcp_failover_recover_done");
5893#if defined (DEBUG_FAILOVER_MESSAGES)
5921 251, 175, 119, 215, 81, 14, 79, 191, 103, 49,
5922 181, 143, 186, 157, 0, 232, 31, 32, 55, 60,
5923 152, 58, 17, 237, 174, 70, 160, 144, 220, 90,
5924 57, 223, 59, 3, 18, 140, 111, 166, 203, 196,
5925 134, 243, 124, 95, 222, 179, 197, 65, 180, 48,
5926 36, 15, 107, 46, 233, 130, 165, 30, 123, 161,
5927 209, 23, 97, 16, 40, 91, 219, 61, 100, 10,
5928 210, 109, 250, 127, 22, 138, 29, 108, 244, 67,
5929 207, 9, 178, 204, 74, 98, 126, 249, 167, 116,
5930 34, 77, 193, 200, 121, 5, 20, 113, 71, 35,
5931 128, 13, 182, 94, 25, 226, 227, 199, 75, 27,
5932 41, 245, 230, 224, 43, 225, 177, 26, 155, 150,
5933 212, 142, 218, 115, 241, 73, 88, 105, 39, 114,
5934 62, 255, 192, 201, 145, 214, 168, 158, 221, 148,
5935 154, 122, 12, 84, 82, 163, 44, 139, 228, 236,
5936 205, 242, 217, 11, 187, 146, 159, 64, 86, 239,
5937 195, 42, 106, 198, 118, 112, 184, 172, 87, 2,
5938 173, 117, 176, 229, 247, 253, 137, 185, 99, 164,
5939 102, 147, 45, 66, 231, 52, 141, 211, 194, 206,
5940 246, 238, 56, 110, 78, 248, 63, 240, 189, 93,
5941 92, 51, 53, 183, 19, 171, 72, 50, 33, 104,
5942 101, 69, 8, 252, 83, 120, 76, 135, 85, 54,
5943 202, 125, 188, 213, 96, 235, 136, 208, 162, 129,
5944 190, 132, 156, 38, 47, 1, 7, 254, 24, 4,
5945 216, 131, 89, 21, 28, 133, 37, 153, 149, 80,
5946 170, 68, 6, 169, 234, 151 };
5948static unsigned char loadb_p_hash (
const unsigned char *,
unsigned);
5949static unsigned char loadb_p_hash (
const unsigned char *key,
unsigned len)
5951 unsigned char hash = len;
5953 for(
i = len;
i > 0; )
5962 unsigned char hbaix;
5975 ((
ec > 255) && ((
ec & 0xff) == 0))) {
5976 ec = (
ec >> 8) | (
ec << 8);
5979 if ((state->load_balance_max_secs == 0) ||
5980 (state->load_balance_max_secs <
ec)) {
6007 hm = state->hba[(
hbaix >> 3) & 0x1F] & (1 << (
hbaix & 0x07));
6009 if (state->i_am == primary)
6024 unsigned char hbaix;
6030 state =
lp->pool->failover_peer;
6032 if (!state || !state->hba)
6037 else if (
lp->hardware_addr.hlen > 1)
6045 lp->hardware_addr.hlen - 1);
6049 hm = state->hba[(
hbaix >> 3) & 0x1F] & (1 << (
hbaix & 0x07));
6051 if (state->i_am == primary)
6072 if (binding_state ==
lease -> binding_state)
6073 return binding_state;
6075 switch (
lease -> binding_state) {
6078 switch (binding_state) {
6089 if (state ->
i_am == secondary)
6090 return binding_state;
6108 if (state ->
i_am == primary) {
6114 return binding_state;
6121 switch (binding_state) {
6130 return binding_state;
6147 return binding_state;
6155 switch (binding_state) {
6164 return binding_state;
6171 return binding_state;
6178 switch (binding_state) {
6189 return binding_state;
6196 switch (binding_state) {
6205 return binding_state;
6212 return binding_state;
6219 switch (binding_state) {
6228 if (state ->
i_am == primary)
6229 return binding_state;
6235 return binding_state;
6265 if (binding_state ==
lease -> binding_state)
6268 switch (
lease -> binding_state) {
6285 switch (binding_state) {
6396 if ((
peer->i_am == primary) &&
6399 if ((
peer->i_am == secondary) &&
6430 if (
peer->i_am == secondary)
6467 if (
m -> refcnt == 0) {
6471 if (
m -> chaddr.data)
6473 if (
m -> client_identifier.data)
6477 if (
m -> message.data)
6487 if (
m -> vendor_options.data)
6578#if defined (DEBUG_FAILOVER_MESSAGES)
isc_result_t omapi_connection_get_uint16(omapi_object_t *, u_int16_t *)
isc_result_t omapi_connection_put_uint32(omapi_object_t *, u_int32_t)
isc_result_t omapi_connection_copyout(unsigned char *, omapi_object_t *, unsigned)
isc_result_t omapi_connection_put_uint16(omapi_object_t *, u_int32_t)
isc_result_t omapi_connection_copyin(omapi_object_t *, const unsigned char *, unsigned)
isc_result_t omapi_connection_require(omapi_object_t *, unsigned)
isc_result_t omapi_connection_get_uint32(omapi_object_t *, u_int32_t *)
int option_cache_reference(struct option_cache **ptr, struct option_cache *src, const char *file, int line)
void data_string_forget(struct data_string *data, const char *file, int line)
void data_string_copy(struct data_string *dest, const struct data_string *src, const char *file, int line)
void add_timeout(struct timeval *when, void *where, void *what, tvref_t ref, tvunref_t unref)
void cancel_timeout(void *where, void *what)
int option_cache_dereference(struct option_cache **ptr, const char *file, int line)
struct option_cache * lookup_option(struct universe *universe, struct option_state *options, unsigned code)
void putUShort(unsigned char *, u_int32_t)
void putULong(unsigned char *, u_int32_t)
int write_lease(struct lease *lease)
#define DHO_DHCP_CLIENT_IDENTIFIER
#define DHO_PXE_CLIENT_ID
struct iaddr server_identifier
isc_result_t dhcp_failover_link_stuff_values(omapi_object_t *, omapi_object_t *, omapi_object_t *)
void dhcp_failover_startup_timeout(void *)
isc_result_t dhcp_failover_process_update_request(dhcp_failover_state_t *, failover_message_t *)
failover_option_t null_failover_option
binding_state_t normal_binding_state_transition_check(struct lease *, dhcp_failover_state_t *, binding_state_t, u_int32_t)
dhcp_failover_state_t * failover_states
void(* tvunref_t)(void *, const char *, int)
int write_failover_state(dhcp_failover_state_t *)
isc_result_t dhcp_failover_listen(omapi_object_t *)
isc_result_t dhcp_failover_generate_update_queue(dhcp_failover_state_t *, int)
void dhcp_failover_sanity_check(void)
int db_printable(const unsigned char *)
const char * dhcp_failover_message_name(unsigned)
const char * dhcp_flink_state_names[]
isc_result_t dhcp_failover_state_lookup(omapi_object_t **, omapi_object_t *, omapi_object_t *)
isc_result_t find_failover_peer(dhcp_failover_state_t **, const char *, const char *, int)
isc_result_t dhcp_failover_link_signal(omapi_object_t *, const char *, va_list)
isc_result_t dhcp_failover_register(omapi_object_t *)
omapi_object_type_t * dhcp_type_failover_listener
isc_result_t dhcp_failover_peer_state_changed(dhcp_failover_state_t *, failover_message_t *)
isc_result_t dhcp_failover_listener_set_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *)
int peer_wants_lease(struct lease *)
struct shared_network * shared_networks
void dhcp_failover_startup(void)
struct failover_option_info ft_options[]
isc_result_t dhcp_failover_send_update_request(dhcp_failover_state_t *)
#define LEASE_GET_NEXT(LQ, LEASE)
void dhcp_failover_ack_queue_remove(dhcp_failover_state_t *, struct lease *)
void(* tvref_t)(void *, void *, const char *, int)
omapi_object_type_t * dhcp_type_failover_state
isc_result_t dhcp_failover_send_connect(omapi_object_t *)
int dhcp_failover_send_acks(dhcp_failover_state_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_listener_get_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **)
struct ipv6_pool ** pools
isc_result_t dhcp_failover_listener_destroy(omapi_object_t *, const char *, int)
isc_result_t dhcp_failover_state_stuff(omapi_object_t *, omapi_object_t *, omapi_object_t *)
int lease_copy(struct lease **, struct lease *, const char *, int)
isc_result_t enter_failover_peer(dhcp_failover_state_t *)
void dhcp_failover_auto_partner_down(void *vs)
int dhcp_failover_state_match(dhcp_failover_state_t *, u_int8_t *, unsigned)
void dhcp_failover_pool_check(struct pool *)
failover_option_t failover_option_t * dhcp_failover_make_option(unsigned, char *, unsigned *, unsigned,...)
int supersede_lease(struct lease *, struct lease *, int, int, int, int)
isc_result_t dhcp_failover_state_destroy(omapi_object_t *, const char *, int)
void dhcp_failover_toack_queue_timeout(void *)
isc_result_t dhcp_failover_set_service_state(dhcp_failover_state_t *state)
int dhcp_failover_queue_update(struct lease *, int)
isc_result_t dhcp_failover_state_set_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *)
isc_result_t dhcp_failover_send_poolreq(dhcp_failover_state_t *)
isc_result_t dhcp_failover_send_connectack(omapi_object_t *, dhcp_failover_state_t *, int, const char *)
int dhcp_failover_state_match_by_name(dhcp_failover_state_t *, failover_option_t *)
void dhcp_failover_recover_done(void *)
failover_option_t skip_failover_option
int dhcp_failover_write_all_states(void)
isc_result_t dhcp_failover_state_create(omapi_object_t **, omapi_object_t *)
isc_result_t dhcp_failover_send_updates(dhcp_failover_state_t *)
struct universe dhcp_universe
void dhcp_failover_rescind_updates(dhcp_failover_state_t *)
isc_result_t dhcp_failover_send_state(dhcp_failover_state_t *)
void dhcp_failover_send_contact(void *)
isc_result_t dhcp_failover_send_update_done(dhcp_failover_state_t *)
isc_result_t dhcp_failover_listener_signal(omapi_object_t *, const char *, va_list)
isc_result_t dhcp_failover_send_bind_update(dhcp_failover_state_t *, struct lease *)
isc_result_t dhcp_failover_link_initiate(omapi_object_t *)
void commit_leases_timeout(void *)
void dhcp_failover_link_startup_timeout(void *)
isc_result_t dhcp_failover_set_state(dhcp_failover_state_t *, enum failover_state)
isc_result_t dhcp_failover_send_disconnect(omapi_object_t *, int, const char *)
const char * dhcp_failover_reject_reason_print(int)
int find_lease_by_ip_addr(struct lease **, struct iaddr, const char *, int)
void dhcp_failover_keepalive(void *)
int dhcp_failover_queue_ack(dhcp_failover_state_t *, failover_message_t *msg)
void dhcp_failover_pool_rebalance(void *)
isc_result_t dhcp_failover_process_bind_ack(dhcp_failover_state_t *, failover_message_t *)
isc_result_t dhcp_failover_link_destroy(omapi_object_t *, const char *, int)
const char * dhcp_failover_state_name_print(enum failover_state)
isc_result_t dhcp_failover_link_get_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **)
void dhcp_failover_listener_restart(void *)
void dhcp_failover_reconnect(void *)
isc_result_t ddns_removals(struct lease *, struct iasubopt *, struct dhcp_ddns_cb *, isc_boolean_t)
isc_result_t dhcp_failover_state_transition(dhcp_failover_state_t *, const char *)
void failover_print(char *, unsigned *, unsigned, const char *)
isc_result_t dhcp_failover_send_bind_ack(dhcp_failover_state_t *, failover_message_t *, int, const char *)
isc_result_t dhcp_failover_state_remove(omapi_object_t *, omapi_object_t *)
binding_state_t conflict_binding_state_transition_check(struct lease *, dhcp_failover_state_t *, binding_state_t, u_int32_t)
void dhcp_failover_timeout(void *)
isc_result_t dhcp_failover_state_get_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **)
isc_result_t dhcp_failover_listener_stuff(omapi_object_t *, omapi_object_t *, omapi_object_t *)
#define LEASE_GET_FIRSTP(LQ)
int lease_mine_to_reallocate(struct lease *)
isc_result_t dhcp_failover_state_signal(omapi_object_t *, const char *, va_list)
int load_balance_mine(struct packet *, dhcp_failover_state_t *)
isc_result_t dhcp_failover_send_poolresp(dhcp_failover_state_t *, int)
isc_result_t dhcp_failover_link_set_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *)
const char * dhcp_failover_option_name(unsigned)
isc_result_t dhcp_failover_process_update_done(dhcp_failover_state_t *, failover_message_t *)
#define LEASE_GET_FIRST(LQ)
omapi_object_type_t * dhcp_type_failover_link
isc_result_t dhcp_failover_send_update_request_all(dhcp_failover_state_t *)
failover_option_t * dhcp_failover_option_printf(unsigned, char *, unsigned *, unsigned, const char *,...) __attribute__((__format__(__printf__
isc_result_t dhcp_failover_put_message(dhcp_failover_link_t *, omapi_object_t *, int, u_int32_t,...)
#define LEASE_GET_NEXTP(LQ, LEASE)
isc_result_t dhcp_failover_process_update_request_all(dhcp_failover_state_t *, failover_message_t *)
void scrub_lease(struct lease *lease, const char *file, int line)
Remove information from a prior use of a lease.
const char * printable(const char *value)
Given a char pointer, return always return a printable value.
const char * binding_state_print(enum failover_state state)
@ communications_interrupted
struct iaddr ip_addr(struct iaddr subnet, struct iaddr mask, u_int32_t host_address)
const char * piaddr(const struct iaddr addr)
#define ISC_R_NOTIMPLEMENTED
isc_result_t omapi_value_dereference(omapi_value_t **, const char *, int)
isc_result_t omapi_connection_put_string(omapi_object_t *, const char *)
isc_result_t omapi_connect_list(omapi_object_t *, omapi_addr_list_t *, omapi_addr_t *)
#define OMAPI_OBJECT_ALLOC(name, stype, type)
isc_result_t omapi_object_dereference(omapi_object_t **, const char *, int)
isc_result_t omapi_listen_addr(omapi_object_t *, omapi_addr_t *, int)
isc_result_t omapi_addr_list_dereference(omapi_addr_list_t **, const char *, int)
isc_result_t omapi_disconnect(omapi_object_t *, int)
isc_result_t omapi_handle_td_lookup(omapi_object_t **, omapi_typed_data_t *)
isc_result_t omapi_make_uint_value(omapi_value_t **, omapi_data_string_t *, unsigned int, const char *, int)
isc_result_t omapi_make_string_value(omapi_value_t **, omapi_data_string_t *, const char *, const char *, int)
isc_result_t omapi_object_reference(omapi_object_t **, omapi_object_t *, const char *, int)
omapi_object_type_t * omapi_type_protocol
isc_result_t omapi_signal_in(omapi_object_t *, const char *,...)
isc_result_t omapi_signal(omapi_object_t *, const char *,...)
isc_result_t omapi_addr_list_new(omapi_addr_list_t **, unsigned, const char *, int)
int omapi_ds_strcmp(omapi_data_string_t *, const char *)
omapi_object_type_t * omapi_type_connection
void * dmalloc(size_t, const char *, int)
void dfree(void *, const char *, int)
isc_result_t omapi_get_value_str(omapi_object_t *, omapi_object_t *, const char *, omapi_value_t **)
isc_result_t omapi_get_int_value(unsigned long *, omapi_typed_data_t *)
isc_result_t omapi_listen(omapi_object_t *, unsigned, int)
isc_result_t omapi_connection_put_name(omapi_object_t *, const char *)
isc_result_t omapi_make_int_value(omapi_value_t **, omapi_data_string_t *, int, const char *, int)
isc_result_t omapi_make_const_value(omapi_value_t **, omapi_data_string_t *, const unsigned char *, unsigned, const char *, int)
int log_error(const char *,...) __attribute__((__format__(__printf__
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
void log_fatal(const char *,...) __attribute__((__format__(__printf__
int int log_info(const char *,...) __attribute__((__format__(__printf__
#define DHCP_R_INVALIDARG
#define DHCP_R_PROTOCOLERROR
#define DHCP_R_KEYCONFLICT
#define DHCP_R_INCOMPLETE
binding_state_t next_binding_state
struct lease_state * state
struct binding_scope * scope
binding_state_t rewind_binding_state
struct lease * next_pending
binding_state_t desired_binding_state
binding_state_t binding_state
unsigned char address[16]
struct option_state * options
dhcp_failover_state_t * failover_peer
struct shared_network * next
int binding_scope_dereference(struct binding_scope **ptr, const char *file, int line)
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)
struct binding_scope * global_scope