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

📄 failover.c

📁 DHCP服务器源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			status = do_a_failover_option (c, link);			if (status != ISC_R_SUCCESS)				goto dhcp_flink_fail;		}		/* If it's a connect message, try to associate it with		   a state object. */		/* XXX this should be authenticated! */		if (link -> imsg -> type == FTM_CONNECT) {		    const char *errmsg;		    int reason;		    /* See if we can find a failover_state object that		       matches this connection.  This message should only		       be received by a secondary from a primary. */		    for (s = failover_states; s; s = s -> next) {			if (dhcp_failover_state_match			    (s, (u_int8_t *)&link -> imsg -> server_addr,			     sizeof link -> imsg -> server_addr))				state = s;		    }				    /* If we can't find a failover protocol state		       for this remote host, drop the connection */		    if (!state) {			    errmsg = "unknown server";			    reason = FTR_INVALID_PARTNER;			  badconnect:				/* XXX Send a refusal message first?				   XXX Look in protocol spec for guidance. */			    log_error ("Failover CONNECT from %u.%u.%u.%u: %s",				       ((u_int8_t *)					(&link -> imsg -> server_addr)) [0],				       ((u_int8_t *)					(&link -> imsg -> server_addr)) [1],				       ((u_int8_t *)					(&link -> imsg -> server_addr)) [2],				       ((u_int8_t *)					(&link -> imsg -> server_addr)) [3],				       errmsg);			    dhcp_failover_send_connectack				    ((omapi_object_t *)link, state,				     reason, errmsg);			    log_info ("failover: disconnect: %s", errmsg);			    omapi_disconnect (c, 0);			    link -> state = dhcp_flink_disconnected;			    return ISC_R_SUCCESS;		    }		    if ((cur_time > link -> imsg -> time &&			 cur_time - link -> imsg -> time > 60) ||			(cur_time < link -> imsg -> time &&			 link -> imsg -> time - cur_time > 60)) {			    errmsg = "time offset too large";			    reason = FTR_TIMEMISMATCH;			    goto badconnect;		    }		    if (!(link -> imsg -> options_present & FTB_HBA) ||			link -> imsg -> hba.count != 32) {			    errmsg = "invalid HBA";			    reason = FTR_HBA_CONFLICT; /* XXX */			    goto badconnect;		    }		    if (state -> hba)			    dfree (state -> hba, MDL);		    state -> hba = dmalloc (32, MDL);		    if (!state -> hba) {			    errmsg = "no memory";			    reason = FTR_MISC_REJECT;			    goto badconnect;		    }		    memcpy (state -> hba, link -> imsg -> hba.data, 32);		    if (!link -> state_object)			    dhcp_failover_state_reference				    (&link -> state_object, state, MDL);		    if (!link -> peer_address)			    option_cache_reference				    (&link -> peer_address,				     state -> partner.address, MDL);		}		/* If we don't have a state object at this point, it's		   some kind of bogus situation, so just drop the		   connection. */		if (!link -> state_object) {			log_info ("failover: connect: no matching state.");			omapi_disconnect (c, 1);			link -> state = dhcp_flink_disconnected;			return ISC_R_INVALIDARG;		}		/* Once we have the entire message, and we've validated		   it as best we can here, pass it to the parent. */		omapi_signal ((omapi_object_t *)link -> state_object,			      "message", link);		link -> state = dhcp_flink_message_length_wait;		failover_message_dereference (&link -> imsg, MDL);		/* XXX This is dangerous because we could get into a tight		   XXX loop reading input without servicing any other stuff.		   XXX There needs to be a way to relinquish control but		   XXX get it back immediately if there's no other work to		   XXX do. */		if ((omapi_connection_require (c, 2)) == ISC_R_SUCCESS)			goto next_message;		break;	      default:		/* XXX should never get here.   Assertion? */		break;	}	return ISC_R_SUCCESS;}static isc_result_t do_a_failover_option (c, link)	omapi_object_t *c;	dhcp_failover_link_t *link;{	u_int16_t option_code;	u_int16_t option_len;	unsigned char *op;	unsigned op_size;	unsigned op_count;	int i;	isc_result_t status;		if (link -> imsg_count + 2 > link -> imsg_len) {		log_error ("FAILOVER: message overflow at option code.");		return ISC_R_PROTOCOLERROR;	}	/* Get option code. */	omapi_connection_get_uint16 (c, &option_code);	link -> imsg_count += 2;		if (link -> imsg_count + 2 > link -> imsg_len) {		log_error ("FAILOVER: message overflow at length.");		return ISC_R_PROTOCOLERROR;	}	/* Get option length. */	omapi_connection_get_uint16 (c, &option_len);	link -> imsg_count += 2;	if (link -> imsg_count + option_len > link -> imsg_len) {		log_error ("FAILOVER: message overflow at data.");		return ISC_R_PROTOCOLERROR;	}	/* If it's an unknown code, skip over it. */	if (option_code > FTO_MAX) {#if defined (DEBUG_FAILOVER_MESSAGES)		log_debug ("  option code %d (%s) len %d (not recognized)",			   option_code,			   dhcp_failover_option_name (option_code),			   option_len);#endif		omapi_connection_copyout ((unsigned char *)0, c, option_len);		link -> imsg_count += option_len;		return ISC_R_SUCCESS;	}	/* If it's the digest, do it now. */	if (ft_options [option_code].type == FT_DIGEST) {		link -> imsg_count += option_len;		if (link -> imsg_count != link -> imsg_len) {			log_error ("FAILOVER: digest not at end of message");			return ISC_R_PROTOCOLERROR;		}#if defined (DEBUG_FAILOVER_MESSAGES)		log_debug ("  option %s len %d",			   ft_options [option_code].name, option_len);#endif		/* For now, just dump it. */		omapi_connection_copyout ((unsigned char *)0, c, option_len);		return ISC_R_SUCCESS;	}		/* Only accept an option once. */	if (link -> imsg -> options_present & ft_options [option_code].bit) {		log_error ("FAILOVER: duplicate option %s",			   ft_options [option_code].name);		return ISC_R_PROTOCOLERROR;	}	/* Make sure the option is appropriate for this type of message.	   Really, any option is generally allowed for any message, and the	   cases where this is not true are too complicated to represent in	   this way - what this code is doing is to just avoid saving the	   value of an option we don't have any way to use, which allows	   us to make the failover_message structure smaller. */	if (ft_options [option_code].bit &&	    !(fto_allowed [link -> imsg -> type] &	      ft_options [option_code].bit)) {		omapi_connection_copyout ((unsigned char *)0, c, option_len);		link -> imsg_count += option_len;		return ISC_R_SUCCESS;	}			/* Figure out how many elements, how big they are, and where	   to store them. */	if (ft_options [option_code].num_present) {		/* If this option takes a fixed number of elements,		   we expect the space for them to be preallocated,		   and we can just read the data in. */		op = ((unsigned char *)link -> imsg) +			ft_options [option_code].offset;		op_size = ft_sizes [ft_options [option_code].type];		op_count = ft_options [option_code].num_present;		if (option_len != op_size * op_count) {			log_error ("FAILOVER: option size (%d:%d), option %s",				   option_len,				   (ft_sizes [ft_options [option_code].type] *				    ft_options [option_code].num_present),				   ft_options [option_code].name);			return ISC_R_PROTOCOLERROR;		}	} else {		failover_option_t *fo;		/* FT_DDNS* are special - one or two bytes of status		   followed by the client FQDN. */		if (ft_options [option_code].type == FT_DDNS1 ||		    ft_options [option_code].type == FT_DDNS1) {			ddns_fqdn_t *ddns =				((ddns_fqdn_t *)				 (((char *)link -> imsg) +				  ft_options [option_code].offset));			op_count = (ft_options [option_code].type == FT_DDNS1				    ? 1 : 2);			omapi_connection_copyout (&ddns -> codes [0],						  c, op_count);			link -> imsg_count += op_count;			if (op_count == 1)				ddns -> codes [1] = 0;			op_size = 1;			op_count = option_len - op_count;			ddns -> length = op_count;			ddns -> data = dmalloc (op_count, MDL);			if (!ddns -> data) {				log_error ("FAILOVER: no memory getting%s(%d)",					   " DNS data ", op_count);				/* Actually, NO_MEMORY, but if we lose here				   we have to drop the connection. */				return ISC_R_PROTOCOLERROR;			}			omapi_connection_copyout (ddns -> data, c, op_count);			goto out;		}		/* A zero for num_present means that any number of		   elements can appear, so we have to figure out how		   many we got from the length of the option, and then		   fill out a failover_option structure describing the		   data. */		op_size = ft_sizes [ft_options [option_code].type];		/* Make sure that option data length is a multiple of the		   size of the data type being sent. */		if (op_size > 1 && option_len % op_size) {			log_error ("FAILOVER: option_len %d not %s%d",				   option_len, "multiple of ", op_size);			return ISC_R_PROTOCOLERROR;		}		op_count = option_len / op_size;				fo = ((failover_option_t *)		      (((char *)link -> imsg) +		       ft_options [option_code].offset));		fo -> count = op_count;		fo -> data = dmalloc (option_len, MDL);		if (!fo -> data) {			log_error ("FAILOVER: no memory getting %s (%d)",				   "option data", op_count);			return ISC_R_PROTOCOLERROR;		}					op = fo -> data;	}	/* For single-byte message values and multi-byte values that           don't need swapping, just read them in all at once. */	if (op_size == 1 || ft_options [option_code].type == FT_IPADDR) {		omapi_connection_copyout ((unsigned char *)op, c, option_len);		link -> imsg_count += option_len;		goto out;	}	/* For values that require swapping, read them in one at a time	   using routines that swap bytes. */	for (i = 0; i < op_count; i++) {		switch (ft_options [option_code].type) {		      case FT_UINT32:			omapi_connection_get_uint32 (c, (u_int32_t *)op);			op += 4;			link -> imsg_count += 4;			break;					      case FT_UINT16:			omapi_connection_get_uint16 (c, (u_int16_t *)op);			op += 2;			link -> imsg_count += 2;			break;					      default:			/* Everything else should have been handled			   already. */			log_error ("FAILOVER: option %s: bad type %d",				   ft_options [option_code].name,				   ft_options [option_code].type);			return ISC_R_PROTOCOLERROR;		}	}      out:	/* Remember that we got this option. */	link -> imsg -> options_present |= ft_options [option_code].bit;	return ISC_R_SUCCESS;}isc_result_t dhcp_failover_link_set_value (omapi_object_t *h,					   omapi_object_t *id,					   omapi_data_string_t *name,					   omapi_typed_data_t *value){	if (h -> type != omapi_type_protocol)		return ISC_R_INVALIDARG;	/* Never valid to set these. */	if (!omapi_ds_strcmp (name, "link-port") ||	    !omapi_ds_strcmp (name, "link-name") ||	    !omapi_ds_strcmp (name, "link-state"))		return ISC_R_NOPERM;	if (h -> inner && h -> inner -> type -> set_value)		return (*(h -> inner -> type -> set_value))			(h -> inner, id, name, value);	return ISC_R_NOTFOUND;}isc_result_t dhcp_failover_link_get_value (omapi_object_t *h,					   omapi_object_t *id,					   omapi_data_string_t *name,					   omapi_value_t **value){	dhcp_failover_link_t *link;	if (h -> type != omapi_type_protocol)		return ISC_R_INVALIDARG;	link = (dhcp_failover_link_t *)h;		if (!omapi_ds_strcmp (name, "link-port")) {		return omapi_make_int_value (value, name,					     (int)link -> peer_port, MDL);	} else if (!omapi_ds_strcmp (name, "link-state")) {		if (link -> state < 0 ||		    link -> state >= dhcp_flink_state_max)			return omapi_make_string_value (value, name,							"invalid link state",							MDL);		return omapi_make_string_value			(value, name,			 dhcp_flink_state_names [link -> state], MDL);	}	if (h -> inner && h -> inner -> type -> get_value)		return (*(h -> inner -> type -> get_value))			(h -> inner, id, name, value);	return ISC_R_NOTFOUND;}isc_result_t dhcp_failover_link_destroy (omapi_object_t *h,					 const char *file, int line){	dhcp_failover_link_t *link;	if (h -> type != dhcp_type_failover_link)		return ISC_R_INVALIDARG;	link = (dhcp_failover_link_t *)h;	if (link -> peer_address)		option_cache_dereference (&link -> peer_address, file, line);	if (link -> imsg)		failover_message_dereference (&link -> imsg, file, line);	if (link -> state_object)		dhcp_failover_state_dereference (&link -> state_object,						 file, line);	return ISC_R_SUCCESS;}/* Write all the published values associated with the object through the   specified connection. */isc_result_t dhcp_failover_link_stuff_values (omapi_object_t *c,					      omapi_object_t *id,					      omapi_object_t *l){	dhcp_failover_link_t *link;	isc_result_t status;	if (l -> type != dhcp_type_failover_link)		return ISC_R_INVALIDARG;	link = (dhcp_failover_link_t *)l;		status = omapi_connection_put_name (c, "link-port");	if (status != ISC_R_SUCCESS)		return status;	status = omapi_connection_put_uint32 (c, sizeof (int));	if (status != ISC_R_SUCCESS)		return status;	status = omapi_connection_put_uint32 (c, link -> peer_port);	if (status != ISC_R_SUCCESS)		return status;		status = omapi_connection_put_name (c, "link-state");	if (status != ISC_R_SUCCESS)		return status;	if (link -> state < 0 ||	    link -> state >= dhcp_flink_state_max)		status = omapi_connection_put_string (c, "invalid link state");	else		status = (omapi_connection_put_string			  (c, dhcp_flink_state_names [link -> state]));	if (status != ISC_R_SUCCESS)		return status;	if (link -> inner && link -> inner -> type -> stuff_values)		return (*(link -> inner -> type -> stuff_values)) (c, id,								link -> inner);	return ISC_R_SUCCESS;}

⌨️ 快捷键说明

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