⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 failover.c

📁 DHCP服务器源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* failover.c   Failover protocol support code... *//* * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 1999-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * *   Internet Systems Consortium, Inc. *   950 Charter Street *   Redwood City, CA 94063 *   <info@isc.org> *   http://www.isc.org/ * * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. * To learn more about Internet Systems Consortium, see * ``http://www.isc.org/''.  To learn more about Vixie Enterprises, * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see * ``http://www.nominum.com''. */#ifndef lintstatic char copyright[] ="$Id: failover.c,v 1.53.2.32 2004/06/22 20:46:23 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";#endif /* not lint */#include "dhcpd.h"#include "version.h"#include <omapip/omapip_p.h>#if defined (FAILOVER_PROTOCOL)dhcp_failover_state_t *failover_states;static isc_result_t do_a_failover_option (omapi_object_t *,					  dhcp_failover_link_t *);dhcp_failover_listener_t *failover_listeners;static isc_result_t failover_message_reference (failover_message_t **,						failover_message_t *,						const char *file, int line);static isc_result_t failover_message_dereference (failover_message_t **,						  const char *file, int line);void dhcp_failover_startup (){	dhcp_failover_state_t *state;	isc_result_t status;	dhcp_failover_listener_t *l;	for (state = failover_states; state; state = state -> next) {		dhcp_failover_state_transition (state, "startup");		if (state -> pool_count == 0) {			log_error ("failover peer declaration with no %s",				   "referring pools.");			log_error ("In order to use failover, you MUST %s",				   "refer to your main failover declaration");			log_error ("in each pool declaration.   You MUST %s",				   "NOT use range declarations outside");			log_fatal ("of pool declarations.");		}		/* In case the peer is already running, immediately try		   to establish a connection with it. */		status = dhcp_failover_link_initiate ((omapi_object_t *)state);		if (status != ISC_R_SUCCESS && status != ISC_R_INCOMPLETE) {#if defined (DEBUG_FAILOVER_TIMING)			log_info ("add_timeout +90 dhcp_failover_reconnect");#endif			add_timeout (cur_time + 90,				     dhcp_failover_reconnect, state,				     (tvref_t)				     dhcp_failover_state_reference,				     (tvunref_t)				     dhcp_failover_state_dereference);			log_error ("failover peer %s: %s", state -> name,				   isc_result_totext (status));		}		status = (dhcp_failover_listen			  ((omapi_object_t *)state));		if (status != ISC_R_SUCCESS) {#if defined (DEBUG_FAILOVER_TIMING)			log_info ("add_timeout +90 %s",				  "dhcp_failover_listener_restart");#endif			add_timeout (cur_time + 90,				     dhcp_failover_listener_restart,				     state,				     (tvref_t)omapi_object_reference,				     (tvunref_t)omapi_object_dereference);		}	}}int dhcp_failover_write_all_states (){	dhcp_failover_state_t *state;	for (state = failover_states; state; state = state -> next) {		if (!write_failover_state (state))			return 0;	}	return 1;}isc_result_t enter_failover_peer (peer)	dhcp_failover_state_t *peer;{	dhcp_failover_state_t *dup = (dhcp_failover_state_t *)0;	isc_result_t status;	status = find_failover_peer (&dup, peer -> name, MDL);	if (status == ISC_R_NOTFOUND) {		if (failover_states) {			dhcp_failover_state_reference (&peer -> next,						      failover_states, MDL);			dhcp_failover_state_dereference (&failover_states,							 MDL);		}		dhcp_failover_state_reference (&failover_states, peer, MDL);		return ISC_R_SUCCESS;	}	dhcp_failover_state_dereference (&dup, MDL);	if (status == ISC_R_SUCCESS)		return ISC_R_EXISTS;	return status;}isc_result_t find_failover_peer (peer, name, file, line)	dhcp_failover_state_t **peer;	const char *name;	const char *file;	int line;{	dhcp_failover_state_t *p;	for (p = failover_states; p; p = p -> next)		if (!strcmp (name, p -> name))			break;	if (p)		return dhcp_failover_state_reference (peer, p, file, line);	return ISC_R_NOTFOUND;}/* The failover protocol has three objects associated with it.  For   each failover partner declaration in the dhcpd.conf file, primary   or secondary, there is a failover_state object.  For any primary or   secondary state object that has a connection to its peer, there is   also a failover_link object, which has its own input state seperate   from the failover protocol state for managing the actual bytes   coming in off the wire.  Finally, there will be one listener object   for every distinct port number associated with a secondary   failover_state object.  Normally all secondary failover_state   objects are expected to listen on the same port number, so there   need be only one listener object, but if different port numbers are   specified for each failover object, there could be as many as one   listener object for each secondary failover_state object. *//* This, then, is the implemention of the failover link object. */isc_result_t dhcp_failover_link_initiate (omapi_object_t *h){	isc_result_t status;	dhcp_failover_link_t *obj;	omapi_value_t *value = (omapi_value_t *)0;	dhcp_failover_state_t *state;	omapi_object_t *o;	int i;	struct data_string ds;	omapi_addr_list_t *addrs = (omapi_addr_list_t *)0;	omapi_addr_t local_addr;	/* Find the failover state in the object chain. */	for (o = h; o -> outer; o = o -> outer)		;	for (; o; o = o -> inner) {		if (o -> type == dhcp_type_failover_state)			break;	}	if (!o)		return ISC_R_INVALIDARG;	state = (dhcp_failover_state_t *)o;	obj = (dhcp_failover_link_t *)0;	status = dhcp_failover_link_allocate (&obj, MDL);	if (status != ISC_R_SUCCESS)		return status;	option_cache_reference (&obj -> peer_address,				state -> partner.address, MDL);	obj -> peer_port = state -> partner.port;	dhcp_failover_state_reference (&obj -> state_object, state, MDL);	memset (&ds, 0, sizeof ds);	if (!evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0,				    (struct client_state *)0,				    (struct option_state *)0,				    (struct option_state *)0,				    &global_scope, obj -> peer_address, MDL)) {		dhcp_failover_link_dereference (&obj, MDL);		return ISC_R_UNEXPECTED;	}	/* Make an omapi address list out of a buffer containing zero or more	   IPv4 addresses. */	status = omapi_addr_list_new (&addrs, ds.len / 4, MDL);	if (status != ISC_R_SUCCESS) {		dhcp_failover_link_dereference (&obj, MDL);		return status;	}	for (i = 0; i  < addrs -> count; i++) {		addrs -> addresses [i].addrtype = AF_INET;		addrs -> addresses [i].addrlen = sizeof (struct in_addr);		memcpy (addrs -> addresses [i].address,			&ds.data [i * 4], sizeof (struct in_addr));		addrs -> addresses [i].port = obj -> peer_port;	}	data_string_forget (&ds, MDL);	/* Now figure out the local address that we're supposed to use. */	if (!state -> me.address ||	    !evaluate_option_cache (&ds, (struct packet *)0,				    (struct lease *)0,				    (struct client_state *)0,				    (struct option_state *)0,				    (struct option_state *)0,				    &global_scope, state -> me.address,				    MDL)) {		memset (&local_addr, 0, sizeof local_addr);		local_addr.addrtype = AF_INET;		local_addr.addrlen = sizeof (struct in_addr);		if (!state -> server_identifier.len) {			log_fatal ("failover peer %s: no local address.",				   state -> name);		}	} else {		if (ds.len != sizeof (struct in_addr)) {			data_string_forget (&ds, MDL);			dhcp_failover_link_dereference (&obj, MDL);			omapi_addr_list_dereference (&addrs, MDL);			return ISC_R_INVALIDARG;		}		local_addr.addrtype = AF_INET;		local_addr.addrlen = ds.len;		memcpy (local_addr.address, ds.data, ds.len);		if (!state -> server_identifier.len)			data_string_copy (&state -> server_identifier,					  &ds, MDL);		data_string_forget (&ds, MDL);		local_addr.port = 0;  /* Let the O.S. choose. */	}	status = omapi_connect_list ((omapi_object_t *)obj,				     addrs, &local_addr);	omapi_addr_list_dereference (&addrs, MDL);	dhcp_failover_link_dereference (&obj, MDL);	return status;}isc_result_t dhcp_failover_link_signal (omapi_object_t *h,					const char *name, va_list ap){	isc_result_t status;	dhcp_failover_link_t *link;	omapi_object_t *c;	u_int16_t nlen;	u_int32_t vlen;	dhcp_failover_state_t *s, *state = (dhcp_failover_state_t *)0;	if (h -> type != dhcp_type_failover_link) {		/* XXX shouldn't happen.   Put an assert here? */		return ISC_R_UNEXPECTED;	}	link = (dhcp_failover_link_t *)h;	if (!strcmp (name, "connect")) {	    if (link -> state_object -> i_am == primary) {		status = dhcp_failover_send_connect (h);		if (status != ISC_R_SUCCESS) {		    log_info ("dhcp_failover_send_connect: %s",			      isc_result_totext (status));		    omapi_disconnect (h -> outer, 1);		}	    } else		status = ISC_R_SUCCESS;	    /* Allow the peer fifteen seconds to send us a	       startup message. */#if defined (DEBUG_FAILOVER_TIMING)	    log_info ("add_timeout +15 %s",		      "dhcp_failover_link_startup_timeout");#endif	    add_timeout (cur_time + 15,			 dhcp_failover_link_startup_timeout,			 link,			 (tvref_t)dhcp_failover_link_reference,			 (tvunref_t)dhcp_failover_link_dereference);	    return status;	}	if (!strcmp (name, "disconnect")) {	    if (link -> state_object) {		dhcp_failover_state_reference (&state,					       link -> state_object, MDL);		link -> state = dhcp_flink_disconnected;		/* Make the transition. */		if (state -> link_to_peer == link) {		    dhcp_failover_state_transition (link -> state_object,						    name);		    /* Start trying to reconnect. */#if defined (DEBUG_FAILOVER_TIMING)		    log_info ("add_timeout +5 %s",			      "dhcp_failover_reconnect");#endif		    add_timeout (cur_time + 5, dhcp_failover_reconnect,				 state,				 (tvref_t)dhcp_failover_state_reference,				 (tvunref_t)dhcp_failover_state_dereference);		}		dhcp_failover_state_dereference (&state, MDL);	    }	    return ISC_R_SUCCESS;	}	/* Not a signal we recognize? */	if (strcmp (name, "ready")) {		if (h -> inner && h -> inner -> type -> signal_handler)			return (*(h -> inner -> type -> signal_handler))				(h -> inner, name, ap);		return ISC_R_NOTFOUND;	}	if (!h -> outer || h -> outer -> type != omapi_type_connection)		return ISC_R_INVALIDARG;	c = h -> outer;	/* We get here because we requested that we be woken up after           some number of bytes were read, and that number of bytes           has in fact been read. */	switch (link -> state) {	      case dhcp_flink_start:		link -> state = dhcp_flink_message_length_wait;		if ((omapi_connection_require (c, 2)) != ISC_R_SUCCESS)			break;	      case dhcp_flink_message_length_wait:	      next_message:		link -> state = dhcp_flink_message_wait;		link -> imsg = dmalloc (sizeof (failover_message_t), MDL);		if (!link -> imsg) {			status = ISC_R_NOMEMORY;		      dhcp_flink_fail:			if (link -> imsg) {				failover_message_dereference (&link->imsg,							      MDL);			}			link -> state = dhcp_flink_disconnected;			log_info ("message length wait: %s",				  isc_result_totext (status));			omapi_disconnect (c, 1);			/* XXX just blow away the protocol state now?			   XXX or will disconnect blow it away? */			return ISC_R_UNEXPECTED;		}		memset (link -> imsg, 0, sizeof (failover_message_t));		link -> imsg -> refcnt = 1;		/* Get the length: */		omapi_connection_get_uint16 (c, &link -> imsg_len);		link -> imsg_count = 0;	/* Bytes read. */				/* Maximum of 2048 bytes in any failover message. */		if (link -> imsg_len > DHCP_FAILOVER_MAX_MESSAGE_SIZE) {			status = ISC_R_UNEXPECTED;			goto dhcp_flink_fail;		}		if ((omapi_connection_require (c, link -> imsg_len - 2U)) !=		    ISC_R_SUCCESS)			break;	      case dhcp_flink_message_wait:		/* Read in the message.  At this point we have the		   entire message in the input buffer.  For each		   incoming value ID, set a bit in the bitmask		   indicating that we've gotten it.  Maybe flag an		   error message if the bit is already set.  Once		   we're done reading, we can check the bitmask to		   make sure that the required fields for each message		   have been included. */		link -> imsg_count += 2;	/* Count the length as read. */		/* Get message type. */		omapi_connection_copyout (&link -> imsg -> type, c, 1);		link -> imsg_count++;		/* Get message payload offset. */		omapi_connection_copyout (&link -> imsg_payoff, c, 1);		link -> imsg_count++;		/* Get message time. */		omapi_connection_get_uint32 (c, &link -> imsg -> time);		link -> imsg_count += 4;		/* Get transaction ID. */		omapi_connection_get_uint32 (c, &link -> imsg -> xid);		link -> imsg_count += 4;#if defined (DEBUG_FAILOVER_MESSAGES)		log_info ("link: message %s  payoff %d  time %ld  xid %ld",			  dhcp_failover_message_name (link -> imsg -> type),			  link -> imsg_payoff,			  (unsigned long)link -> imsg -> time,			  (unsigned long)link -> imsg -> xid);#endif		/* Skip over any portions of the message header that we		   don't understand. */		if (link -> imsg_payoff - link -> imsg_count) {			omapi_connection_copyout ((unsigned char *)0, c,						  (link -> imsg_payoff -						   link -> imsg_count));			link -> imsg_count = link -> imsg_payoff;		}						/* Now start sucking options off the wire. */		while (link -> imsg_count < link -> imsg_len) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -