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

📄 fa.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 3 页
字号:
		break;	}	api_send(sock, &addr, addrlen, &send_msg);}static voidhandle_errqueue(int s){	char msg[256];	int n;	struct sockaddr_in cli_addr;	struct msghdr mh;	char cdata[256];	struct iovec iov;	struct cmsghdr *cmsg;	struct dest_unreachable_data unreach;	memset(&mh, 0, sizeof(mh));	iov.iov_base = msg;	iov.iov_len = sizeof(msg);	mh.msg_name = &cli_addr;	mh.msg_namelen = sizeof(cli_addr);	mh.msg_iov = &iov;	mh.msg_iovlen = 1;	mh.msg_control = &cdata;	for (;;) {		struct dynamics_sock_extended_err *err = NULL;		memset(&cli_addr, 0, sizeof(cli_addr));		mh.msg_controllen = sizeof(cdata);		n = recvmsg(s, &mh, MSG_ERRQUEUE);		if (n < 0)			break;		memset(&unreach, 0, sizeof(unreach));		unreach.port = -1;		if (cli_addr.sin_family == AF_INET) {			DEBUG(DEBUG_FLAG, "Learned unreachable address from "			      "msg_name: %s:%i\n",			      inet_ntoa(cli_addr.sin_addr),			      ntohs(cli_addr.sin_port));			unreach.addr.s_addr = cli_addr.sin_addr.s_addr;			unreach.port = cli_addr.sin_port;		}		for (cmsg = CMSG_FIRSTHDR(&mh); cmsg != NULL;		     cmsg = DYNAMICS_CMSG_NXTHDR(&mh, cmsg)) {			if (cmsg->cmsg_level == SOL_IP &&			    cmsg->cmsg_type == IP_RECVERR) {				err = (struct dynamics_sock_extended_err *)					CMSG_DATA(cmsg);			}		}		if (err == NULL) {			DEBUG(DEBUG_FLAG, "Could not get IP_RECVERR data\n");			break;		}		DEBUG(DEBUG_FLAG, "\tIP_RECVERR: errno=%i origin=%i "		      "type=%i code=%i pad=%i info=%i data=%i\n",		      err->ee_errno, err->ee_origin, err->ee_type,		      err->ee_code, err->ee_pad, err->ee_info,		      err->ee_data);		unreach.code = err->ee_code;		if (unreach.port == -1) {			/* Older kernels (2.2.x?) seem to give bogus port			 * entries or do not return address in msg_name, so try			 * to get the IP address from offender data */			struct sockaddr_in *offender;			offender = (struct sockaddr_in *) SO_EE_OFFENDER(err);			if (offender == NULL ||			    offender->sin_family != AF_INET) {				DEBUG(DEBUG_FLAG,				      "Could not get offender data\n");				break;			}			DEBUG(DEBUG_FLAG, "\toffender %s:%i (ignoring bogus "			      "port)\n",			      inet_ntoa(offender->sin_addr),			      ntohs(offender->sin_port));			unreach.addr.s_addr = offender->sin_addr.s_addr;			/* offender->sin_port seem to be bogus in 2.2.17 and			 * zero in 2.4.4, so better ignore it; port number -1			 * is handled as a special wildcard later */		}		handle_dest_unreach(&unreach);	}}/* Rotating L2 data queue of last registration messages */#define L2_QUEUE_LEN 10/* How many bytes to save from each packet; this is the size of the * registration request header. If the message is registration reply, only * first 20 bytes are checked when searching for L2 data. */#define L2_SAVE_UDP_LEN 24struct pending_registration_l2_info {	struct packet_from_info info;	unsigned char udp_start[L2_SAVE_UDP_LEN];};static struct pending_registration_l2_info l2_info[L2_QUEUE_LEN];static int l2_next_pos = 0;/* Received registration message. Process it.   returns:     0 if successful     1 on error (not enough memory)*/static inthandle_reg_msg(struct interface_entry *iface){	char msg[MAXMSG];	int res, n, check_len;	struct sockaddr_in from;	socklen_t fromlen;	struct packet_from_info *info = NULL, tmpinfo;	struct msg_extensions ext;	memset(&from, 0, sizeof(from));	fromlen = sizeof(from);	n = recvfrom(iface->udp_sock, msg, sizeof(msg), 0,		     (struct sockaddr *) &from, &fromlen);	if (n < 0) {		DEBUG(DEBUG_FLAG, "handle_reg_msg - recvmsg: (errno=%i) "		      "%s\n", errno, strerror(errno));		handle_errqueue(iface->udp_sock);		return 0;	}	DEBUG(DEBUG_FLAG, "Received %d bytes from %s:%d\n", n,	      inet_ntoa(from.sin_addr), ntohs(from.sin_port));	/* search for L2 data from packet socket */	if (n > 0 && msg[0] == REG_REP)		check_len = sizeof(struct reg_rep);	else		check_len = L2_SAVE_UDP_LEN;	if (n >= check_len) {		int pos = l2_next_pos;		for (;;) {			if (pos == 0)				pos = L2_QUEUE_LEN - 1;			else				pos--;			if (pos == l2_next_pos)				break;			if (memcmp(msg, &l2_info[pos].udp_start,				   check_len) == 0) {				DEBUG(DEBUG_FLAG, "\tpending L2 data found "				      "from pos %i\n", pos);				info = &l2_info[pos].info;				break;			}		}	}	if (info == NULL) {		DEBUG(DEBUG_FLAG, "\tcould not find pending L2 data - using "		      "dummy entry\n");		memset(&tmpinfo, 0, sizeof(tmpinfo));		info = &tmpinfo;		info->iface = iface;		memcpy(&info->src, &from, sizeof(info->src));	}	res = parse_msg(msg, n, &ext);	if (res != 0) {		char *reason = "N/A";		if (res == -1) {			reason = "unknown extension";			stats.discarded_unknown_ext++;		} else if (res == -2) {			reason = "malformed message";			stats.discarded_malformed_msg++;		} else if (res == -3 || res == -4 || res == -5) {			reason = "unknown vendor extension";			stats.discarded_vendor_ext++;		}		report_discarded_msg(msg, n, &info->src, reason);		DEBUG(DEBUG_FLAG, "parse_msg returned %i\n", res);		if (res == -3 || res == -4) {			DEBUG(DEBUG_FLAG, "Unknown critical vendor extension -"			      " sending failure reply\n");			send_failure_reply(REGREP_UNSUPP_VENDOR_ID_MN_FA, &ext,					   info, NULL, 0);		}		if (res != -5 || ext.rep == NULL) {			return 0;		}		/* let registration replies with unknown CVSE pass through to		 * be denied properly in handle_reply() */	}	if (ext.req && iface->type == INTERFACE_TYPE_UP) {		DEBUG(DEBUG_FLAG, "Received registration request from "		      "interface type UP - rejecting\n");		report_discarded_msg(msg, n, &info->src,				     "registration request from UP interface");		send_failure_reply(REGREP_ADMIN_PROHIBITED_FA, &ext,				   info, NULL, 0);	} else if (ext.rep && iface->type == INTERFACE_TYPE_DOWN) {		DEBUG(DEBUG_FLAG, "Received registration reply from "		      "interface type DOWN - rejecting\n");		report_discarded_msg(msg, n, &info->src, "registration reply "				     "from DOWN interface");	} else if (ext.req) {		res = handle_request(&ext, info, config);		if (res) {			stats.req_rejected++;			report_discarded_msg(msg, n, &info->src,					     "registration request rejected");		} else			stats.req_accepted++;		info_send(FA_INFO_REQUEST,			  res == 0 ? FA_INFO_OK : FA_INFO_FAILED, ext.req,			  sizeof(struct reg_req));	} else if (ext.rep) {		res = handle_reply(&ext, info);		if (res) {			stats.rep_rejected++;			report_discarded_msg(msg, n, &info->src,					     "registration reply rejected");		} else			stats.rep_accepted++;		info_send(FA_INFO_REPLY,			  res == 0 ? FA_INFO_OK : FA_INFO_FAILED, ext.rep,			  sizeof(struct reg_rep));	} else if (ext.fa_req) {		res = handle_fa_req(msg, n, &ext, &info->src, iface);	} else if (ext.fa_rep) {		res = handle_fa_rep(msg, n, &ext, &info->src, iface);	} else {		DEBUG(DEBUG_FLAG, "Unknown registration message type\n");	}	return 0;}static inthandle_reg_msg_packet(struct interface_entry *iface){	char msg[MAXMSG];	int n, i;	socklen_t fromlen;	struct packet_from_info *info;	struct iphdr *ip;	struct udphdr *udp;	int hdrlen = sizeof(struct iphdr) + sizeof(struct udphdr);	info = &l2_info[l2_next_pos].info;	memset(info, 0, sizeof(*info));	info->iface = iface;	fromlen = sizeof(info->from);	n = recvfrom(iface->udp_packet, msg, sizeof(msg), 0,		     (struct sockaddr *) &info->from, &fromlen);	if (n < 0) {		DEBUG(DEBUG_FLAG, "handle_reg_msg_packet - recvfrom: %s\n",		      strerror(errno));		return -1;	}	if (n < hdrlen + L2_SAVE_UDP_LEN) {		DEBUG(DEBUG_FLAG, "handle_reg_msg_packet - underflow\n");		return -1;	}	DEBUG(DEBUG_FLAG, "\treceived %i bytes - saving L2 data to pos %i\n",	      n, l2_next_pos);	DEBUG(DEBUG_FLAG, "\tsll_ifindex=%i sll_hatype=0x%04x sll_pkttype=%i "	      "sll_halen=%i sll_addr=",	      info->from.sll_ifindex, ntohs(info->from.sll_hatype),	      info->from.sll_pkttype, info->from.sll_halen);	for (i = 0; i < sizeof(info->from.sll_addr); i++) {		if (i > 0)			DEBUG(DEBUG_FLAG, ":");		DEBUG(DEBUG_FLAG, "%02x", info->from.sll_addr[i]);	}	DEBUG(DEBUG_FLAG, "\n");	ip = (struct iphdr *) msg;	if (ip->protocol != IPPROTO_UDP) {		DEBUG(DEBUG_FLAG, "\tskipping non-UDP packet (protocol=%i)\n",		      ip->protocol);		return -1;	}	udp = (struct udphdr *) (ip + 1);	if (ntohs(udp->dest) != 434) {		DEBUG(DEBUG_FLAG, "\tskipping UDP packet to port other than "		      "434 (%i)\n", ntohs(udp->dest));		return -1;	}	info->ttl = ip->ttl;	info->dst_addr.s_addr = ip->daddr;	info->src.sin_family = AF_INET;	info->src.sin_addr.s_addr = ip->saddr;	info->src.sin_port = udp->source;	memcpy(&l2_info[l2_next_pos].udp_start, udp + 1, L2_SAVE_UDP_LEN);	l2_next_pos++;	if (l2_next_pos >= L2_QUEUE_LEN)		l2_next_pos = 0;	return 0;}/* Open sockets and initialize them. */static voidinit_sockets(void){	struct interface_entry *iface;	int one = 1;#ifdef INCLUDE_IPAY	struct in_addr dummy;	memset(&dummy, 0, sizeof(dummy));	ipay_sock = dynamics_open_udp_socket(config, dummy, config->ipay_port,					     NULL);	if (ipay_sock < 0) {		LOG2(LOG_ALERT, "Ipay socket open failed - %s\n",		     strerror(errno));		clean_up(-1);	}#endif	/* Unix sockets for API calls */	api_rw_sock = api_open_socket(config->fa_api_admin_socket_path,				      config->fa_api_admin_socket_group,				      config->fa_api_admin_socket_owner,				      config->fa_api_admin_socket_permissions);	if (api_rw_sock < 0) {		syslog(LOG_ERR, "init - open_api_rw_socket: %m");	}	api_ro_sock = api_open_socket(config->fa_api_read_socket_path,				      config->fa_api_read_socket_group,				      config->fa_api_read_socket_owner,				      config->fa_api_read_socket_permissions);	if (api_ro_sock < 0) {		syslog(LOG_ERR, "init - open_api_ro_socket: %m");	}	/* RAW sockets for ICMP agent solicitation messages */	DEBUG(DEBUG_FLAG, "Initializing interfaces\n");	iface = (struct interface_entry *) list_get_first(&config->interfaces);	if (iface == NULL) {		LOG2(LOG_ALERT, "No interfaces defined\n");		clean_up(-1);	}	while (iface != NULL) {		DEBUG(DEBUG_FLAG, "\t%s: ", iface->dev);		iface->if_index = dyn_ip_get_ifindex(iface->dev);		if (iface->if_index < 0) {			LOG2(LOG_ALERT,			     "Could not get ifindex for interface %s\n",			     iface->dev);			clean_up(-1);		}		DEBUG(DEBUG_FLAG, "ifindex=%i ", iface->if_index);		if (iface->type == INTERFACE_TYPE_BOTH ||		    iface->type == INTERFACE_TYPE_UP)			up_interface = iface;		if (iface->force_addr.s_addr != 0) {			DEBUG(DEBUG_FLAG, "forcing address ");			iface->addr = iface->force_addr;		} else {			if (dyn_ip_get_ifaddr(iface->dev, &iface->addr) != 0) {				LOG2(LOG_ALERT, "could not get interface[%s] "				     "address\n", iface->dev);				clean_up(-1);			}		}		iface->udp_sock =			dynamics_open_udp_socket(config->socket_priority,						 iface->force_addr,						 config->udp_port,						 iface->dev);		if (iface->udp_sock < 0) {			LOG2(LOG_ALERT, "UDP socket opening failed\n");			clean_up(-1);		}		if (setsockopt(iface->udp_sock, SOL_IP, IP_RECVERR, 			       (const void *) &one, sizeof(one)) < 0) {			DEBUG(DEBUG_FLAG,			      "init_sockets - setsockopt(SOL_IP, IP_RECVERR): "			      " %s\n", strerror(errno));			/* continue without IP_RECVERR */		}		iface->udp_packet =			open_agent_icmp_adv_socket(iface->dev,						   UDP_FILTER_PORT434);		if (iface->udp_packet < 0) {			LOG2(LOG_ALERT, "could not open packet socket for "			     "UDP port 434\n");			clean_up(-1);		}		iface->icmp_sock =			open_agent_icmp_adv_socket(iface->dev,						   AGENTADV_FILTER_SOL);		if (iface->icmp_sock < 0) {			LOG2(LOG_ALERT, "could not open ICMP socket\n");			clean_up(-1);		}		DEBUG(DEBUG_FLAG, "%s => socket=%i\n", inet_ntoa(iface->addr),		      iface->icmp_sock);		iface = (struct interface_entry *) list_get_next(&iface->node);	}}/* initializations that are run on all config reads */static voidinit_config_data(void){	int i;	/* Configure logging */	openlog("foreign agent", LOG_PID | LOG_CONS, config->syslog_facility);	/* Fill in the upper_fa_addr */	upper_fa_addr.sin_family = AF_INET;	memcpy(&upper_fa_addr.sin_addr, &config->upper_fa_addr,	       sizeof(config->upper_fa_addr));	upper_fa_addr.sin_port = htons(config->upper_fa_port);	DEBUG(DEBUG_FLAG, "\tinit_data: upper_fa_addr = %s:%d\n",	      inet_ntoa(upper_fa_addr.sin_addr),	      ntohs(upper_fa_addr.sin_port));	/* Get the FA public key */	if (rsa_initialize(config->key_file) != 0) {		fprintf(stderr, "RSA initialization failed (key file: %s)\n",			config->key_file);		clean_up(1);	}	if (fa_public_key != NULL)		free(fa_public_key);	fa_public_key = (struct msg_key *)		malloc(sizeof(struct msg_key) + SPI_LEN +		       rsa_get_public_key_len() + 1);	if (fa_public_key == NULL) {		fprintf(stderr, "Not enough memory for fa_public_key\n");		clean_up(1);	}	if (rsa_get_public_key_len() + SPI_LEN > 255) {		fprintf(stderr, "fa_public_key over 255 bytes long - does "			"not fit into extension\n");		clean_up(1);	}	init_key_extension(fa_public_key, VENDOR_EXT_DYNAMICS_FA_PUBKEY,			   htonl(PUBKEY_ALG_SPI_RSA),			   rsa_get_public_key_len());  	memcpy(MSG_KEY_DATA(fa_public_key), rsa_get_public_key(),  	       GET_KEY_LEN(fa_public_key));	if (fa_nai != NULL) {		free(fa_nai);		fa_nai = NULL;	}	if (config->fa_nai[0] != '\0') {		fa_nai = (struct fa_nai_ext *)			malloc(sizeof(struct fa_nai_ext) +			       strlen(config->fa_nai));		if (fa_nai == NULL) {			DEBUG(DEBUG_FLAG, "Not enough memory for fa_nai\n");			clean_up(1);		}		fa_nai->type = VENDOR_EXT_TYPE2;		fa_nai->reserved = 0;		fa_nai->length = sizeof(struct fa_nai_ext) - 2 +			strlen(config->fa_nai);		fa_nai->vendor_id = htonl(VENDOR_ID_DYNAMICS);		fa_nai->sub_type = htons(VENDOR_EXT_DYNAMICS_FA_NAI);		memcpy(fa_nai + 1, config->fa_nai, strlen(config->fa_nai));	}	last_challenges = (struct challenge_ext **)		malloc(config->challenge_window *		       sizeof(struct challenge_ext *));	if (last_challenges == NULL) {		DEBUG(DEBUG_FLAG, "Not enough memory for last_challenges\n");		clean_up(1);	}	for (i = 0; i < config->challenge_window; i++)		last_challenges[i] = NULL;	last_challenges_pos = 0;}/* initializations that are run only once (not on config reloads) */static voidinit_data(void){	struct interface_entry *iface;	iface = (struct interface_entry *) list_get_first(&config->interfaces);	if (iface == NULL) {		LOG2(LOG_ALERT, "init_data: no interfaces defined\n");		clean_up(1);	}	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->fa_default_tunnel_lifetime);	if (bindings_hash == NULL) {		LOG2(LOG_ALERT, "init_data: Could not initialize"		     " bindings_hash\n");		clean_up(1);	}	bcounters.bindingcount = 0;	bcounters.pendingcount = 0;	if (!fa_hash_init()) {		LOG2(LOG_ALERT, "init_data: Could not initialize fa_hash\n");		clean_up(1);	}	if (mn_addr_init() < 0) {		LOG2(LOG_ALERT, "init_data: Could not initialize "		     "mn_addr_hash\n");		clean_up(1);	}	DEBUG(DEBUG_FLAG, "\tinit_data: Hashes initialized\n");	iface = (struct interface_entry *) list_get_first(&config->interfaces);	srand(time(NULL) ^ (iface ? iface->addr.s_addr : 0));	/* Reset statistic counters */	memset(&stats, 0, sizeof(stats));	dynamics_strlcpy(stats.version, VERSION, sizeof(stats.version));	/* Set up signal actions */	signal(SIGHUP, reload_config);	signal(SIGTERM, clean_up);    /* clean death */	signal(SIGINT, clean_up);     /* clean death */}/* set_expr_timer: * @tv: Set to time when next event is due. * @next_agentadv: Time when next agent advertisement is due. *

⌨️ 快捷键说明

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