📄 mn_handler.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 + -