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

📄 sha.c

📁 mobile ip 在linux下的一种实现
💻 C
字号:
/* $Id: sha.c,v 1.6 2001/09/08 14:29:40 jm Exp $ * Surrogate Home Agent * * Dynamic hierarchial IP tunnel * Copyright (C) 2000-2001, Jouni Malinen * * 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 <stdlib.h>#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/socket.h>#include <sys/un.h>#include <sys/time.h>#include <string.h>#include <arpa/inet.h>#include <errno.h>#include <unistd.h>#include <syslog.h>#include <signal.h>#include <time.h>#include <assert.h>#include <getopt.h>#include "sha.h"#include "sha_config.h"#include "sha_utils.h"#include "tunnel.h"#include "list.h"#include "hashtable.h"#include "debug.h"#include "fixed_fd_zero.h"#include "dyn_ip.h"#include "util.h"#include "agent_utils.h"/* sockets */int sha_sock = -1;struct hashtable *tunnels_hash;struct bindingtable *bindings_hash;struct sha_config *config;int bindingcount = 0; /* number of confirmed bindings */static char *program_name; /* the name this program was run with */static void init_sockets(void);static void init_config_data(void);/* util.c - common command line arguments */extern int opt_foreground;extern char *opt_config;static voidclose_sockets(void){	close(sha_sock);	sha_sock = -1;}/* Free all reserved memory. Destroy hashes. * Unlink the unix domain socket filenames. */static voidclean_up(int sig){	/* destroy all hashes and finish nicely */	DEBUG(DEBUG_FLAG, "clean_up(%d)\n", sig);	syslog(LOG_INFO,	       "Surrogate Home Agent daemon cleaning up (signal %d)", sig);	close_sockets();	unlink(SHA_PID_FILE);	/* Free hashtables */	if (bindings_hash != NULL) {		DEBUG(DEBUG_FLAG, "Removing bindings..\n");		binding_iterator(bindings_hash, eliminate_binding_entry_force,				   &bindingcount);		binding_destroy(bindings_hash);	}	if (tunnels_hash != NULL) {		DEBUG(DEBUG_FLAG, "Removing tunnels..\n");		tunnel_destroy_hash(tunnels_hash);	}	cleanup_sha_config(config);	if (config != NULL)		free(config);	closelog();	exit(sig);}static voidreload_config(int sig){	LOG2(LOG_INFO, "Reloading configuration\n");	/* remove possible entries from the solrep list; this needs to be done	 * because the iface pointers change during configuration reloading */	cleanup_sha_config(config);        if (load_sha(config, program_name,		     opt_config == NULL ? SHA_GLOBAL_CONF_FILE : opt_config) ==	    FALSE) {		LOG2(LOG_ALERT, "Reloading configuration failed\n");		clean_up(-1);        }	close_sockets();	closelog();	init_sockets();	init_config_data();}/* search for spi/addr/priv_HA_ID match from the SHA SPI list * if spi=0, accept any spi * if addr=0.0.0.0, accept any addr * Returns: pointer to the SPI entry or NULL on failure */struct sha_spi_entry *get_sha_spi(int spi, struct in_addr addr, __u32 id){	struct sha_spi_entry *s;	struct node *node;	for (node = list_get_first(&config->sha_spi_list); node != NULL;	     node = list_get_next(node)) {		s = (struct sha_spi_entry *) node;		if ((spi == 0 || s->spi == spi) &&		    (addr.s_addr == 0 || s->addr.s_addr == addr.s_addr) &&		    id == s->priv_ha) {			return s;		}	}	return NULL;}/* Received registration message. Process it.   returns:     0 if successful     1 on error*/static inthandle_reg_msg(){	char *msg;	int res, n, cli_len;	struct sockaddr_in cli_addr;	struct msg_extensions ext;	msg = malloc(MAXMSG);	if (msg == NULL) {		LOG2(LOG_WARNING, "Not enough memory for msg\n");		return 1;	}	memset(&cli_addr, 0, sizeof(cli_addr));	cli_len = sizeof(cli_addr);	n = recvfrom(sha_sock, msg, MAXMSG, 0, (struct sockaddr *) &cli_addr,		     &cli_len);	if (n < 0) {		DEBUG(DEBUG_FLAG, "handle_reg_msg - recvfrom: (errno=%i) %s\n",		      errno, strerror(errno));		free(msg);		return 1;	}	DEBUG(DEBUG_FLAG, "Received %d bytes from %s:%d\n", n,	      inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));	res = parse_msg(msg, n, &ext);	if (res != 0) {		DEBUG(DEBUG_FLAG, "parse_msg returned %i\n", res);		free(msg);		return 0;	}        if (ext.req) {		handle_request(msg, n, &ext, &cli_addr);	} else if (ext.rep) {		handle_reply(msg, n, &ext, &cli_addr);	} else {		DEBUG(DEBUG_FLAG, "Unknown registration message type\n");	}	free(msg);	return 0;}/* Open sockets and initialize them. */static voidinit_sockets(void){	struct sockaddr_in addr;	sha_sock = socket(AF_INET, SOCK_DGRAM, 0);	if (sha_sock < 0) {		LOG2(LOG_ALERT, "init_sockets - socket: %s\n",		     strerror(errno));		clean_up(-1);	}	memset(&addr, 0, sizeof(addr));	addr.sin_family = AF_INET;	addr.sin_addr.s_addr = INADDR_ANY;	addr.sin_port = htons(config->udp_port);	if (bind(sha_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {		LOG2(LOG_ALERT, "init_sockets - bind: %s\n", strerror(errno));		clean_up(-1);	}	if (config->socket_priority > -1 &&	    setsockopt(sha_sock, SOL_SOCKET, SO_PRIORITY,		       (char *)&config->socket_priority,		       sizeof(config->socket_priority)) < 0) {		LOG2(LOG_ERR, "inet_sockets - setsockopt SO_PRIORITY: %s\n",		     strerror(errno));		/* continue without SO_PRIORITY */	}	DEBUG(DEBUG_FLAG, "Listening UDP on port %i\n",	      ntohs(addr.sin_port));}/* initializations that are run on all config reads */static voidinit_config_data(void){	/* Configure logging */	openlog("surrogate home agent", LOG_PID | LOG_CONS,		config->syslog_facility);}/* initializations that are run only once (not on config reloads) */static voidinit_data(void){	allow_ipv4_forwarding();	/* Initialize hashes */	tunnels_hash = tunnel_init(config->tunnel_device,				   config->routing_table_start,				   config->routing_table_end);	if (tunnels_hash == NULL) {		LOG2(LOG_ALERT,		     "init_data: Tunnels hash not initialized!\n");		clean_up(1);	}	bindings_hash = binding_init(config->max_bindings,				     config->max_lifetime);	if (bindings_hash == NULL) {		LOG2(LOG_ALERT, "init_data: Could not initialize"		     " bindings_hash\n");		clean_up(1);	}	DEBUG(DEBUG_FLAG, "\tinit_data: Hashes initialized\n");	/* Set up signal actions */	signal(SIGHUP, reload_config);	signal(SIGTERM, clean_up);    /* clean death */	signal(SIGINT, clean_up);     /* clean death */}/* Schedule next wake up time */static intset_expr_timer(struct timeval *tv){	int expire_time;	struct timeval now;	gettimeofday(&now, NULL);	tv->tv_sec = -1;	tv->tv_usec = 0;	if ((expire_time = binding_nextexpiretime(bindings_hash)) >= 0) {		DEBUG(DEBUG_FLAG2, "set_expr_timer: binding next expire %d\n",		      expire_time);		tv->tv_sec = expire_time;		tv->tv_usec = 0;	}	if (tv->tv_sec == -1 && tunnel_delayed_exists(tunnels_hash))		tv->tv_sec = TUNNEL_DELAYED_CHECK_INTERVAL;	return 0;}static voidmain_loop(void){	fd_set set;	struct timeval tv, now;	int oldmask;	for (;;) {		FD_ZERO(&set);		FD_SET(sha_sock, &set);		/* Wake up when the next scheduled task timer expires or there		 * is something in the sockets. */		set_expr_timer(&tv);		DEBUG(DEBUG_FLAG2, "SHA main: timer for select %ld.%ld\n",		      tv.tv_sec, tv.tv_usec);		if (select(FD_SETSIZE, &set, NULL, NULL,			   tv.tv_sec == -1 ? NULL : &tv) < 0) {			/* don't exit on e.g. SIGHUP */			if (errno != EINTR) {				LOG2(LOG_ERR, "select error: %s\n",				     strerror(errno));				clean_up(1);			}			continue;		}		/* get timestamp */		gettimeofday(&now, NULL);		/* we don't want to reread the configuration file		 * while we are handling requests; hold the signal		 * until we are ready */		oldmask = sigblock(sigmask(SIGHUP));		/* Check if any of the bindings have expired.		 * Due to the binding module implementation this must be done		 * just before using binding_add in order to get the binding		 * module to current time. */		check_bindings(bindings_hash, tunnels_hash,			       &bindingcount, (time_t)now.tv_sec);		if (FD_ISSET(sha_sock, &set)) {			DEBUG(DEBUG_FLAG, "Got UDP message\n");			handle_reg_msg();		}		tunnel_check_delayed(tunnels_hash, 0);		sigsetmask(oldmask);	}}static intsha_parse_command_line(int argc, char *argv[]){	int c, oindex = 0;	static struct option long_options[] = {		/* common arguments */		{"help", no_argument, NULL, 'h'},		{"version", no_argument, NULL, 'v'},		{"debug", no_argument, NULL, 0},		{"fg", no_argument, NULL, 0},		{"config", required_argument, NULL, 'c'},		/* SHA specific arguments */		/* end of arguments */		{0, 0, 0, 0}	};	DEBUG(DEBUG_FLAG, "SHA command line parsing\n");	while ((c = getopt_long(argc, argv, "+hv", long_options, &oindex)) !=	       EOF) {				switch (c) {		case 'h':			/* show SHA specific parameters */			/* N/A */			exit(1);			break;					case '?':			printf("Command line parsing failed - aborting\n");			exit(1);		case 'v':		case 'c':		case 0:			break;					default:			printf("?? getopt returned character code 0%o ??\n",			       c);			exit(1);		}	}	return 0;}intmain(int argc, char *argv[]){	program_name = parse_long_options(argc, argv, "foreign agent",					  PACKAGE, VERSION, dynamics_usage);	sha_parse_command_line(argc, argv);        config = malloc(sizeof(struct sha_config));        if (config == NULL) {                fprintf(stderr, "Not enough memory for struct sha_config\n");                exit(1);        }        if (load_sha(config, program_name,		    opt_config == NULL ? SHA_GLOBAL_CONF_FILE : opt_config) ==	    FALSE) {                fprintf(stderr, "Configuration file reading failed.\n");                exit(1);        }	check_kernel_support(CHECK_KERNEL_ADV_ROUTING | CHECK_KERNEL_IPIP |			     CHECK_KERNEL_NETLINK);#ifndef NO_SUID_CHECK_FOR_SHA	if (getuid()) {		fprintf(stderr, "This program must be run by root.\n");		exit(1);	}#endif 	/* These routines don't return any values. If something is           wrong clean_up() is used */	init_sockets();	init_data();	init_config_data();	if (!opt_foreground && dynamics_fork_daemon() == -1)		clean_up(1);	dynamics_write_pid_file(SHA_PID_FILE);	syslog(LOG_INFO, "%s surrogate home agent daemon version %s started\n",	       PACKAGE, VERSION);	main_loop();        return 0;}

⌨️ 快捷键说明

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