X-Git-Url: https://git.saurik.com/apple/ipsec.git/blobdiff_plain/52b7d2ce06d68d0a9160d16f6e7c08c21c149d0d..HEAD:/ipsec-tools/racoon/sainfo.c?ds=sidebyside diff --git a/ipsec-tools/racoon/sainfo.c b/ipsec-tools/racoon/sainfo.c index 2ad8797..e2170bc 100644 --- a/ipsec-tools/racoon/sainfo.c +++ b/ipsec-tools/racoon/sainfo.c @@ -79,12 +79,14 @@ static LIST_HEAD(_sitree, sainfo) sitree; * First pass is for sainfo from a specified peer, second for others. */ struct sainfo * -getsainfo(src, dst, peer) - const vchar_t *src, *dst, *peer; +getsainfo(const vchar_t *src, const vchar_t *dst, const vchar_t *peer, int use_nat_addr) { struct sainfo *s = NULL; struct sainfo *anonymous = NULL; int pass = 1; + + if (use_nat_addr && lcconf->ext_nat_id == NULL) + return NULL; if (peer == NULL) pass = 2; @@ -109,13 +111,21 @@ getsainfo(src, dst, peer) continue; } - if (memcmp(src->v, s->idsrc->v, s->idsrc->l) == 0 - && memcmp(dst->v, s->iddst->v, s->iddst->l) == 0) - return s; + // TODO: handle wildcard port numbers in the id + if ((src->l == s->idsrc->l) && memcmp(src->v, s->idsrc->v, s->idsrc->l) == 0) { + if (use_nat_addr) { + if (memcmp(lcconf->ext_nat_id->v, s->iddst->v, s->iddst->l) == 0) { + plogdump(ASL_LEVEL_DEBUG, lcconf->ext_nat_id->v, lcconf->ext_nat_id->l, "matched external nat address.\n"); + return s; + } + } else if ((dst->l == s->iddst->l) && memcmp(dst->v, s->iddst->v, s->iddst->l) == 0) { + return s; + } + } } if (anonymous) { - plog(LLV_DEBUG, LOCATION, NULL, + plog(ASL_LEVEL_DEBUG, "anonymous sainfo selected.\n"); } else if (pass == 1) { pass = 2; @@ -125,8 +135,58 @@ getsainfo(src, dst, peer) return anonymous; } +/* + * return matching entry. + * no matching entry found and if there is anonymous entry, return it. + * else return NULL. + * XXX by each data type, should be changed to compare the buffer. + */ struct sainfo * -newsainfo() +getsainfo_by_dst_id(const vchar_t *dst, const vchar_t *peer) +{ + struct sainfo *s = NULL; + struct sainfo *anonymous = NULL; + + plog(ASL_LEVEL_DEBUG, "getsainfo_by_dst_id - dst id:\n"); + if (dst != NULL) + plogdump(ASL_LEVEL_DEBUG, dst->v, dst->l, "getsainfo_by_dst_id - dst id:\n"); + else + return NULL; + + LIST_FOREACH(s, &sitree, chain) { + if (s->idsrc != NULL) { + plogdump(ASL_LEVEL_DEBUG, s->idsrc->v, s->idsrc->l, "getsainfo_by_dst_id - sainfo id - src:\n"); + plogdump(ASL_LEVEL_DEBUG, s->iddst->v, s->iddst->l, "getsainfo_by_dst_id - sainfo id - dst:\n"); + } else { + plog(ASL_LEVEL_DEBUG, "getsainfo_by_dst_id - sainfo id = anonymous\n"); + } + if (s->id_i != NULL) { + plogdump(ASL_LEVEL_DEBUG, s->id_i->v, s->id_i->l, "getsainfo_by_dst_id - sainfo id_i:\n"); + if (peer == NULL) + continue; + if (memcmp(peer->v, s->id_i->v, s->id_i->l) != 0) + continue; + } + if (s->idsrc == NULL) { + anonymous = s; + continue; + } + + if (memcmp(dst->v, s->iddst->v, s->iddst->l) == 0) + return s; + } + + if (anonymous) { + plog(ASL_LEVEL_DEBUG, + "anonymous sainfo selected.\n"); + } + + return anonymous; +} + + +struct sainfo * +create_sainfo() { struct sainfo *new; @@ -136,16 +196,18 @@ newsainfo() new->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT; new->lifebyte = IPSECDOI_ATTR_SA_LD_KB_MAX; + new->refcount = 1; + new->in_list = 0; return new; } + void -delsainfo(si) - struct sainfo *si; +delsainfo(struct sainfo *si) { int i; - + for (i = 0; i < MAXALGCLASS; i++) delsainfoalg(si->algs[i]); @@ -154,35 +216,77 @@ delsainfo(si) if (si->iddst) vfree(si->iddst); +#ifdef ENABLE_HYBRID + if (si->group) + vfree(si->group); +#endif + racoon_free(si); } void -inssainfo(new) - struct sainfo *new; +inssainfo(struct sainfo *new) { LIST_INSERT_HEAD(&sitree, new, chain); + new->in_list = 1; } void -remsainfo(si) - struct sainfo *si; +remsainfo(struct sainfo *si) { - LIST_REMOVE(si, chain); + if (si->in_list) { + LIST_REMOVE(si, chain); + si->in_list = 0; + } } +// remove sainfos from linked list +// if not used - delete it void flushsainfo() { struct sainfo *s, *next; - for (s = LIST_FIRST(&sitree); s; s = next) { - next = LIST_NEXT(s, chain); - remsainfo(s); - delsainfo(s); + LIST_FOREACH_SAFE(s, &sitree, chain, next) { + if (s->dynamic == 0) { + remsainfo(s); + if (--(s->refcount) <= 0) + delsainfo(s); + } } } +// remove sainfos from linked list +// if not used - delete it +void +flushsainfo_dynamic(u_int32_t addr) +{ + struct sainfo *s, *next; + + LIST_FOREACH_SAFE(s, &sitree, chain, next) { + if (s->dynamic == addr) { + remsainfo(s); + if (--(s->refcount) <= 0) + delsainfo(s); + } + } +} + +void +retain_sainfo(struct sainfo *si) +{ + (si->refcount)++; +} + +void +release_sainfo(struct sainfo *si) +{ + if (--(si->refcount) <= 0) { + remsainfo(si); + delsainfo(si); + } +} + void initsainfo() { @@ -202,8 +306,7 @@ newsainfoalg() } void -delsainfoalg(alg) - struct sainfoalg *alg; +delsainfoalg(struct sainfoalg *alg) { struct sainfoalg *a, *next; @@ -214,9 +317,7 @@ delsainfoalg(alg) } void -inssainfoalg(head, new) - struct sainfoalg **head; - struct sainfoalg *new; +inssainfoalg(struct sainfoalg **head, struct sainfoalg *new) { struct sainfoalg *a; @@ -228,23 +329,44 @@ inssainfoalg(head, new) *head = new; } + + const char * -sainfo2str(si) - const struct sainfo *si; +sainfo2str(const struct sainfo *si) { + char *idsrc_str; + char *iddst_str; + char *idi_str; static char buf[256]; if (si->idsrc == NULL) snprintf(buf, sizeof(buf), "anonymous"); else { - snprintf(buf, sizeof(buf), "%s", ipsecdoi_id2str(si->idsrc)); - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - " %s", ipsecdoi_id2str(si->iddst)); + idsrc_str = ipsecdoi_id2str(si->idsrc); + if (idsrc_str) { + snprintf(buf, sizeof(buf), "%s", idsrc_str); + racoon_free(idsrc_str); + } + if (si->iddst == NULL) { + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " anonymous"); + } else { + iddst_str = ipsecdoi_id2str(si->iddst); + if (iddst_str) { + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), + " %s", iddst_str); + racoon_free(iddst_str); + } + } } - if (si->id_i != NULL) - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - " from %s", ipsecdoi_id2str(si->id_i)); + if (si->id_i != NULL) { + idi_str = ipsecdoi_id2str(si->id_i); + if (idi_str) { + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), + " from %s", idi_str); + racoon_free(idi_str); + } + } return buf; }