/* * Reinitialize a message buffer, retaining its previous contents if * the size and checksum are correct. If the old contents cannot be * recovered, the message buffer is cleared. */ void msgbuf_reinit(struct msgbuf *mbp, void *ptr, int size) { u_int cksum; if (mbp->msg_magic != MSG_MAGIC || mbp->msg_size != size) { msgbuf_init(mbp, ptr, size); return; } mbp->msg_seqmod = SEQMOD(size); mbp->msg_wseq = MSGBUF_SEQNORM(mbp, mbp->msg_wseq); mbp->msg_rseq = MSGBUF_SEQNORM(mbp, mbp->msg_rseq); mbp->msg_ptr = ptr; cksum = msgbuf_cksum(mbp); if (cksum != mbp->msg_cksum) { if (bootverbose) { printf("msgbuf cksum mismatch (read %x, calc %x)\n", mbp->msg_cksum, cksum); printf("Old msgbuf not recovered\n"); } msgbuf_clear(mbp); } mbp->msg_lastpri = -1; /* Assume that the old message buffer didn't end in a newline. */ mbp->msg_flags |= MSGBUF_NEEDNL; bzero(&mbp->msg_lock, sizeof(mbp->msg_lock)); mtx_init(&mbp->msg_lock, "msgbuf", NULL, MTX_SPIN); }
/* * Initialize a message buffer of the specified size at the specified * location. This also zeros the buffer area. */ void msgbuf_init(struct msgbuf *mbp, void *ptr, int size) { mbp->msg_ptr = ptr; mbp->msg_size = size; mbp->msg_seqmod = SEQMOD(size); msgbuf_clear(mbp); mbp->msg_magic = MSG_MAGIC; }
/* * Initialize a message buffer of the specified size at the specified * location. This also zeros the buffer area. */ void msgbuf_init(struct msgbuf *mbp, void *ptr, int size) { mbp->msg_ptr = ptr; mbp->msg_size = size; mbp->msg_seqmod = SEQMOD(size); msgbuf_clear(mbp); mbp->msg_magic = MSG_MAGIC; mbp->msg_lastpri = -1; mbp->msg_flags = 0; bzero(&mbp->msg_lock, sizeof(mbp->msg_lock)); mtx_init(&mbp->msg_lock, "msgbuf", NULL, MTX_SPIN); }
/* * Reinitialize a message buffer, retaining its previous contents if * the size and checksum are correct. If the old contents cannot be * recovered, the message buffer is cleared. */ void msgbuf_reinit(struct msgbuf *mbp, void *ptr, int size) { u_int cksum; if (mbp->msg_magic != MSG_MAGIC || mbp->msg_size != size) { msgbuf_init(mbp, ptr, size); return; } mbp->msg_seqmod = SEQMOD(size); mbp->msg_wseq = MSGBUF_SEQNORM(mbp, mbp->msg_wseq); mbp->msg_rseq = MSGBUF_SEQNORM(mbp, mbp->msg_rseq); mbp->msg_ptr = ptr; cksum = msgbuf_cksum(mbp); if (cksum != mbp->msg_cksum) { if (bootverbose) { printf("msgbuf cksum mismatch (read %x, calc %x)\n", mbp->msg_cksum, cksum); printf("Old msgbuf not recovered\n"); } msgbuf_clear(mbp); } }
/** * 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; }