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

📄 mn_handler.c

📁 mobile ip 在linux下的一种实现
💻 C
字号:
/* $id: mn_handler.c,v 1.5 1999/09/21 19:15:08 dforsber Exp $ * Mobile Node handler module * * 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#include <stddef.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <errno.h>#ifdef DYN_TARGET_LINUX#include <linux/if.h>#endif#include "mn_handler.h"#include "mn.h"#include "debug.h"#include "util.h"#include "device_info.h"#include "fixed_fd_zero.h"extern struct mn_data mn;extern int real_tunnel_up; /* from mn_tunnel *//* Event hooks. Handler lists */static struct list fa_adv_rec_handlers;static struct list fa_adv_exp_handlers;static struct list fa_get_handlers;static struct list interface_init_handlers;static struct list interface_down_handlers;/* MN default Handlers (called first) */static int mn_default_FA_GET_handler(void *data);static int mn_default_INTERFACE_INIT_handler(void *data);static int mn_default_INTERFACE_DOWN_handler(void *data);static int get_device_priority(char *ifname){	int i;	if (ifname == NULL)		return -1;	for (i = 0; i < MAX_INTERFACES; i++) {		if (mn.iface[i].s > -1 && 		    strncmp(mn.iface[i].device, ifname, IFNAMSIZ) == 0) {			DEBUG(DEBUG_HANDLERS, "\tdevice %s", 			      mn.iface[i].device);			return mn.iface[i].priority;		}	}	DEBUG(DEBUG_HANDLERS, "get_device_priority: Couldn't find interface "	      "from interface list (%s, device count %d)\n", ifname, 	      mn.device_count);	return -1;}/* This function will honor the force FA address. If the force FA flag is * set only one advertisement entry has priority 1 and that's the force FA's * advertisement. */static int set_base_priority(struct node *node, void *data){	struct timeval tval = *((struct timeval *)data);	struct agentadv_data *adv = (struct agentadv_data *) node;	int prio, i;	DEBUG(DEBUG_HANDLERS, "set_base_priority: %-15s ", 	      inet_ntoa(adv->addr));	i = cmp_timeval(&tval, &adv->expire);	if (i >= 0)		DEBUG(DEBUG_HANDLERS, " EXPIRED");	if ((i < 0 || mn.force_fa_addr.s_addr != 0) && adv_ok_fa(adv)) {		if (mn.force_fa_addr.s_addr != 0)			DEBUG(DEBUG_HANDLERS, " FORCED FA");		prio = get_device_priority(adv->ifname);		if (prio > 0)			adv->priority = prio;		DEBUG(DEBUG_HANDLERS, " prio: %d", adv->priority);	} else		adv->priority = 0;	DEBUG(DEBUG_HANDLERS, "\n");	return TRUE;}static int mn_default_FA_GET_handler(void *data){	struct timeval tval;	struct hashtable *hash;	if (data == NULL)		return -1;	hash = ((struct event_FA *)data)->hash;	if (hash == NULL) {		DEBUG(DEBUG_HANDLERS, "mn_default_FA_GET_handler: hashtable "		      "pointer was NULL\n");		return 0;	}	gettimeofday(&tval, NULL);	hashtable_iterator(hash, set_base_priority, &tval);	return 0;}static int open_query_socket(void){	int sock, r;	struct sockaddr_un addr;	socklen_t addrlen;		sock = socket(AF_LOCAL, SOCK_DGRAM, 0);	if (sock < 0)		return sock;		memset(&addr, 0, sizeof(struct sockaddr_un));	addr.sun_family = AF_LOCAL;	addr.sun_path[0] = '\0';	snprintf(addr.sun_path + 1, sizeof(addr.sun_path) - 1,		 "dynamics-%i-%i", getpid(), (int) random());	addrlen = sizeof(addr.sun_family) + 1 + strlen(addr.sun_path + 1);		r = bind(sock, (struct sockaddr *) &addr, addrlen);	if (r < 0) {		DEBUG(DEBUG_INFO, "open_query_socket: bind failed: %s\n",		      strerror(errno));		return -1;	}	return sock;}static int mn_get_device_priority(int index){	struct device_info_query msg;	int s;	fd_set set;	int n;	struct timeval tv;	msg.device_index = index;	msg.priority = -1;	/* open socket */	s = open_query_socket();	if (s < 0) {		DEBUG(DEBUG_HANDLERS, "mn_get_device_priority: socket: %s",		      strerror(errno));		return s;	}	/* send query */	n = sendto(s, &msg, sizeof(struct device_info_query), 0, 		   (struct sockaddr *)&mn.dev_info_addr, 		   sizeof(mn.dev_info_addr));	if (n != sizeof(struct device_info_query)) {		DEBUG(DEBUG_HANDLERS, "\tmn_get_device_priority: sendto "		      "%d/%d bytes: %s\n", n, 		      sizeof(struct device_info_query), strerror(errno));		close(s);		return -1;	}	/* get reply */	FD_ZERO(&set);	FD_SET(s, &set);	tv.tv_usec = MICRO_SECONDS_TO_WAIT_INFO_REPLY;	tv.tv_sec = 0;	n = select(FD_SETSIZE, &set, NULL, NULL, &tv);	if (n != 1 || !FD_ISSET(s, &set)) {		DEBUG(DEBUG_HANDLERS, "mn_get_device_priority: no device "		      "info daemon present?\n");		close(s);		return -1;	}	n = recvfrom(s, (void *) &msg, sizeof(msg), 0, NULL, 0);	if (n != sizeof(msg)) {		DEBUG(DEBUG_HANDLERS, "mn_get_device_priority: couldn't "		      "receive the whole message %d/%d\n", 			n, sizeof(msg));		close(s);		return -1;	}	DEBUG(DEBUG_HANDLERS, "mn_get_device_priority: received reply. "	      "priority = %d\n", msg.priority);	close(s);	return msg.priority;}static int mn_default_INTERFACE_INIT_handler(void *data){	struct event_INTERFACE *i = (struct event_INTERFACE *)data;	int prio;		if (!i)		return -1;		DEBUG(DEBUG_HANDLERS, "mn_default_INTERFACE_INIT_handler\n");	DEBUG(DEBUG_HANDLERS, "\tOpening ICMP socket for interface "	      "%s (index=%i).\n", i->idx->name, i->idx->index);	*(i->icmp_sock_adv) = open_agent_icmp_adv_socket(i->idx->name,							 AGENTADV_FILTER_ADV);	if (*(i->icmp_sock_adv) < 0) {		DEBUG(DEBUG_HANDLERS,		      "\tOpening ICMP adv. socket failed: %s. "		      "Ignoring this interface.\n",		      strerror(errno));		return -1;	}	*(i->icmp_sock) = open_agent_icmp_socket(i->idx->name, ICMP_FILTER_MN);	if (*(i->icmp_sock) < 0) {		DEBUG(DEBUG_HANDLERS, "\tOpening ICMP socket failed: %s."		      " Ignoring this interface.\n",		      strerror(errno));		close(*(i->icmp_sock_adv));		*(i->icmp_sock_adv) = -1;		return -1;	}	DEBUG(DEBUG_HANDLERS, "sockets: sol=%i adv=%i\n",	      *i->icmp_sock, *i->icmp_sock_adv);		*(i->index) = i->idx->index;	DEBUG(DEBUG_HANDLERS, "\tindex = %d\n", i->idx->index);	memcpy(i->ifname, i->idx->name, IFNAMSIZ);	/* set priority for the device */	if (i->priority == NULL) {		DEBUG(DEBUG_HANDLERS, "\tpriority pointers is NULL!\n");		return -1;	}	*(i->priority) = DEFAULT_INTERFACE_PRIORITY;	prio = mn_get_device_priority(i->idx->index);	if (prio > 0) {		DEBUG(DEBUG_HANDLERS, "\tGot priority from interface info "		      "daemon: %d\n", prio);		*(i->priority) = prio;	}	DEBUG(DEBUG_HANDLERS, "\tinterface priority = %d\n", *(i->priority));	/* send agent solicitation */	send_agent_solicitation(*(i->icmp_sock));	if (i->iface != NULL)		gettimeofday(&i->iface->last_solicitation, NULL);	return 0;}static int remove_agentadv_data(struct node *node, void *data){	struct agentadv_data *adv;	int *ifindex;	adv = (struct agentadv_data *) node;	ifindex = (int*) data;	if (*ifindex == adv->ifindex) {		DEBUG(DEBUG_AGENTADV, "\tremoving agentadv item: %s (%s)\n",		      inet_ntoa(adv->addr), adv->ifname);		clean_agentadv(node, NULL);	}		return TRUE;}static int mn_default_INTERFACE_DOWN_handler(void *data){	struct event_INTERFACE *i = (struct event_INTERFACE *)data;	if(!i)		return -1;	/* close sockets */	DEBUG(DEBUG_HANDLERS,	      "Closing ICMP socket for interface %s (index=%d)\n",	      i->ifname, *(i->index));	close(*(i->icmp_sock));	*(i->icmp_sock) = -1;	if (*(i->icmp_sock_adv) > -1)		close(*(i->icmp_sock_adv));	*(i->icmp_sock_adv) = -1;	if (mn.current_adv != NULL && *(i->index) == mn.current_adv->ifindex) {		DEBUG(DEBUG_HANDLERS, "Current interface down - resetting "		      "connections\n");		mn.tunnel_addr.s_addr = 0;		real_tunnel_up = 0;	}	/* clear saved agent advertisement entries that came from 	   this interface */	DEBUG(DEBUG_AGENTADV, "Clearing agentadv cache for interface: %s "	      "(index=%i)\n", i->ifname, *(i->index));	hashtable_iterator(mn.agentadv, remove_agentadv_data, i->index);	return 0;}/* Initialize all handler lists. Called once, when first handler is added. */static void init_handler_lists(void){	DEBUG(DEBUG_HANDLERS, "init_handler_lists: begin\n");	list_init(&fa_adv_rec_handlers);     /* FA_ADV_EXPIRE  */	list_init(&fa_adv_exp_handlers);     /* FA_ADV_RECEIVE */	list_init(&fa_get_handlers);         /* FA_GET         */	list_init(&interface_init_handlers); /* INTERFACE_INIT */	list_init(&interface_down_handlers); /* INTERFACE_DOWN */	DEBUG(DEBUG_HANDLERS, "init_handler_lists: end\n");}/* Register handler to the <event_type> list */int handler_register(int event_type, int (*func)(void *data)){	static int inited = 0;	struct handler *new;	/* Init all lists for now */	if (!inited) {		init_handler_lists();		inited = 1;	}	new = calloc(1, sizeof(struct handler));	if (new == NULL) {		DEBUG(DEBUG_HANDLERS, "handler_register: calloc: %s",		      strerror(errno));		return 1;	}	list_init_node(&new->listnode);	new->func = func;	switch (event_type) {	case FA_ADV_RECEIVE:		list_add_tail(&fa_adv_rec_handlers, &new->listnode);		break;	case FA_ADV_EXPIRE:		list_add_tail(&fa_adv_exp_handlers, &new->listnode);		break;	case FA_GET:		list_add_tail(&fa_get_handlers, &new->listnode);		break;	case INTERFACE_INIT:		list_add_tail(&interface_init_handlers, &new->listnode);		break;	case INTERFACE_DOWN:		list_add_tail(&interface_down_handlers, &new->listnode);		break;	default:		DEBUG(DEBUG_HANDLERS, "handler_register: Unknown event "		      "type (%d)\n", event_type);		return 2;	}	DEBUG(DEBUG_HANDLERS, "handler_register: \"%s\" Event handler "	      "registered\n", event_type_str(event_type));	return 0;}/* Unregister handler from the <event_type> list * return: *  0 success *  -1 list is empty or no such handler *  -2 no such event type */int handler_unregister(int event_type, int (*func)(void *data)){	struct list *handlers;	struct node *iterator;	struct handler *p;	switch (event_type) {	case FA_ADV_RECEIVE:		handlers = &fa_adv_rec_handlers;		break;	case FA_ADV_EXPIRE:		handlers = &fa_adv_exp_handlers;		break;	case FA_GET:		handlers = &fa_get_handlers;		break;	case INTERFACE_INIT:		handlers = &interface_init_handlers;		break;	case INTERFACE_DOWN:		handlers = &interface_down_handlers;		break;	default:		DEBUG(DEBUG_HANDLERS, "handler_unregister: Unknown event type "		      "(%d)\n", event_type);		return -2;	}	iterator = list_get_first(handlers);	while (iterator != NULL) {		p = (struct handler *) iterator;		if (p->func == func) {			list_remove(iterator);			DEBUG(DEBUG_HANDLERS, "handler_unregister: "			      "\"%s\" Event handler unregistered\n",			      event_type_str(event_type));			free(p);			return 0;		}		iterator = list_get_next(iterator);	}	/* List is empty or no such handler found */	return -1;}/* Remove all hooked handlers for this <event_type> */int handler_unregister_all(int event_type){	struct node *iterator;	struct list *handlers;	struct handler *p;	int i = 0, r;	switch (event_type) {	case FA_ADV_RECEIVE:		handlers = &fa_adv_rec_handlers;		break;	case FA_ADV_EXPIRE:		handlers = &fa_adv_exp_handlers;		break;	case FA_GET:		handlers = &fa_get_handlers;		break;	case INTERFACE_INIT:		handlers = &interface_init_handlers;		break;	case INTERFACE_DOWN:		handlers = &interface_down_handlers;		break;	default:		DEBUG(DEBUG_HANDLERS, "handler_unregister_all: Unknown event "		      "type (%d)\n", event_type);		return -2;	}	iterator = list_get_first(handlers);	while (iterator != NULL) {		p = (struct handler *) iterator;		iterator = list_get_next(iterator);		r = handler_unregister(event_type, p->func);		if (!r)			i++;	}	return i;}/* Call all hooked handlers for this <event_type> */int handler_call_all(int event_type, void *data){	struct list *handlers;	struct node *iterator;	struct handler *p;	int num = 0;	int ret = 0;	switch (event_type) {	case FA_ADV_RECEIVE:		handlers = &fa_adv_rec_handlers;		break;	case FA_ADV_EXPIRE:		handlers = &fa_adv_exp_handlers;		break;	case FA_GET:		handlers = &fa_get_handlers;		break;	case INTERFACE_INIT:		handlers = &interface_init_handlers;		break;	case INTERFACE_DOWN:		handlers = &interface_down_handlers;		break;	default:		DEBUG(DEBUG_HANDLERS, "handler_call_all: Unknown event "		      "type (%d)", event_type);		return 2;	}	iterator = list_get_first(handlers);	while (iterator != NULL) {		p = (struct handler *) iterator;		if (p->func != NULL) {			ret = (*p->func)(data);			num++;			if (ret == -1) {				DEBUG(DEBUG_HANDLERS, "handler_call_all: "				      "handler returned -1. %d handlers "				      "called\n", num);				return -1;			}		}		iterator = list_get_next(iterator);	}	DEBUG(DEBUG_HANDLERS, "handler_call_all: %d \"%s\" Event "	      "handlers called\n", num, event_type_str(event_type));	return 0;}int mn_handlers_init(void){	/* Register the MN default handler for FA selection (for now	 * must be the first one in the handler list) */	DEBUG(DEBUG_HANDLERS, "Register MN default FA_GET handler\n");	handler_register(FA_GET, mn_default_FA_GET_handler);		/* Register the MN default handler for interface initialization */	DEBUG(DEBUG_HANDLERS, "Register MN default INTERFACE_INIT handler\n");	handler_register(INTERFACE_INIT, mn_default_INTERFACE_INIT_handler);		/* Register the MN default handler for interface down event */	DEBUG(DEBUG_HANDLERS, "Register MN default INTERFACE_DOWN handler\n");	handler_register(INTERFACE_DOWN, mn_default_INTERFACE_DOWN_handler);		return 0;}

⌨️ 快捷键说明

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