📄 ipsec_sa.c
字号:
(unsigned long) sizeof(*ips), ips, ips->ips_ref); if(ips->ips_ref == IPSEC_SAREF_NULL) { kfree(ips); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_alloc: " "SAref allocation error\n"); return NULL; } atomic_inc(&ips->ips_refcount); IPsecSAref2SA(ips->ips_ref) = ips;#endif /* IPSEC_SA_REF_CODE */ *error = 0; return(ips);}intipsec_sa_free(struct ipsec_sa* ips){ return ipsec_sa_wipe(ips);}struct ipsec_sa *ipsec_sa_getbyid(ip_said *said){ int hashval; struct ipsec_sa *ips; char sa[SATOT_BUF]; size_t sa_len; if(said == NULL) { KLIPS_PRINT(debug_xform, "klips_error:ipsec_sa_getbyid: " "null pointer passed in!\n"); return NULL; } sa_len = satot(said, 0, sa, sizeof(sa)); hashval = IPS_HASH(said); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_getbyid: " "linked entry in ipsec_sa table for hash=%d of SA:%s requested.\n", hashval, sa_len ? sa : " (error)"); if((ips = ipsec_sadb_hash[hashval]) == NULL) { KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_getbyid: " "no entries in ipsec_sa table for hash=%d of SA:%s.\n", hashval, sa_len ? sa : " (error)"); return NULL; } for (; ips; ips = ips->ips_hnext) { if ((ips->ips_said.spi == said->spi) && (ips->ips_said.dst.u.v4.sin_addr.s_addr == said->dst.u.v4.sin_addr.s_addr) && (ips->ips_said.proto == said->proto)) { atomic_inc(&ips->ips_refcount); return ips; } } KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_getbyid: " "no entry in linked list for hash=%d of SA:%s.\n", hashval, sa_len ? sa : " (error)"); return NULL;}intipsec_sa_put(struct ipsec_sa *ips){ char sa[SATOT_BUF]; size_t sa_len; if(ips == NULL) { KLIPS_PRINT(debug_xform, "klips_error:ipsec_sa_put: " "null pointer passed in!\n"); return -1; } sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_put: " "ipsec_sa SA:%s, ref:%d reference count decremented.\n", sa_len ? sa : " (error)", ips->ips_ref); atomic_dec(&ips->ips_refcount); return 0;}/* The ipsec_sa table better *NOT* be locked before it is handed in, or SMP locks will happen*/intipsec_sa_add(struct ipsec_sa *ips){ int error = 0; unsigned int hashval; if(ips == NULL) { KLIPS_PRINT(debug_xform, "klips_error:ipsec_sa_add: " "null pointer passed in!\n"); return -ENODATA; } hashval = IPS_HASH(&ips->ips_said); atomic_inc(&ips->ips_refcount); spin_lock_bh(&tdb_lock); ips->ips_hnext = ipsec_sadb_hash[hashval]; ipsec_sadb_hash[hashval] = ips; spin_unlock_bh(&tdb_lock); return error;}/* The ipsec_sa table better be locked before it is handed in, or races might happen*/intipsec_sa_del(struct ipsec_sa *ips){ unsigned int hashval; struct ipsec_sa *ipstp; char sa[SATOT_BUF]; size_t sa_len; if(ips == NULL) { KLIPS_PRINT(debug_xform, "klips_error:ipsec_sa_del: " "null pointer passed in!\n"); return -ENODATA; } sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); if(ips->ips_inext || ips->ips_onext) { KLIPS_PRINT(debug_xform, "klips_error:ipsec_sa_del: " "SA:%s still linked!\n", sa_len ? sa : " (error)"); return -EMLINK; } hashval = IPS_HASH(&ips->ips_said); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_del: " "deleting SA:%s, hashval=%d.\n", sa_len ? sa : " (error)", hashval); if(ipsec_sadb_hash[hashval] == NULL) { KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_del: " "no entries in ipsec_sa table for hash=%d of SA:%s.\n", hashval, sa_len ? sa : " (error)"); return -ENOENT; } if (ips == ipsec_sadb_hash[hashval]) { ipsec_sadb_hash[hashval] = ipsec_sadb_hash[hashval]->ips_hnext; ips->ips_hnext = NULL; atomic_dec(&ips->ips_refcount); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_del: " "successfully deleted first ipsec_sa in chain.\n"); return 0; } else { for (ipstp = ipsec_sadb_hash[hashval]; ipstp; ipstp = ipstp->ips_hnext) { if (ipstp->ips_hnext == ips) { ipstp->ips_hnext = ips->ips_hnext; ips->ips_hnext = NULL; atomic_dec(&ips->ips_refcount); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_del: " "successfully deleted link in ipsec_sa chain.\n"); return 0; } } } KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_del: " "no entries in linked list for hash=%d of SA:%s.\n", hashval, sa_len ? sa : " (error)"); return -ENOENT;}/* The ipsec_sa table better be locked before it is handed in, or races might happen*/intipsec_sa_delchain(struct ipsec_sa *ips){ struct ipsec_sa *ipsdel; int error = 0; char sa[SATOT_BUF]; size_t sa_len; if(ips == NULL) { KLIPS_PRINT(debug_xform, "klips_error:ipsec_sa_delchain: " "null pointer passed in!\n"); return -ENODATA; } sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_delchain: " "passed SA:%s\n", sa_len ? sa : " (error)"); while(ips->ips_onext != NULL) { ips = ips->ips_onext; } while(ips) { /* XXX send a pfkey message up to advise of deleted ipsec_sa */ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_delchain: " "unlinking and delting SA:%s", sa_len ? sa : " (error)"); ipsdel = ips; ips = ips->ips_inext; if(ips != NULL) { sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_xform, ", inext=%s", sa_len ? sa : " (error)"); atomic_dec(&ipsdel->ips_refcount); ipsdel->ips_inext = NULL; atomic_dec(&ips->ips_refcount); ips->ips_onext = NULL; } KLIPS_PRINT(debug_xform, ".\n"); if((error = ipsec_sa_del(ipsdel))) { KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_delchain: " "ipsec_sa_del returned error %d.\n", -error); return error; } if((error = ipsec_sa_wipe(ipsdel))) { KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_delchain: " "ipsec_sa_wipe returned error %d.\n", -error); return error; } } return error;}int ipsec_sadb_cleanup(__u8 proto){ unsigned i; int error = 0; struct ipsec_sa *ips, **ipsprev, *ipsdel; char sa[SATOT_BUF]; size_t sa_len; KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sadb_cleanup: " "cleaning up proto=%d.\n", proto); spin_lock_bh(&tdb_lock); for (i = 0; i < SADB_HASHMOD; i++) { ipsprev = &(ipsec_sadb_hash[i]); ips = ipsec_sadb_hash[i]; if(ips != NULL) { atomic_inc(&ips->ips_refcount); } for(; ips != NULL;) { sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sadb_cleanup: " "checking SA:%s, hash=%d, ref=%d", sa_len ? sa : " (error)", i, ips->ips_ref); ipsdel = ips; ips = ipsdel->ips_hnext; if(ips != NULL) { atomic_inc(&ips->ips_refcount); sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_xform, ", hnext=%s", sa_len ? sa : " (error)"); } if(*ipsprev != NULL) { sa_len = satot(&(*ipsprev)->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_xform, ", *ipsprev=%s", sa_len ? sa : " (error)"); if((*ipsprev)->ips_hnext) { sa_len = satot(&(*ipsprev)->ips_hnext->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_xform, ", *ipsprev->ips_hnext=%s", sa_len ? sa : " (error)"); } } KLIPS_PRINT(debug_xform, ".\n"); if(proto == 0 || (proto == ipsdel->ips_said.proto)) { sa_len = satot(&ipsdel->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sadb_cleanup: " "deleting SA chain:%s.\n", sa_len ? sa : " (error)"); if((error = ipsec_sa_delchain(ipsdel))) { SENDERR(-error); } ipsprev = &(ipsec_sadb_hash[i]); ips = ipsec_sadb_hash[i]; KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sadb_cleanup: " "deleted SA chain:%s", sa_len ? sa : " (error)"); if(ips != NULL) { sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_xform, ", ipsec_sadb_hash[%d]=%s", i, sa_len ? sa : " (error)"); } if(*ipsprev != NULL) { sa_len = satot(&(*ipsprev)->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_xform, ", *ipsprev=%s", sa_len ? sa : " (error)"); if((*ipsprev)->ips_hnext != NULL) { sa_len = satot(&(*ipsprev)->ips_hnext->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_xform, ", *ipsprev->ips_hnext=%s", sa_len ? sa : " (error)"); } } KLIPS_PRINT(debug_xform, ".\n"); } else { ipsprev = &ipsdel; } if(ipsdel != NULL) { ipsec_sa_put(ipsdel); } } } errlab: spin_unlock_bh(&tdb_lock);#if IPSEC_SA_REF_CODE /* clean up SA reference table */ /* go through the ref table and clean out all the SAs */ KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sadb_cleanup: " "removing SAref entries and tables."); { unsigned table, entry; for(table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) { KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sadb_cleanup: " "cleaning SAref table=%u.\n", table); if(ipsec_sadb.refTable[table] == NULL) { printk("\n"); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sadb_cleanup: " "cleaned %u used refTables.\n", table); break; } for(entry = 0; entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) { if(ipsec_sadb.refTable[table]->entry[entry] != NULL) { ipsec_sa_delchain(ipsec_sadb.refTable[table]->entry[entry]); ipsec_sadb.refTable[table]->entry[entry] = NULL; } } } }#endif /* IPSEC_SA_REF_CODE */ return(error);}int ipsec_sadb_free(void){ int error = 0; KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sadb_free: " "freeing SArefTable memory.\n"); /* clean up SA reference table */ /* go through the ref table and clean out all the SAs if any are left and free table memory */ KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sadb_free: " "removing SAref entries and tables.\n"); { unsigned table, entry; for(table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) { KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sadb_free: " "removing SAref table=%u.\n", table); if(ipsec_sadb.refTable[table] == NULL) { KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sadb_free: " "removed %u used refTables.\n", table); break; } for(entry = 0; entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) { if(ipsec_sadb.refTable[table]->entry[entry] != NULL) { ipsec_sa_delchain(ipsec_sadb.refTable[table]->entry[entry]); ipsec_sadb.refTable[table]->entry[entry] = NULL; } } vfree(ipsec_sadb.refTable[table]); ipsec_sadb.refTable[table] = NULL; } } return(error);}intipsec_sa_wipe(struct ipsec_sa *ips){ if(ips == NULL) { return -ENODATA; } /* if(atomic_dec_and_test(ips)) { }; */#if IPSEC_SA_REF_CODE /* remove me from the SArefTable */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -