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

📄 mn_api.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: mn_api.c,v 1.46 2001/09/29 16:06:39 jm Exp $ * Mobile Node - API handling * * 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. */#include "config.h"#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <time.h>#include "agentapi.h"#include "debug.h"#include "dyn_ip.h"#include "list.h"#include "util.h"#ifdef WITH_WIRELESS#include "monitor.h"#endif#include "mn.h"extern struct mn_data mn;extern struct mn_config config; /* configuration information */extern struct timeval timers[TIMER_COUNT];/* Policies can be changed on/off from dynmn_tool (policy) */static struct policy_vars monitor_policy[] = {	{EARLY_EXPIRE_STR,    EARLY_EXPIRE_BIT},	{NEWEST_FA_STR,       NEWEST_FA_BIT},	{EAGER_SWITCH_STR,    EAGER_SWITCH_BIT},	{NEWEST_ADV_STR,      NEWEST_ADV_BIT},	{"", -1}};static dyn_api_sockaddr api_addr; /* address of progressing api call */static socklen_t api_addr_len = 0;/* String representations of the states */char *state_strings[MN_STATE_COUNT] = {	"Startup", "Disconnected", "Find Agent", "Passive Find",	"Request Tunnel", "Connected",	"Close For Home", "At Home", "Error", "Stop" };/* Fill static status structure and return a pointer to it. */static struct dynamics_mobile_status *get_mobile_status(void){	static struct dynamics_mobile_status status;	status.state = mn.state;	if (mn.state >= 0 && mn.state < MN_STATE_COUNT)		dynamics_strlcpy(status.state_str, state_strings[mn.state],				 API_STATE_LEN);	else		memset(status.state_str, 0, sizeof(status.state_str));	status.local_addr = mn.local_addr;	status.co_addr = mn.co_addr;	status.fa_addr = mn.fa_addr;	status.ha_addr = config.ha_ip_addr;	status.home_addr = config.mn_home_ip_addr;	status.tunnel_up = mn.tunnel_up;	status.tunnel_mode = mn.tunnel_mode;	if (mn.tunnel_up) {		status.lifetime = timers[TIMER_LIFETIME].tv_sec - time(NULL);	} else {		status.lifetime = 0;	}	status.last_reply_code = mn.last_reply_code;	status.last_reply_rcvd = mn.last_reply_rcvd;	status.last_request_sent = mn.last_request_sent;	if (mn.info_str == NULL)		memset(status.info_str, 0, API_INFO_LEN + 1);	else		dynamics_strlcpy(status.info_str, mn.info_str,				 API_INFO_LEN + 1);	if (mn.warn_str == NULL)		memset(status.warn_str, 0, API_INFO_LEN + 1);	else		dynamics_strlcpy(status.warn_str, mn.warn_str,				 API_INFO_LEN + 1);	status.device_count = mn.device_count;	status.discarded_msgs = mn.discarded_msgs;	return &status;}/* * Handling function for API update location call. API message is in msg. * Set own local address according to msg. If in disconnected state, stay * there, but otherwise go to find_agent state, because we have * moved under another FA and we will want hear its address. * Tunnels must be updated for new address. */static void handle_api_locupd(int s, dyn_api_sockaddr *addr, socklen_t addrlen,			      struct api_msg *msg, int block_api){	int ok, i;	char device[IFNAMSIZ + 1];	struct in_addr iaddr;	/* locupd should have new IP address or interface name after four	 * zero octets */	ok = 1;	if (msg->length == 4) {		if (mn.local_addr.s_addr != (__u32) *msg->params) {			/* set local address */			memcpy(&mn.local_addr, msg->params, 4);			DEBUG(DEBUG_INFO, "Address changed to %s\n",			      inet_ntoa(mn.local_addr));		}	} else if (msg->length > 4 && msg->params[0] == 0 &&		msg->params[1] == 0 && msg->params[2] == 0 &&		msg->params[3] == 0) {		if (msg->length > IFNAMSIZ)			ok = 0;		else {			memcpy(device, msg->params + 4, msg->length - 4);			device[msg->length - 4] = '\0';			ok = 2;		}	} else if (msg->length == 0) {		/* try to use the first available interface */		for (i = 0; i < MAX_INTERFACES; i++) {			if (mn.iface[i].s > -1) {				memcpy(device, mn.iface[i].device, IFNAMSIZ);				device[sizeof(device) - 1] = '\0';				ok = 2;				break;			}		}		if (ok != 2) ok = 0;	} else ok = 0;	if (ok == 2) {		DEBUG(DEBUG_INFO, "\tinterface[%s]\n", device);		if (dyn_ip_get_ifaddr(device, &iaddr) < 0)			ok = 0;		else if (mn.local_addr.s_addr != iaddr.s_addr) {			DEBUG(DEBUG_INFO,			      "Address changed to %s (%s)\n",			      inet_ntoa(iaddr), device);			mn.local_addr.s_addr = iaddr.s_addr;		}	}	if (!ok) {		DEBUG(DEBUG_INFO, "API: locupd failed - illegal parameter\n");		api_send_reply(s, addr, addrlen, API_ILLEGAL_PARAMETERS, NULL,			       0);		return;	}	/* check if we are at home */	if (mn.local_addr.s_addr == config.mn_home_ip_addr.s_addr &&	    !config.enable_fa_decapsulation) {		close_for_home(STATE_INIT);	} else {		switch (mn.state) {		case MN_DISCONNECTED:			break;		default:			/* allow quick locupd */			timerclear(&mn.last_reg_send_time);			find_agent(STATE_INIT);			break;		}	}	if (!block_api)		api_send_reply(s, addr, addrlen, API_SUCCESS, NULL, 0);}static void handle_api_force_fa(int s, dyn_api_sockaddr *addr,				socklen_t addrlen,				struct api_msg *msg){	/* force_fa should have new address */	if (msg->length != 4) {		api_send_reply(s, addr, addrlen, API_ILLEGAL_PARAMETERS, NULL,			       0);		return;	}	/* set local address */	memcpy(&mn.force_fa_addr, msg->params, 4);	DEBUG(DEBUG_INFO, "Force FA address set to %s\n",	      inet_ntoa(mn.force_fa_addr));	api_send_reply(s, addr, addrlen, API_SUCCESS, NULL, 0);}static int adv_iter(struct node *node, void *data){	struct agentadv_data *adv;	struct api_msg *api_msg;	struct dynamics_mobile_fa_list *list;	int size, tmp;	unsigned int flags;	adv = (struct agentadv_data *) node;	api_msg = (struct api_msg *) data;	list = (struct dynamics_mobile_fa_list *)		((char *) api_msg->params + api_msg->length);	size = sizeof(struct dynamics_mobile_fa_list);	if ((api_msg->length + size) > API_DATA_SIZE) {		DEBUG(DEBUG_INFO, "adv_iter: Not enough room in msg "		      " (itemsize %d, length %d)\n",		      size, api_msg->length);		return 0;	}	api_msg->length += size;	/* copy values */	UNALIGNED_(&list->addr, &adv->addr);	MOVE_UNALIGNED(list->interface, adv->ifname, IFNAMSIZ);	UNALIGNED_(&list->in_use, &adv->in_use);	if (mn.current_adv != NULL && 	    adv->addr.s_addr == mn.current_adv->addr.s_addr) {		tmp = 1;	} else {		tmp = 0;	}	UNALIGNED_(&list->current_adv, &tmp);	flags = 0;	if (adv->adv.ext) {		int opts = ntohs(adv->adv.ext->opts);		if (opts & AGENT_ADV_FOREIGN_AGENT)			flags |= API_MA_FLAGS_FA;		if (opts & AGENT_ADV_HOME_AGENT)			flags |= API_MA_FLAGS_HA;		if (opts & AGENT_ADV_BUSY)			flags |= API_MA_FLAGS_BUSY;	}	if (adv->adv.own_ext)		flags |= API_MA_FLAGS_DYNAMICS;	UNALIGNED_(&list->flags, &flags);#ifdef WITH_WIRELESS	if (adv->mon != NULL) {		tmp = adv->mon->avg;	} else {		tmp = -1;	}#else	tmp = -1;#endif	UNALIGNED_(&list->quality_avg, &tmp);		/* Priorities aren't calculated if MN is in DISCONNECTED           state. That is why we don't want to update priority because           it's not up to date information and may confuse the           user. */	if (mn.state == MN_DISCONNECTED) {		tmp = -2;  /* not up to date information */                UNALIGNED_(&list->priority, &tmp); 	} else 	        UNALIGNED_(&list->priority, &adv->priority);        UNALIGNED_(&list->last, &adv->last.tv_sec);	UNALIGNED_(&list->reduce, &adv->prio_degrade_percent);		return 1;}static void handle_api_get_fa_list(int s, dyn_api_sockaddr *addr,				   socklen_t addrlen,				   struct api_msg *msg){	msg->length = 0;	hashtable_iterator(mn.agentadv, adv_iter, msg);	api_send_reply(s, addr, addrlen, API_SUCCESS,		       (unsigned char *) &msg->params, msg->length);}static void handle_api_get_fa_info(int s, dyn_api_sockaddr *addr,				   socklen_t addrlen,				   struct api_msg *msg){	struct dynamics_mobile_fa_info *info;	struct agentadv_data *adv;	struct in_addr fa_addr;	int ifindex, tmp;	char interface[IFNAMSIZ + 1];	char nai[API_MAX_NAI_LEN + 1];	/* should have fa address */	if (msg->length != sizeof(struct dynamics_mobile_fa_info)) {		api_send_reply(s, addr, addrlen, API_ILLEGAL_PARAMETERS, NULL,			       0);		return;	}	info = (struct dynamics_mobile_fa_info *)&msg->params;	MOVE_UNALIGNED(&fa_addr, &info->list.addr, sizeof(struct in_addr));	DEBUG(DEBUG_API, "handle_api_get_fa_info: %s\n",	      inet_ntoa(fa_addr));		ifindex = 0;	MOVE_UNALIGNED(interface, &info->list.interface, IFNAMSIZ);	interface[IFNAMSIZ] = '\0';	if (strlen(interface) > 0) {		ifindex = dyn_ip_get_ifindex(interface);		DEBUG(DEBUG_API, "handle_api_get_fa_info: interface \"%s\""		      " ifindex %d\n", interface, ifindex);	}	adv = adv_fetch(mn.agentadv, &fa_addr, ifindex);	if (adv == NULL) {		DEBUG(DEBUG_API, "handle_api_get_fa_info: %s not found\n",		      inet_ntoa(fa_addr));		api_send_reply(s, addr, addrlen, API_FAILED, NULL, 0);		return;	}	msg->length = sizeof(struct dynamics_mobile_fa_info);	UNALIGNED_(&info->list.addr, &adv->addr);	UNALIGNED_(&info->list.in_use, &adv->in_use);	UNALIGNED_(&info->ifindex, &ifindex);#ifdef WITH_WIRELESS	if (adv->mon != NULL)		UNALIGNED_(&info->list.quality_avg, &adv->mon->avg);	else {		tmp = -1;		UNALIGNED_(&info->list.quality_avg, &tmp);	}#else	tmp = -1;	UNALIGNED_(&info->list.quality_avg, &tmp);#endif	UNALIGNED_(&tmp, &info->list.quality_avg);	DEBUG(DEBUG_INFO, "quality: %d\n", tmp);	UNALIGNED_(&info->list.priority, &adv->priority);	UNALIGNED_(&info->ifindex, &adv->ifindex);	MOVE_UNALIGNED(info->list.interface, adv->ifname, sizeof(adv->ifname));	UNALIGNED_(&info->list.last, &adv->last.tv_sec);	UNALIGNED_(&info->expire, &adv->expire.tv_sec);	UNALIGNED_(&info->arpentry, &adv->arpentry);	nai[0] = '\0';	if (adv->adv.fa_nai != NULL &&	    API_MAX_NAI_LEN >= GET_NAI_LEN(adv->adv.fa_nai)) {		memcpy(nai, MSG_NAI_DATA(adv->adv.fa_nai), API_MAX_NAI_LEN);		nai[GET_NAI_LEN(adv->adv.fa_nai)] = '\0';	}	DEBUG(DEBUG_INFO, "\tNAI[%s]\n", nai);	MOVE_UNALIGNED(&info->nai, &nai, API_MAX_NAI_LEN + 1);	api_send_reply(s, addr, addrlen, API_SUCCESS,		       (unsigned char *) &msg->params, msg->length);}#ifdef WITH_WIRELESSstatic void handle_api_get_iw_ch(int s, dyn_api_sockaddr *addr,				 socklen_t addrlen,				 struct api_msg *msg){	int r;

⌨️ 快捷键说明

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