pkgdata* packagelist_get(hashlist* list, stringptr* name, uint32_t hash) { sblist* bucket = hashlist_get(list, hash); pkgdata* result; if(bucket) { sblist_iter(bucket, result) { if(EQ(name, result->name)) return result; } } return NULL; }
/** * 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; }
/** * mipv6_bcache_exists - check if entry exists * @home_addr: address to check * * Determines if a binding exists for @home_addr. Returns type of the * entry or negative if entry does not exist. **/ int mipv6_bcache_exists(struct in6_addr *home_addr) { unsigned long flags; struct mipv6_bcache_entry *entry; DEBUG_FUNC(); if (home_addr == NULL) return -1; read_lock_irqsave(&bcache->lock, flags); entry = (struct mipv6_bcache_entry *) hashlist_get(bcache->entries, home_addr); read_unlock_irqrestore(&bcache->lock, flags); if(entry == NULL) return -1; return entry->type; }
/** * mipv6_bcache_delete - delete Binding Cache entry * @home_addr: MN's home address * @type: type of entry * * Deletes an entry associated with @home_addr from Binding Cache. * Valid values for @type are %CACHE_ENTRY, %HOME_REGISTRATION and * %ANY_ENTRY. %ANY_ENTRY deletes any type of entry. **/ int mipv6_bcache_delete(struct in6_addr *home_addr, __u8 type) { unsigned long flags; struct mipv6_bcache_entry *entry; DEBUG_FUNC(); if (home_addr == NULL || !is_valid_type(type)) { DEBUG((DBG_INFO, "error in arguments")); return -1; } write_lock_irqsave(&bcache->lock, flags); entry = (struct mipv6_bcache_entry *) hashlist_get(bcache->entries, home_addr); if (entry == NULL) { DEBUG((DBG_INFO, "mipv6_bcache_delete: No such entry")); write_unlock_irqrestore(&bcache->lock, flags); return -1; } if (!(entry->type & type)) { DEBUG((DBG_INFO, "mipv6_bcache_delete: No entry with " "type correct type")); write_unlock_irqrestore(&bcache->lock, flags); return -1; } if (type == HOME_REGISTRATION) { 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); } hashlist_delete(bcache->entries, &entry->home_addr); mipv6_bcache_entry_free(entry); set_timer(); write_unlock_irqrestore(&bcache->lock, flags); return 0; }
/** * mipv6_bcache_get - get entry from Binding Cache * @home_addr: address to search * @entry: pointer to buffer * * Gets a copy of Binding Cache entry for @home_addr. Entry's * @last_used field is updated. If entry exists entry is copied to * @entry and zero is returned. Otherwise returns negative. **/ int mipv6_bcache_get( struct in6_addr *home_addr, struct mipv6_bcache_entry *entry) { unsigned long flags; struct mipv6_bcache_entry *entry2; DEBUG_FUNC(); if (home_addr == NULL || entry == NULL) return -1; read_lock_irqsave(&bcache->lock, flags); entry2 = (struct mipv6_bcache_entry *) hashlist_get(bcache->entries, home_addr); if (entry2 != NULL) { entry2->last_used = jiffies; memcpy(entry, entry2, sizeof(struct mipv6_bcache_entry)); } read_unlock_irqrestore(&bcache->lock, flags); return (entry2 == NULL)? -1 : 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; }