Ejemplo n.º 1
0
/**
 * mipv6_halist_add - Add new home agent to the Home Agents List
 * @ifindex: interface identifier
 * @glob_addr: home agent's global address
 * @ll_addr: home agent's link-local address
 * @pref: relative preference for this home agent
 * @lifetime: lifetime for the entry
 *
 * Adds new home agent to the Home Agents List.  The list is interface
 * specific and @ifindex tells through which interface the home agent
 * was heard.  Returns zero on success and negative on failure.
 **/
int mipv6_halist_add(int ifindex, struct in6_addr *glob_addr,
		     struct in6_addr *ll_addr, int pref, __u32 lifetime)
{
	int update = 0, ret = 0;
	long mpref;
	struct mipv6_halist_entry *entry = NULL;
	unsigned long flags;

	DEBUG_FUNC();

	write_lock_irqsave(&home_agents->lock, flags);

	if (glob_addr == NULL || lifetime <= 0) {
		DEBUG((DBG_WARNING, "mipv6_halist_add: invalid arguments"));
		write_unlock_irqrestore(&home_agents->lock, flags);
		return -1;
	}
	mpref = PREF_BASE - pref;
	if ((entry = hashlist_get(home_agents->entries, glob_addr)) != NULL) {
		if (entry->ifindex == ifindex) {
			DEBUG((DBG_DATADUMP, "mipv6_halist_add: updating old entry"));
			update = 1;
		} else {
			update = 0;
		}
	}
	if (update) {
		entry->expire = jiffies + lifetime * HZ;
		if (entry->preference != mpref) {
			entry->preference = mpref;
			ret = hashlist_reschedule(home_agents->entries, glob_addr, mpref);
		}
	} else {
		entry = mipv6_halist_new_entry();
		if (entry == NULL) {
			DEBUG((DBG_INFO, "mipv6_halist_add: list full"));
			write_unlock_irqrestore(&home_agents->lock, flags);
			return -1;
		}
		entry->ifindex = ifindex;
		if (ll_addr)
			ipv6_addr_copy(&entry->link_local_addr, ll_addr);
		else
			ipv6_addr_set(&entry->link_local_addr, 0, 0, 0, 0);
		ipv6_addr_copy(&entry->global_addr, glob_addr);
		entry->preference = mpref;
		entry->expire = jiffies + lifetime * HZ;
		ret = hashlist_add(home_agents->entries, glob_addr, mpref, entry);
	}
	write_unlock_irqrestore(&home_agents->lock, flags);

	return ret;
}
Ejemplo n.º 2
0
int mipv6_bcache_put(struct mipv6_bcache_entry *entry)
{
	unsigned long flags;
	write_lock_irqsave(&bcache->lock, flags);
	DEBUG((DBG_INFO, "adding entry: %x", entry));
	if (mipv6_tunnel_add(&entry->coa, &entry->our_addr, 0)) {
		DEBUG((DBG_INFO, "mipv6_bcache_add: no free tunnel devices!"));
		bcache_proxy_nd_rem(entry);
		mipv6_bcache_entry_free(entry);
		write_unlock_irqrestore(&bcache->lock, flags);
		return -1;
	}
	if (mipv6_tunnel_route_add(&entry->home_addr, &entry->coa,
				    &entry->our_addr)) {
		DEBUG((DBG_INFO, "mipv6_bcache_add: invalid route to home address!"));
		mipv6_tunnel_del(&entry->coa, &entry->our_addr);
		bcache_proxy_nd_rem(entry);
		mipv6_bcache_entry_free(entry);
		write_unlock_irqrestore(&bcache->lock, flags);
		return -1;
	}
	if ((hashlist_add(bcache->entries, &entry->home_addr,
		entry->callback_time, entry)) < 0) {
		mipv6_tunnel_route_del(&entry->home_addr, &entry->coa,
			&entry->our_addr);
		mipv6_tunnel_del(&entry->coa, &entry->our_addr);
		bcache_proxy_nd_rem(entry);
		mipv6_bcache_entry_free(entry);
		DEBUG((DBG_ERROR, "Hash add failed"));
		write_unlock_irqrestore(&bcache->lock, flags);
		return -1;
	}
        set_timer();

	write_unlock_irqrestore(&bcache->lock, flags);
	return 0;
}
Ejemplo n.º 3
0
pkgdata* packagelist_add(hashlist* list, stringptr* name, uint32_t hash) {
	pkgdata pkg_empty = {0};
	pkg_empty.name = stringptr_copy(name);
	hashlist_add(list, hash, &pkg_empty);
	return packagelist_get(list, name, hash);
}
Ejemplo n.º 4
0
/**
 * mipv6_bcache_add - add Binding Cache entry
 * @ifindex: interface index
 * @our_addr: own address
 * @home_addr: MN's home address
 * @coa: MN's care-of address
 * @lifetime: lifetime for this binding
 * @prefix: prefix length
 * @seq: sequence number
 * @single: single address bit
 * @type: type of entry
 *
 * Adds an entry for this @home_addr in the Binding Cache.  If entry
 * already exists, old entry is updated.  @type may be %CACHE_ENTRY or
 * %HOME_REGISTRATION.
 **/
int mipv6_bcache_add(
	int ifindex,
	struct in6_addr *our_addr,
	struct in6_addr *home_addr,
	struct in6_addr *coa,
	__u32 lifetime,
	__u8 prefix,
	__u8 seq,
	__u8 single,
	__u8 type) 
{
	unsigned long flags;
	struct mipv6_bcache_entry *entry;
	int update = 0;
	int create_tunnel = 0;
	unsigned long now = jiffies;
	struct cache_entry_iterator_args args;

	write_lock_irqsave(&bcache->lock, flags);

	if ((entry = (struct mipv6_bcache_entry *)
	     hashlist_get(bcache->entries, home_addr)) != NULL) {
                /* if an entry for this home_addr exists (with smaller
		 * seq than the new seq), update it by removing it
		 * first
		 */
		if (SEQMOD(seq, entry->seq)) {
			DEBUG((DBG_INFO, "mipv6_bcache_add: updating an "
			       "existing entry"));
			update = 1;

			if (entry->type == HOME_REGISTRATION) {
				create_tunnel = ipv6_addr_cmp(&entry->our_addr,
							      our_addr) ||
					ipv6_addr_cmp(&entry->coa, coa) ||
					entry->ifindex != ifindex || 
					entry->prefix != prefix || 
					entry->single != single;
				if (create_tunnel || 
				    type != HOME_REGISTRATION) {
					mipv6_tunnel_route_del(
						&entry->home_addr, 
						&entry->coa,
						&entry->our_addr);
					mipv6_tunnel_del(&entry->coa, 
							 &entry->our_addr);
				}				
				if (type != HOME_REGISTRATION) {
					bcache_proxy_nd_rem(entry);
				}
			}
		} else {
			DEBUG((DBG_INFO, "mipv6_bcache_add: smaller seq "
			       "than existing, not updating"));
/*
			write_unlock_irqrestore(&bcache->lock, flags);
			return 0;
*/
		}
	} else {
		/* no entry for this home_addr, try to create a new entry */
		DEBUG((DBG_INFO, "mipv6_bcache_add: creating a new entry"));
		entry = mipv6_bcache_get_entry(type);
		
		if (entry == NULL) {
			/* delete next expiring entry of type CACHE_ENTRY */
			args.entry = &entry;
			hashlist_iterate(bcache->entries, &args,
			                 find_first_cache_entry_iterator);

			if (entry == NULL) {
				DEBUG((DBG_INFO, "mipv6_bcache_add: cache full"));
				write_unlock_irqrestore(&bcache->lock, flags);
				return -1;
			}
			hashlist_delete(bcache->entries, &entry->home_addr);
		}
		create_tunnel = (type == HOME_REGISTRATION);
	}
	
	ipv6_addr_copy(&(entry->our_addr), our_addr);
	ipv6_addr_copy(&(entry->home_addr), home_addr);
	ipv6_addr_copy(&(entry->coa), coa);
	entry->ifindex = ifindex;
	entry->prefix = prefix;
	entry->seq = seq;
	entry->type = type;
	entry->last_used = 0;

	if (type == HOME_REGISTRATION) {
		entry->router = 0;
		entry->single = single;
		if (create_tunnel) {
			if (mipv6_tunnel_add(coa, our_addr, 0)) {
				DEBUG((DBG_INFO, "mipv6_bcache_add: no free tunnel devices!"));
				bcache_proxy_nd_rem(entry);
				if (update) 
					hashlist_delete(bcache->entries, 
							&entry->home_addr);
				mipv6_bcache_entry_free(entry);

				write_unlock_irqrestore(&bcache->lock, flags);
				return -1;
			}
			/* Todo: set the prefix length correctly */
			if (mipv6_tunnel_route_add(home_addr, 
						   coa, 
						   our_addr)) {
				DEBUG((DBG_INFO, "mipv6_bcache_add: invalid route to home address!"));
				mipv6_tunnel_del(coa, our_addr);
				bcache_proxy_nd_rem(entry);

				if (update) 
					hashlist_delete(bcache->entries, 
							&entry->home_addr);
				mipv6_bcache_entry_free(entry);

				write_unlock_irqrestore(&bcache->lock, flags);
				return -1;
			}
		}
	}
	entry->last_br = 0;
	if (lifetime == EXPIRE_INFINITE) {
		entry->callback_time = EXPIRE_INFINITE; 
	} else {
		entry->callback_time = now + lifetime * HZ;
		if (entry->type & (HOME_REGISTRATION | TEMPORARY_ENTRY))
			entry->br_callback_time = 0;
		else
			entry->br_callback_time = now + 
				(lifetime - BCACHE_BR_SEND_LEAD) * HZ;
	}

	if (update) {
		DEBUG((DBG_INFO, "updating entry : %x", entry));
		hashlist_reschedule(bcache->entries,
		                    home_addr,
		                    entry->callback_time);
	} else {
		DEBUG((DBG_INFO, "adding entry: %x", entry));
		if ((hashlist_add(bcache->entries,
				  home_addr,
				  entry->callback_time,
				  entry)) < 0) {
			if (create_tunnel) {
				mipv6_tunnel_route_del(home_addr, 
						       coa, 
						       our_addr);
				mipv6_tunnel_del(coa, our_addr);
				bcache_proxy_nd_rem(entry);
			}
			mipv6_bcache_entry_free(entry);
			DEBUG((DBG_ERROR, "Hash add failed"));
			write_unlock_irqrestore(&bcache->lock, flags);
			return -1;
		}
	}

	set_timer();

	write_unlock_irqrestore(&bcache->lock, flags);
	return 0;
}