int ipsec_sa_intern(struct ipsec_sa *ips) { int error = 0; IPsecSAref_t ref = ips->ips_ref; if(ref == IPSEC_SAREF_NULL) { ref = ipsec_SAref_alloc(&error); /* pass in error return by pointer */ KLIPS_PRINT(debug_xform, "ipsec_sa_intern: " "allocated ref=%u for sa %p\n", ref, ips); if(ref == IPSEC_SAREF_NULL) { KLIPS_PRINT(debug_xform, "ipsec_sa_intern: " "SAref allocation error\n"); return error; } ips->ips_ref = ref; } error = ipsec_saref_verify_slot(ref); if(error) { return error; } ipsec_sa_get(ips, IPSEC_REFINTERN); /* * if there is an existing SA at this reference, then free it * note, that nsa might == ips!. That's okay, we just incremented * the reference count above. */ { struct ipsec_sa *nsa = IPsecSAref2SA(ref); if(nsa) { ipsec_sa_put(nsa, IPSEC_REFINTERN); } } KLIPS_PRINT(debug_xform, "ipsec_sa_intern: " "SAref[%d]=%p\n", ips->ips_ref, ips); IPsecSAref2SA(ips->ips_ref) = ips; /* return OK */ return 0; }
void ipsec_sa_untern(struct ipsec_sa *ips) { IPsecSAref_t ref = ips->ips_ref; int error; /* verify that we are removing correct item! */ error = ipsec_saref_verify_slot(ref); if (error) return; if (IPsecSAref2SA(ref) == ips) { IPsecSAref2SA(ref) = NULL; ipsec_sa_put(ips, IPSEC_REFINTERN); } else { KLIPS_PRINT(debug_xform, "ipsec_sa_untern: " "ref=%u -> %p but untern'ing %p\n", ref, IPsecSAref2SA(ref), ips); } }
static int ipsec_SAref_recycle(void) { int table, i; int error = 0; int entry; int addone; ipsec_sadb.refFreeListHead = IPSEC_SAREF_NULL; ipsec_sadb.refFreeListTail = IPSEC_SAREF_NULL; KLIPS_PRINT(debug_xform, "klips_debug:ipsec_SAref_recycle: " "recycling, continuing from SAref=%d (0p%p), table=%d, entry=%d.\n", ipsec_sadb.refFreeListCont, (ipsec_sadb.refTable[IPsecSAref2table(ipsec_sadb. refFreeListCont)] != NULL) ? IPsecSAref2SA(ipsec_sadb.refFreeListCont) : NULL, IPsecSAref2table(ipsec_sadb.refFreeListCont), IPsecSAref2entry(ipsec_sadb.refFreeListCont)); /* add one additional table entry */ addone = 0; for (i = 0; i < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; i++) { if (ipsec_sadb.refFreeListCont == IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES * IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES) { KLIPS_PRINT(debug_xform, "klips_debug:ipsec_SAref_recycle: " "end of table reached, continuing at start..\n"); ipsec_sadb.refFreeListCont = IPSEC_SAREF_FIRST; } table = IPsecSAref2table(ipsec_sadb.refFreeListCont); if (ipsec_sadb.refTable[table] == NULL) { if (addone == 0) { addone = 1; error = ipsec_SArefSubTable_alloc(table); if (error) return error; else break; } } for (entry = IPsecSAref2entry(ipsec_sadb.refFreeListCont); entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) { if (ipsec_sadb.refTable[table]->entry[entry] == NULL) { ipsec_sadb.refFreeList[++ipsec_sadb. refFreeListTail] = IPsecSArefBuild(table, entry); if (ipsec_sadb.refFreeListTail == (IPSEC_SA_REF_FREELIST_NUM_ENTRIES - 1)) { ipsec_sadb.refFreeListHead = IPSEC_SAREF_FIRST; ipsec_sadb.refFreeListCont = ipsec_sadb.refFreeList[ ipsec_sadb. refFreeListTail ] + 1; KLIPS_PRINT(debug_xform, "klips_debug:ipsec_SAref_recycle: " "SArefFreeList refilled.\n"); return 0; } } ipsec_sadb.refFreeListCont++; } } if (ipsec_sadb.refFreeListTail == IPSEC_SAREF_NULL) { KLIPS_PRINT(debug_xform, "klips_debug:ipsec_SAref_recycle: " "out of room in the SArefTable.\n"); return -ENOSPC; } ipsec_sadb.refFreeListHead = IPSEC_SAREF_FIRST; ipsec_sadb.refFreeListCont = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListTail] + 1; KLIPS_PRINT(debug_xform, "klips_debug:ipsec_SAref_recycle: " "SArefFreeList partly refilled to %d of %d.\n", ipsec_sadb.refFreeListTail, IPSEC_SA_REF_FREELIST_NUM_ENTRIES); return 0; }
int ipsec_SAref_recycle(void) { int table, i; int error = 0; int addone; ipsec_sadb.refFreeListHead = IPSEC_SAREF_NULL; ipsec_sadb.refFreeListTail = IPSEC_SAREF_NULL; if(ipsec_sadb.refFreeListCont == IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES * IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES) { KLIPS_PRINT(debug_xform, "klips_debug:ipsec_SAref_recycle: " "end of table reached, continuing at start..\n"); ipsec_sadb.refFreeListCont = IPSEC_SAREF_FIRST; } KLIPS_PRINT(debug_xform, "klips_debug:ipsec_SAref_recycle: " "recycling, continuing from SAref=%d (0p%p), table=%d, entry=%d.\n", ipsec_sadb.refFreeListCont, (ipsec_sadb.refTable[IPsecSAref2table(ipsec_sadb.refFreeListCont)] != NULL) ? IPsecSAref2SA(ipsec_sadb.refFreeListCont) : NULL, IPsecSAref2table(ipsec_sadb.refFreeListCont), IPsecSAref2entry(ipsec_sadb.refFreeListCont)); /* add one additional table entry */ addone = 0; ipsec_sadb.refFreeListHead = IPSEC_SAREF_FIRST; for(i = 0; i < IPSEC_SA_REF_FREELIST_NUM_ENTRIES; i++) { table = IPsecSAref2table(ipsec_sadb.refFreeListCont); if(addone == 0 && ipsec_sadb.refTable[table] == NULL) { addone = 1; error = ipsec_SArefSubTable_alloc(table); if(error) { return error; } } if(ipsec_sadb.refTable[table] == NULL) { /* we failed to add a second table, so just stop */ break; } if(IPsecSAref2SA(ipsec_sadb.refFreeListCont) == NULL) { ipsec_sadb.refFreeList[i] = ipsec_sadb.refFreeListCont; } ipsec_sadb.refFreeListCont++; ipsec_sadb.refFreeListTail=i; } if(ipsec_sadb.refFreeListTail == IPSEC_SAREF_NULL) { KLIPS_PRINT(debug_xform, "klips_debug:ipsec_SAref_recycle: " "out of room in the SArefTable.\n"); return(-ENOSPC); } KLIPS_PRINT(debug_xform, "klips_debug:ipsec_SAref_recycle: " "SArefFreeList partly refilled to %d of %d.\n", ipsec_sadb.refFreeListTail, IPSEC_SA_REF_FREELIST_NUM_ENTRIES); return 0; }