/* check if nonce w/ index i is expected/valid and if so marked it "seen" * returns: 0 - ok, < 0 some error: * OTN_INV_POOL (pool number is invalid/corrupted) * OTN_ID_OVERFLOW (crt_id has overflowed with partition size since the * id was generated) * OTN_REPLAY (nonce id seen before => replay ) */ enum otn_check_ret otn_check_id(nid_t id, unsigned pool) { unsigned int i; unsigned n, b; otn_cell_t v, b_mask; if (unlikely(pool>=nid_pool_no)) return OTN_INV_POOL; if (unlikely(otn_id_check_overflow(id, pool))) return OTN_ID_OVERFLOW; n=get_otn_array_bit_idx(id, pool); /* n-th bit */ i=get_otn_array_cell_idx(n); /* aray index i, corresponding to n */ b=get_otn_cell_bit(n); /* bit pos corresponding to n */ b_mask= (otn_cell_t)1<<b; #ifdef OTN_CELL_T_LONG v=atomic_get_long(&oth_array[i]); if (unlikely(v & b_mask)) return OTN_REPLAY; atomic_or_long((long*)&otn_array[i], b_mask); #else v=atomic_get_int(&otn_array[i]); if (unlikely(v & b_mask)) return OTN_REPLAY; atomic_or_int((int*)&otn_array[i], b_mask); #endif /* OTN_CELL_T_LONG */ return 0; }
/*! * \brief Unset a dialog profile * \param msg SIP message * \param value value * \param profile dialog profile table * \return 1 on success, -1 on failure */ int unset_dlg_profile(sip_msg_t *msg, str *value, dlg_profile_table_t *profile) { dlg_cell_t *dlg; dlg_profile_link_t *linker; dlg_profile_link_t *linker_prev; dlg_entry_t *d_entry; if (is_route_type(REQUEST_ROUTE)) { LM_ERR("dialog delete profile cannot be used in request route\n"); return -1; } /* get current dialog */ dlg = dlg_get_msg_dialog(msg); if (dlg==NULL) { LM_WARN("dialog is NULL for delete profile\n"); return -1; } /* check the dialog linkers */ d_entry = &d_table->entries[dlg->h_entry]; dlg_lock( d_table, d_entry); linker = dlg->profile_links; linker_prev = NULL; for( ; linker ; linker_prev=linker,linker=linker->next) { if (linker->profile==profile) { if (profile->has_value==0) { goto found; } else if (value && value->len==linker->hash_linker.value.len && memcmp(value->s,linker->hash_linker.value.s,value->len)==0){ goto found; } /* allow further search - maybe the dialog is inserted twice in * the same profile, but with different values -bogdan */ } } atomic_or_int((volatile int*)&dlg->dflags, DLG_FLAG_CHANGED_PROF); dlg_unlock( d_table, d_entry); dlg_release(dlg); return -1; found: /* table still locked */ /* remove the linker element from dialog */ if (linker_prev==NULL) { dlg->profile_links = linker->next; } else { linker_prev->next = linker->next; } linker->next = NULL; dlg_unlock( d_table, d_entry); /* remove linker from profile table and free it */ destroy_linkers(linker); dlg_release(dlg); return 1; }
/* lockless insert: should be always safe */ int insert_tmcb(struct tmcb_head_list *cb_list, int types, transaction_cb f, void *param, release_tmcb_param rel_func) { struct tm_callback *cbp; struct tm_callback *old; /* build a new callback structure */ if (!(cbp=shm_malloc( sizeof( struct tm_callback)))) { LOG(L_ERR, "ERROR:tm:insert_tmcb: out of shm. mem\n"); return E_OUT_OF_MEM; } atomic_or_int(&cb_list->reg_types, types); /* ... and fill it up */ cbp->callback = f; cbp->param = param; cbp->release = rel_func; cbp->types = types; cbp->id=0; old=(struct tm_callback*)cb_list->first; /* link it into the proper place... */ do{ cbp->next = old; /* if (cbp->next) cbp->id = cbp->next->id+1; else cbp->id = 0; -- callback ids are useless -- andrei */ membar_write_atomic_op(); old=(void*)atomic_cmpxchg_long((void*)&cb_list->first, (long)old, (long)cbp); }while(old!=cbp->next); return 1; }
/*! * \brief Link a dialog profile * \param linker dialog linker * \param dlg dialog cell */ static void link_dlg_profile(struct dlg_profile_link *linker, struct dlg_cell *dlg) { struct dlg_entry *d_entry; /* add the linker to the dialog */ /* FIXME zero h_id is not 100% for testing if the dialog is inserted * into the hash table -> we need circular lists -bogdan */ if (dlg->h_id) { d_entry = &d_table->entries[dlg->h_entry]; dlg_lock( d_table, d_entry); linker->next = dlg->profile_links; dlg->profile_links =linker; linker->hash_linker.dlg = dlg; dlg_unlock( d_table, d_entry); } else { linker->next = dlg->profile_links; dlg->profile_links =linker; linker->hash_linker.dlg = dlg; } atomic_or_int((volatile int*)&dlg->dflags, DLG_FLAG_CHANGED_PROF); link_profile(linker, &dlg->callid); }