struct ipsec_sa* ipsec_sa_alloc(int*error) /* pass in error var by pointer */ { struct ipsec_sa* ips; if((ips = kmalloc(sizeof(*ips), GFP_ATOMIC) ) == NULL) { KLIPS_PRINT(debug_xform, "ipsec_sa_alloc: " "memory allocation error\n"); *error = -ENOMEM; return NULL; } memset((caddr_t)ips, 0, sizeof(*ips)); #ifdef IPSEC_SA_RECOUNT_DEBUG ips->ips_raw = ipsec_sa_raw; ipsec_sa_raw = ips; #endif /* return with at least counter = 1 */ ipsec_sa_get(ips, IPSEC_REFALLOC); *error = 0; return(ips); }
/* The ipsec_sa table better *NOT* be locked before it is handed in, or SMP locks will happen */ int ipsec_sa_add(struct ipsec_sa *ips) { int error = 0; unsigned int hashval; ips = ipsec_sa_get(ips); 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); spin_lock_bh(&tdb_lock); ips->ips_hnext = ipsec_sadb_hash[hashval]; ipsec_sadb_hash[hashval] = ips; spin_unlock_bh(&tdb_lock); return error; }
struct ipsec_sa *ipsec_sa_getbyref(IPsecSAref_t ref, int type) { struct ipsec_sa *ips; struct IPsecSArefSubTable *st = ipsec_sadb.refTable[IPsecSAref2table(ref)]; if (st == NULL) return NULL; ips = st->entry[IPsecSAref2entry(ref)]; if (ips) ipsec_sa_get(ips, type); return ips; }
struct ipsec_sa * ipsec_sa_getbyid(ip_said *said, int type) { int hashval; struct ipsec_sa *ips; char sa[SATOT_BUF]; size_t sa_len; if(said == NULL) { KLIPS_PRINT(debug_xform, "ipsec_sa_getbyid: " "null pointer passed in!\n"); return NULL; } hashval = IPS_HASH(said); sa_len = KLIPS_SATOT(debug_xform, said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_xform, "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, "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) && (ip_address_cmp(&ips->ips_said.dst, &said->dst) == 0) && (ips->ips_said.proto == said->proto)) { ipsec_sa_get(ips, type); return ips; } } KLIPS_PRINT(debug_xform, "ipsec_sa_getbyid: " "no entry in linked list for hash=%d of SA:%s.\n", hashval, sa_len ? sa : " (error)"); return NULL; }
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; }
struct ipsec_sa * ipsec_sa_getbyref(IPsecSAref_t ref) { struct ipsec_sa *ips; struct IPsecSArefSubTable *st = ipsec_sadb.refTable[IPsecSAref2table(ref)]; if(st == NULL) { return NULL; } ips = st->entry[IPsecSAref2entry(ref)]; if(ips) { ipsec_sa_get(ips); } return ips; }
struct ipsec_sa* ipsec_sa_alloc(int*error) /* pass in error var by pointer */ { struct ipsec_sa* ips; if((ips = kmalloc(sizeof(*ips), GFP_ATOMIC) ) == NULL) { KLIPS_PRINT(debug_xform, "ipsec_sa_alloc: " "memory allocation error\n"); *error = -ENOMEM; return NULL; } memset((caddr_t)ips, 0, sizeof(*ips)); /* return with at least counter = 1 */ ipsec_sa_get(ips); *error = 0; return(ips); }
IPSEC_PROCFS_DEBUG_NO_STATIC int ipsec_spi_format(struct ipsec_sa *sa_p, struct seq_file *seq) { char sa[SATOT_BUF]; char buf_s[SUBNETTOA_BUF]; char buf_d[SUBNETTOA_BUF]; size_t sa_len; ipsec_sa_get(sa_p, IPSEC_REFPROC); sa_len = satot(&sa_p->ips_said, 'x', sa, sizeof(sa)); seq_printf(seq, "%s ", sa_len ? sa : " (error)"); seq_printf(seq, "%s%s%s", IPS_XFORM_NAME(sa_p)); seq_printf(seq, ": dir=%s", (sa_p->ips_flags & EMT_INBOUND) ? "in " : "out"); if (sa_p->ips_addr_s) { sin_addrtot(sa_p->ips_addr_s, 0, buf_s, sizeof(buf_s)); seq_printf(seq, " src=%s", buf_s); } if ((sa_p->ips_said.proto == IPPROTO_IPIP) && (sa_p->ips_flags & (SADB_X_SAFLAGS_INFLOW |SADB_X_SAFLAGS_POLICYONLY))) { if (sa_p->ips_flow_s.u.v4.sin_family == AF_INET) { subnettoa(sa_p->ips_flow_s.u.v4.sin_addr, sa_p->ips_mask_s.u.v4.sin_addr, 0, buf_s, sizeof(buf_s)); subnettoa(sa_p->ips_flow_d.u.v4.sin_addr, sa_p->ips_mask_d.u.v4.sin_addr, 0, buf_d, sizeof(buf_d)); } else { subnet6toa(&sa_p->ips_flow_s.u.v6.sin6_addr, &sa_p->ips_mask_s.u.v6.sin6_addr, 0, buf_s, sizeof(buf_s)); subnet6toa(&sa_p->ips_flow_d.u.v6.sin6_addr, &sa_p->ips_mask_d.u.v6.sin6_addr, 0, buf_d, sizeof(buf_d)); } seq_printf(seq, " policy=%s->%s", buf_s, buf_d); } if (sa_p->ips_iv_bits) { int j; seq_printf(seq, " iv_bits=%dbits iv=0x", sa_p->ips_iv_bits); for (j = 0; j < sa_p->ips_iv_bits / 8; j++) { #ifdef CONFIG_KLIPS_OCF if (sa_p->ips_iv == NULL) { /* * ocf doesn't set the IV * so fake it for the test cases */ seq_printf(seq, "%02x", 0xA5 + j); } else #endif seq_printf(seq, "%02x", ((__u8*)sa_p->ips_iv)[j]); } } if (sa_p->ips_encalg || sa_p->ips_authalg) { if (sa_p->ips_replaywin) seq_printf(seq, " ooowin=%d", sa_p->ips_replaywin); if (sa_p->ips_errs.ips_replaywin_errs) seq_printf(seq, " ooo_errs=%d", sa_p->ips_errs.ips_replaywin_errs); if (sa_p->ips_replaywin_lastseq) seq_printf(seq, " seq=%d", sa_p->ips_replaywin_lastseq); if (sa_p->ips_replaywin_bitmap) seq_printf(seq, " bit=0x%Lx", sa_p->ips_replaywin_bitmap); if (sa_p->ips_replaywin_maxdiff) seq_printf(seq, " max_seq_diff=%d", sa_p->ips_replaywin_maxdiff); } if (sa_p->ips_flags & ~EMT_INBOUND) { seq_printf(seq, " flags=0x%x", sa_p->ips_flags & ~EMT_INBOUND); seq_printf(seq, "<"); /* flag printing goes here */ seq_printf(seq, ">"); } if (sa_p->ips_auth_bits) seq_printf(seq, " alen=%d", sa_p->ips_auth_bits); if (sa_p->ips_key_bits_a) seq_printf(seq, " aklen=%d", sa_p->ips_key_bits_a); if (sa_p->ips_errs.ips_auth_errs) seq_printf(seq, " auth_errs=%d", sa_p->ips_errs.ips_auth_errs); if (sa_p->ips_key_bits_e) seq_printf(seq, " eklen=%d", sa_p->ips_key_bits_e); if (sa_p->ips_errs.ips_encsize_errs) seq_printf(seq, " encr_size_errs=%d", sa_p->ips_errs.ips_encsize_errs); if (sa_p->ips_errs.ips_encpad_errs) seq_printf(seq, " encr_pad_errs=%d", sa_p->ips_errs.ips_encpad_errs); seq_printf(seq, " jiffies=%lu", jiffies); seq_printf(seq, " life(c,s,h)="); ipsec_lifetime_format(seq, "alloc", ipsec_life_countbased, &sa_p->ips_life.ipl_allocations); ipsec_lifetime_format(seq, "bytes", ipsec_life_countbased, &sa_p->ips_life.ipl_bytes); ipsec_lifetime_format(seq, "addtime", ipsec_life_timebased, &sa_p->ips_life.ipl_addtime); ipsec_lifetime_format(seq, "usetime", ipsec_life_timebased, &sa_p->ips_life.ipl_usetime); ipsec_lifetime_format(seq, "packets", ipsec_life_countbased, &sa_p->ips_life.ipl_packets); if (sa_p->ips_life.ipl_usetime.ipl_last) { /* XXX-MCR should be last? */ seq_printf(seq, " idle=%Ld", ipsec_jiffieshz_elapsed(jiffies/HZ, sa_p->ips_life.ipl_usetime.ipl_last)); } #ifdef CONFIG_KLIPS_IPCOMP if (sa_p->ips_said.proto == IPPROTO_COMP && (sa_p->ips_comp_ratio_dbytes || sa_p->ips_comp_ratio_cbytes)) { seq_printf(seq, " ratio=%Ld:%Ld", sa_p->ips_comp_ratio_dbytes, sa_p->ips_comp_ratio_cbytes); } #endif /* CONFIG_KLIPS_IPCOMP */ seq_printf(seq, " natencap="); switch (sa_p->ips_natt_type) { case 0: seq_printf(seq, "none"); break; case ESPINUDP_WITH_NON_IKE: seq_printf(seq, "nonike"); break; case ESPINUDP_WITH_NON_ESP: seq_printf(seq, "nonesp"); break; default: seq_printf(seq, "unknown"); break; } seq_printf(seq, " natsport=%d", sa_p->ips_natt_sport); seq_printf(seq, " natdport=%d", sa_p->ips_natt_dport); /* we decrement by one, because this SA has been referenced in order to dump this info */ seq_printf(seq, " refcount=%d", atomic_read(&sa_p->ips_refcount)-1); #ifdef IPSEC_SA_RECOUNT_DEBUG { int f; seq_printf(seq, "["); for (f = 0; f < sizeof(sa_p->ips_track); f++) seq_printf(seq, "%s%d", f == 0 ? "" : ",", sa_p->ips_track[f]); seq_printf(seq, "]"); } #endif seq_printf(seq, " ref=%d", sa_p->ips_ref); seq_printf(seq, " refhim=%d", sa_p->ips_refhim); if (sa_p->ips_out) { seq_printf(seq, " outif=%s:%d", sa_p->ips_out->name, sa_p->ips_transport_direct); } if (debug_xform) { seq_printf(seq, " reftable=%lu refentry=%lu", (unsigned long)IPsecSAref2table(sa_p->ips_ref), (unsigned long)IPsecSAref2entry(sa_p->ips_ref)); } seq_printf(seq, "\n"); ipsec_sa_put(sa_p, IPSEC_REFPROC); return 0; }