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

📄 ha.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 5 页
字号:
 */static intnew_session_key(struct bindingentry *binding, struct spi_entry *mn_spi){#ifndef NODEBUGMODE	int i;#endif	/* remove the (possibly) cached previous key reply using FA's public	 * key, because the session key changes */	if (binding->last_sent_fa_pubkeyrep)		free(binding->last_sent_fa_pubkeyrep);	binding->last_sent_fa_pubkeyrep = NULL;	/* generate a new session key */	binding->keylen =		generate_session_key(mn_spi->auth_alg, mn_spi->shared_secret,				     mn_spi->shared_secret_len, binding->key);	if (binding->keylen == -1) {		LOG2(LOG_ERR, "Could not generate session key\n");		return -1;	}#ifndef NODEBUGMODE	DEBUG(DEBUG_FLAG, "Session key: ");	for (i = 0; i < binding->keylen; i++)		DEBUG(DEBUG_FLAG, "%02x", binding->key[i]);	DEBUG(DEBUG_FLAG, "\n");#endif	return 0;}struct gratuitous_arp_data {	struct gratuitous_arp_data *next;	struct timeval tv;	struct in_addr addr;	char interface[IFNAMSIZ + 1];};static struct gratuitous_arp_data *gratuitous_arp_queue = NULL;/** * send_gratuitous_arp: * @addr: IP address for the ARP packet * @interface: interface to which the packet is sent * * Send a gratuitous ARP for an MN. */static voidsend_gratuitous_arp(struct in_addr addr, char *interface){	struct gratuitous_arp_data *arp2, *arp3, *arp;	/* HW broadcast is not usually guaranteed, so the gratuitous ARP is	 * transmitted a small number of times (see RFC2002, sec. 4.6) */	/* send first packet immediately */	proxyarp_gratuitous(addr, interface);	arp2 = (struct gratuitous_arp_data *)		malloc(sizeof(struct gratuitous_arp_data));	arp3 = (struct gratuitous_arp_data *)		malloc(sizeof(struct gratuitous_arp_data));	if (arp2 == NULL || arp3 == NULL) {		DEBUG(DEBUG_FLAG, "send_gratuitous_arp: malloc() failed\n");		if (arp2 != NULL)			free(arp2);		if (arp3 != NULL)			free(arp3);		return;	}	/* send second packet after 100 ms delay */	memset(arp2, 0, sizeof(struct gratuitous_arp_data));	gettimeofday(&arp2->tv, NULL);	add_usecs(&arp2->tv, 100000);	arp2->addr.s_addr = addr.s_addr;	dynamics_strlcpy(arp2->interface, interface, sizeof(arp2->interface));	/* send third packet after 200 ms delay */	memcpy(arp3, arp2, sizeof(struct gratuitous_arp_data));	add_usecs(&arp3->tv, 100000);	DEBUG(DEBUG_FLAG, "send_gratuitous_arp - adding packet to queue at "	      "%li.%06li and %li.%06li\n", arp2->tv.tv_sec, arp2->tv.tv_usec,	      arp3->tv.tv_sec, arp3->tv.tv_usec);	if (gratuitous_arp_queue == NULL) {		/* empty queue - make new queue of the new items */		gratuitous_arp_queue = arp2;		arp2->next = arp3;		arp3->next = NULL;		return;	}	if (cmp_timeval(&gratuitous_arp_queue->tv, &arp2->tv) > 0) {		/* arp2 goes before the old head of the queue */		arp2->next = gratuitous_arp_queue;		gratuitous_arp_queue = arp2;	} else {		/* insert arp2 into queue */		arp = gratuitous_arp_queue;		while (arp->next != NULL &&		       cmp_timeval(&arp->next->tv, &arp2->tv) <= 0)			arp = arp->next;		arp2->next = arp->next;		arp->next = arp2;	}	/* insert arp3 into queue */	arp = arp2;	while (arp->next != NULL &&	       cmp_timeval(&arp->next->tv, &arp3->tv) <= 0)		arp = arp->next;	arp3->next = arp->next;	arp->next = arp3;}/** * check_queued_gratuitous_arp: * * Send any pending gratuitous ARP packets from the queue. */static voidcheck_queued_gratuitous_arp(void){	struct timeval now;	struct gratuitous_arp_data *arp;	if (gratuitous_arp_queue == NULL)		return;	gettimeofday(&now, NULL);	while (gratuitous_arp_queue != NULL &&	       cmp_timeval(&gratuitous_arp_queue->tv, &now) <= 0) {		arp = gratuitous_arp_queue;		DEBUG(DEBUG_FLAG, "Sending queued gratuitous ARP "		      "(tv=%li.%06li addr=%s interface=%s)\n",		      arp->tv.tv_sec, arp->tv.tv_usec, inet_ntoa(arp->addr),		      arp->interface);		proxyarp_gratuitous(arp->addr, arp->interface);		gratuitous_arp_queue = arp->next;		free(arp);	}	if (gratuitous_arp_queue == NULL)		DEBUG(DEBUG_FLAG, "Gratuitous ARP queue empty.\n");	else		DEBUG(DEBUG_FLAG, "Entries remaining in gratuitous ARP queue "		      "(next at %li.%06li)\n",		      gratuitous_arp_queue->tv.tv_sec,		      gratuitous_arp_queue->tv.tv_usec);}/** * create_binding: * @ext: parsed registration request extensions * @mn_spi: pointer to SPI entry for the MN * @create_tunnels: 1=create tunnels, 0=create only binding data * * Creates a binding matching the given request. * * Returns: *  On success, a memory for the binding entry is allocated and a *  pointer to it returned. On failure, %NULL is returned. */static struct bindingentry *create_binding(struct msg_extensions *ext, struct spi_entry *mn_spi,	       int create_tunnels){	struct bindingentry *binding;	struct ha_tunnel_data *t_data;	char mn_addrstr[17];	char co_addrstr[17];	int ok = TRUE;	DEBUG(DEBUG_FLAG, "Creating a new binding for MN\n");	ASSERT(ext != NULL && ext->req != NULL);	ASSERT(mn_spi != NULL);	if (bindingcount >= config.max_bindings) {		LOG2(LOG_WARNING, "max bindings reached\n");		return NULL;	}	/* create the binding */	binding = malloc(sizeof(struct bindingentry));	if (binding == NULL) {		LOG2(LOG_ERR, "malloc[binding] - %s\n", strerror(errno));		return NULL;	}	memset(binding, 0, sizeof(struct bindingentry));	binding->data = malloc(sizeof(struct ha_tunnel_data));	if (binding->data == NULL) {		LOG2(LOG_ERR, "malloc[ha_tunnel_data] - %s\n",		     strerror(errno));		free(binding);		return NULL;	}	memset(binding->data, 0, sizeof(struct ha_tunnel_data));	t_data = (struct ha_tunnel_data *) binding->data;	binding->spi = mn_spi->spi;	if ((ext->fa_keyreq || ext->fa_pubkey || ext->mn_keyreq) &&	    new_session_key(binding, mn_spi) < 0)		ok = FALSE;	binding->mn_addr.s_addr = ext->req->home_addr.s_addr;	binding->ha_addr.s_addr = ext->req->ha_addr.s_addr;	binding->priv_ha = config.priv_ha;	binding->lower_addr.s_addr = config.sha_addr.s_addr != 0 ?		config.sha_addr.s_addr : ext->req->co_addr.s_addr;	dynamics_strlcpy(mn_addrstr, inet_ntoa(ext->req->home_addr),			 sizeof(mn_addrstr));	dynamics_strlcpy(co_addrstr, inet_ntoa(ext->req->co_addr),			 sizeof(co_addrstr));	memcpy(&binding->id, ext->req->id, REG_REQ_ID_LEN);	binding->create_time = time(NULL);	if (ok && create_tunnels &&	    tunnel_add(tunnels, binding->lower_addr, binding->tun_dev,		       ext->req->ha_addr, 1, TUNNEL_IPIP, 0) == NULL) {		LOG2(LOG_ERR, "Could not add tunnel to FA %s (COA=%s) for "		     "MN %s\n", inet_ntoa(binding->lower_addr), co_addrstr,		     mn_addrstr);		ok = FALSE;	}	if (ok && create_tunnels &&	    dyn_ip_route_get(binding->mn_addr, t_data->arp_if, IFNAMSIZ)	    != 0) {		LOG2(LOG_ERR, "Could not get arp interface for MN %s\n",		     mn_addrstr);		ok = FALSE;	}	if (ok && create_tunnels &&	    dyn_ip_route_replace(binding->mn_addr, binding->tun_dev) != 0) {		LOG2(LOG_ERR, "Could not add route to MN %s\n",		     mn_addrstr);		ok = FALSE;	}	if (!ok) {		free(binding->data);		free(binding);		return NULL;	}	if (create_tunnels) {		DEBUG(DEBUG_FLAG, "tunnel_add => tun_dev=[%s]\n",		      binding->tun_dev);		DEBUG(DEBUG_FLAG, "dyn_ip_route_get: %s => %s\n",		      inet_ntoa(binding->mn_addr), t_data->arp_if);		proxyarp_add_item(binding->mn_addr, t_data->arp_if);		send_gratuitous_arp(binding->mn_addr, t_data->arp_if);	}	bindingcount++;	return binding;}/** * remove_tunnel: * @binding: bindingentry whose tunnel is to be removed * * Removes the route, tunnel, and proxy ARP entry for the @binding that were * created in create_binding() and possibly updated with switch_tunnel(). */static voidremove_tunnel(struct bindingentry *binding){	struct ha_tunnel_data *t_data;	ASSERT(binding != NULL && binding->data != NULL);	t_data = (struct ha_tunnel_data *) binding->data;	if (dyn_ip_route_del(binding->mn_addr, binding->tun_dev) < 0)		LOG2(LOG_WARNING, "remove_tunnel: dyn_ip_route_del failed\n");	if (tunnel_delete(tunnels, binding->lower_addr, 0, TUNNEL_IPIP, 0) < 0)		LOG2(LOG_WARNING, "remove_tunnel: tunnel_delete failed\n");	if (proxyarp_del_item(binding->mn_addr, t_data->arp_if) < 0)		LOG2(LOG_WARNING, "remove_tunnel: proxyarp_del_item failed\n");}/** * switch_tunnel: * @binding: the bindingentry to be updated * @ext: parsed registration request extensions * @mn_spi: pointer to SPI entry for the MN * * Switch the tunnel, i.e., do optimized remove_tunnel() and create_binding(). * * Returns: *  0 on success or -1 on failure */static intswitch_tunnel(struct bindingentry *binding, struct msg_extensions *ext,	      struct spi_entry *mn_spi){	char mn_addrstr[17];	char co_addrstr[17];	char old_lower_tunl[IFNAMSIZ];	ASSERT(binding != NULL && ext != NULL && ext->req != NULL);	dynamics_strlcpy(mn_addrstr, inet_ntoa(ext->req->home_addr),			 sizeof(mn_addrstr));	dynamics_strlcpy(co_addrstr, inet_ntoa(ext->req->co_addr),			 sizeof(co_addrstr));	memcpy(old_lower_tunl, binding->tun_dev, IFNAMSIZ);	/* remove old tunnel (delayed deletion) */	if (tunnel_delete(tunnels, binding->lower_addr, 0, TUNNEL_IPIP, 0) < 0)	{		LOG2(LOG_ERR,		     "Could not delete old tunnel to FA %s for MN %s\n",		     co_addrstr, mn_addrstr);	}	binding->lower_addr = config.sha_addr.s_addr != 0 ?		config.sha_addr : ext->req->co_addr;	/* add the new tunnel */	if (tunnel_add(tunnels, binding->lower_addr, binding->tun_dev,		       ext->req->ha_addr, 1, TUNNEL_IPIP, 0) == NULL) {		LOG2(LOG_ERR, "Could not add tunnel to FA %s (COA=%s) for "		     "MN %s\n", inet_ntoa(binding->lower_addr), co_addrstr,		     mn_addrstr);		destroy_binding(binding);		return -1;	}	DEBUG(DEBUG_FLAG, "tunnel_add => tun_dev=[%s]\n", binding->tun_dev);	if (dyn_ip_route_replace(binding->mn_addr, binding->tun_dev) != 0) {		LOG2(LOG_WARNING,		     "Route replace failed (COA=%s, MN=%s, dev=%s)\n",		     co_addrstr, mn_addrstr, binding->tun_dev)	}	if ((ext->fa_keyreq || ext->fa_pubkey || ext->mn_keyreq) &&	    new_session_key(binding, mn_spi) < 0) {		destroy_binding(binding);		return -1;	}	return 0;}/** * destroy_binding: * @binding: the bindingentry to be freed * * Frees the associated memory for a binding. * remove_tunnel() should be called before this function. */static voiddestroy_binding(struct bindingentry *binding){	if (binding->data) /* ccmalloc needs this */		free(binding->data);	if (binding->fa_pubkey)		free(binding->fa_pubkey);	if (binding->last_sent_fa_pubkeyrep)		free(binding->last_sent_fa_pubkeyrep);	free(binding);	bindingcount--;}/** * check_bindings: * * Checks if any bindings have expired since the last call to the function. * Any expired bindings will be removed. */static voidcheck_bindings(void){	struct bindingentry *binding;	time_t diff;	static int first_time = 1;	static time_t advance_expire_time;	time_t time2;        if (first_time) {                advance_expire_time = time(NULL);                first_time = 0;        }	time2 = time(NULL);	diff = time2 - advance_expire_time;	advance_expire_time = time2;	if (diff < 0) {		DEBUG(DEBUG_FLAG,		      "check_bindings: diff(%li) < 0 - system time changed?\n",		      diff);		diff = 0;	}	binding = binding_getexpired(bindings, diff);        while (binding != NULL) {		DEBUG(DEBUG_FLAG, "Binding to MN %s expired\n",		      inet_ntoa(binding->mn_addr));		remove_tunnel(binding);		destroy_binding(binding);                binding = binding_getexpired(bindings, 0);        }}/** * get_fa_spi: * @spi: security parameter index * @addr: IP address of the FA * * Fetches SPI structure for an FA using key (@spi,@addr). If @spi is zero, * any item with a matching IP address is returned regardless of the configured * SPI value. * * Returns: *  pointer to the SPI structure or %NULL if requested item not found */static struct fa_spi_entry *get_fa_spi(int spi, struct in_addr addr){	struct fa_spi_entry *s;	struct node *node;	for (node = list_get_first(&config.fa_spi_list); node != NULL;	     node = list_get_next(node)) {		s = (struct fa_spi_entry *) node;		if ((spi == 0 || s->spi == spi) &&		    s->addr.s_addr == addr.s_addr) {			return s;		}	}

⌨️ 快捷键说明

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