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

📄 ha.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* $Id: ha.c,v 1.204 2001/10/20 15:41:38 jm Exp $ * Home Agent daemon * * Dynamic hierarchial IP tunnel * Copyright (C) 1998-2001, Dynamics group * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See README and COPYING for * more details. */#ifdef HAVE_CONFIG_H#include <config.h>#endif#define DEBUG_FLAG 'H'#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <string.h>#include <stdio.h>#include <arpa/inet.h>#include <sys/un.h>#include <net/if.h>#include <sys/time.h>#include <unistd.h>#include <syslog.h>#ifndef __USE_BSD#define __USE_BSD /* for sigblock et al. */#endif#include <signal.h>#include <time.h>#include <stdlib.h>#include <assert.h>#include <errno.h>#include <getopt.h>#include <sys/uio.h>#include "ha.h"#include "list.h"#include "hashtable.h"#include "fileio.h"#include "msgparser.h"#include "agentadv.h"#include "proxyarp.h"#include "binding.h"#include "auth.h"#include "tunnel.h"#include "debug.h"#include "agentapi.h"#include "util.h"#include "fixed_fd_zero.h"#include "dyn_ip.h"#include "ha_config.h"#include "agent_utils.h"#include "md5_mac.h"/* util.c - common command line arguments */extern int opt_foreground;extern char *opt_config;/******************** * defines ********************/#define ASSERT assert#define MIN(x, y) ( (x) < (y) ? (x) : (y))#define LOG2(lev, fmt, args...) { DEBUG(DEBUG_FLAG, fmt, ## args); \  syslog(lev, fmt, ## args); }#define MAX_ADV_DELAY 200000.0 /* wait random 0 - MAX_ADV_DELAY microseconds 				  befora sending agent advertisement (either 				  broadcast or unicast, answer to agent 				  solicitation *//********************* * function prototypes *********************//* called before the home agent terminates to do some cleaning */static void clean_up();/* functions for handling requests, creating and destroying * tunnels (bindings) */static void remove_tunnel(struct bindingentry *binding);static void destroy_binding(struct bindingentry *binding);static struct fa_spi_entry* get_fa_spi(int spi, struct in_addr addr);static struct spi_entry* get_mn_spi(int spi);static void init_interfaces(void);/******************** * global variables ********************/static struct ha_config config;struct fa_nai_ext *ha_nai = NULL;static HASH *tunnels;static struct bindingtable *bindings;static int bindingcount = 0;static char *program_name; /* the name this program was run with */static struct dynamics_ha_status stats;/**********************************************************************//** * set_ha_nai: * * Setup global variable ha_nai according to config.ha_nai. set_ha_nai() * release the previously allocated buffer and allocates a new buffer for the * new HA NAI extension. */static voidset_ha_nai(void){	if (ha_nai != NULL) {		free(ha_nai);		ha_nai = NULL;	}	if (config.ha_nai[0] != '\0') {		ha_nai = (struct fa_nai_ext *)			malloc(sizeof(struct fa_nai_ext) +			       strlen(config.ha_nai));		if (ha_nai == NULL) {			DEBUG(DEBUG_FLAG, "Not enough memory for ha_nai\n");			clean_up(1);		}		ha_nai->type = VENDOR_EXT_TYPE2;		ha_nai->reserved = 0;		ha_nai->length = sizeof(struct fa_nai_ext) - 2 +			strlen(config.ha_nai);		ha_nai->vendor_id = htonl(VENDOR_ID_DYNAMICS);		ha_nai->sub_type = htons(VENDOR_EXT_DYNAMICS_FA_NAI);		memcpy(ha_nai + 1, config.ha_nai, strlen(config.ha_nai));	}}/** * reload_config: * * SIGHUP handler for reloading the configuration. */static voidreload_config(int sig){	LOG2(LOG_INFO, "Received signal %d, rereading configuration\n", sig);	cleanup_config(&config);        if (load_config(&config, program_name,			opt_config == NULL ? HA_GLOBAL_CONF_FILE : opt_config)	    == FALSE) {		LOG2(LOG_ALERT, "Reloading configuration file failed\n");		clean_up(1);	}	init_interfaces();	set_ha_nai();	/* If the Port configuration is changed in the configuration	 * file, it will have no effect on a reload. If this functionality	 * is needed, the code should close the old sockets and reopen them	 * here. */}/********************************************************************** * clean up stuff **********************************************************************//** * binding_hash_iterator: * @node: bindingentry * @dummy: not used * * Hashtable iterator for clean_up() function; releases the resources reserved * for the bindings. * * Returns: *  1 (to continue iterator loop) */static intbinding_cleanup_iterator(struct node *node, void *dummy){	struct bindingentry *data = (struct bindingentry *) node;	ASSERT(data != NULL);		binding_remove(data);	remove_tunnel(data);	destroy_binding(data);	return 1;}/** * sig_handler: * * Called on various signals to end the process. */static voidsig_handler(int sig){	LOG2(LOG_INFO, "signal %d received, cleaning up\n", sig);	clean_up(sig); /* calls clean_up */}	/** * clean_up: * * Clean up allocated resources and terminate HA daemon execution. */static voidclean_up(int value){	/* destroy all hashes and finish nicely */	if (bindings != NULL) {		binding_iterator(bindings, binding_cleanup_iterator, NULL);		binding_destroy(bindings);	}	if (tunnels != NULL)		tunnel_destroy_hash(tunnels);	/* remove old unix sockets */	if (config.ha_api_read_socket_path[0] != '\0')		unlink(config.ha_api_read_socket_path);	if (config.ha_api_admin_socket_path[0] != '\0')		unlink(config.ha_api_admin_socket_path);	if (unlink(HA_PID_FILE) < 0) {		LOG2(LOG_INFO, "clean_up() could not remove PID file ("		     HA_PID_FILE "): %s\n", strerror(errno));	}	cleanup_config(&config);	if (ha_nai != NULL) {		free(ha_nai);		ha_nai = NULL;	}	syslog(LOG_INFO, "%s home agent daemon version %s stopped\n",	       PACKAGE, VERSION);	closelog();	exit(value);}/********************************************************************** * API handling **********************************************************************//** * binding_get_tunnels_iter: * @node: pointer to bindingentry * @data: pointer to the message to be returned to the API caller * * Called from handle_api on an API_GET_TUNNELS request. This function is * called for each existing binding in the bindings list. * * Returns: *  1 (to continue iteration loop) */static intbinding_get_tunnels_iter(struct node *node, void *data){	struct bindingentry *binding = (struct bindingentry *) node;	struct api_msg *api_msg = (struct api_msg *) data;	dyn_tunnel_id id;	if (api_msg->length + sizeof(dyn_tunnel_id) > API_DATA_SIZE) {		DEBUG(DEBUG_FLAG, "API message overflow - skipping rest of "		      "the bindings\n");		return 0;	}	id.mn_addr.s_addr = binding->mn_addr.s_addr;	id.ha_addr.s_addr = binding->ha_addr.s_addr;	id.priv_ha = 0;	memcpy((char *) api_msg->params + api_msg->length, &id,	       sizeof(dyn_tunnel_id));	api_msg->length += sizeof(dyn_tunnel_id);	return 1;}/** * api_fetch_binding: * @msg: pointer to received API message * * Check that the dynamics_tunnel_id is in correct format and fetch the * requested binding. * * Returns: *   Pointer to the requested binding or NULL on failure. */static struct bindingentry*api_fetch_binding(struct api_msg *msg){	dyn_tunnel_id *tid;	struct bindingkey bkey;	struct bindingentry *binding;	if (msg->length != sizeof(dyn_tunnel_id)) {		LOG2(LOG_ERR, "API message has wrong length (%i, expected %i)"		     "\n", msg->length, sizeof(dyn_tunnel_id));		return NULL;	}	tid = (dyn_tunnel_id *) msg->params;	bkey.mn_addr = tid->mn_addr;	if (config.sha_addr.s_addr != 0)		bkey.ha_addr = config.sha_addr;	else if (tid->ha_addr.s_addr != 0)		bkey.ha_addr = tid->ha_addr;	else {		struct interface_entry *iface;		iface = (struct interface_entry *)			list_get_first(&config.interfaces);		if (iface == NULL)			return NULL;		bkey.ha_addr = iface->addr;	}	bkey.priv_ha = config.priv_ha;	binding = binding_fetch(bindings, &bkey);	if (!binding) {		DEBUG(DEBUG_FLAG, "   API call could not find the request "		      "binding\n");	}	return binding;}/** * handle_api: * @socket: the socket where the request arrived * @priv: whether the request is privileged to do administrative actions * * Receives an API request, executes the requested tasks, and sends the result. * * Returns: *   0 on success, -1 on failure */static inthandle_api(int socket, int priv){	struct sockaddr_un cli_addr;	socklen_t cli_len;	int n;	struct api_msg recv_msg;	struct api_msg send_msg;	struct bindingentry *binding;	struct dynamics_tunnel_info *info;	struct dynamics_ha_status *status;	memset(&cli_addr, 0, sizeof(cli_addr));	cli_len = sizeof(cli_addr);	n = recvfrom(socket, &recv_msg, sizeof(struct api_msg), 0,		     (struct sockaddr*)&cli_addr,		     &cli_len);	LOG2(LOG_DEBUG, "API: received %d bytes from %s\n", n,	     cli_addr.sun_path);	if (n < 0) {		LOG2(LOG_ERR, "handle_api - recvfrom failed - %s\n",		     strerror(errno));		return -1;	}	if (priv)		stats.apicalls_admin++;	else		stats.apicalls_read++;	memset(&send_msg, 0, sizeof(struct api_msg));	send_msg.type = API_REPLY_MSG;	send_msg.code = API_UNDEFINED;	send_msg.length = 0;	switch (recv_msg.code) {        case API_GET_TUNNELS:		DEBUG(DEBUG_FLAG, "Received API_GET_TUNNELS\n");		if (recv_msg.length != 0) {			LOG2(LOG_ERR,			     "API_GET_TUNNELS message has wrong length\n");			send_msg.code = API_ILLEGAL_PARAMETERS;			break;		}		/* get the list of bindings into send_msg */		if (binding_iterator(bindings, binding_get_tunnels_iter,				     &send_msg))			send_msg.code = API_SUCCESS;		else			send_msg.code = API_INSUFFICIENT_SPACE;		break;        case API_GET_TUNNEL_INFO:		DEBUG(DEBUG_FLAG, "Received API_GET_TUNNEL_INFO\n");		binding = api_fetch_binding(&recv_msg);		if (!binding) {			send_msg.code = API_FAILED;			break;		}		info = (struct dynamics_tunnel_info *) send_msg.params;		memset(info, 0, sizeof(struct dynamics_tunnel_info));		info->id.mn_addr.s_addr = binding->mn_addr.s_addr;		info->id.ha_addr.s_addr = binding->ha_addr.s_addr;		info->mn_addr.s_addr = binding->mn_addr.s_addr;		info->co_addr.s_addr = binding->lower_addr.s_addr;		info->ha_addr.s_addr = binding->ha_addr.s_addr;		info->expiration_time = binding->exp_time;		info->creation_time = binding->create_time;		info->refresh_time = binding->mod_time;		info->last_timestamp[0] = ntohl(binding->id[0]);		info->last_timestamp[1] = ntohl(binding->id[1]);		info->spi = binding->spi;		info->confirmed = 1;		info->timeout = binding->timeout;		send_msg.code = API_SUCCESS;		send_msg.length = sizeof(struct dynamics_tunnel_info);		break;	case API_DESTROY_TUNNEL:		DEBUG(DEBUG_FLAG, "Received API_DESTROY_TUNNEL\n");		if (!priv) {			send_msg.code = API_NOT_PERMITTED;			break;		}

⌨️ 快捷键说明

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