diff options
author | Hakan Olsson <ho@cvs.openbsd.org> | 2004-08-03 10:54:10 +0000 |
---|---|---|
committer | Hakan Olsson <ho@cvs.openbsd.org> | 2004-08-03 10:54:10 +0000 |
commit | b337bae270d603117da35f981f247b3da7e438c2 (patch) | |
tree | df3936e1daf533c07e658cd6f05947a78a1192a6 | |
parent | 1ec3ed82d5c3bf12eb37bd41f367c6326270f671 (diff) |
Rewrite the transport reference count code to avoid leaks.
hshoexer@ ok.
-rw-r--r-- | sbin/isakmpd/nat_traversal.c | 11 | ||||
-rw-r--r-- | sbin/isakmpd/transport.c | 43 | ||||
-rw-r--r-- | sbin/isakmpd/udp.c | 21 | ||||
-rw-r--r-- | sbin/isakmpd/udp.h | 3 | ||||
-rw-r--r-- | sbin/isakmpd/udp_encap.c | 57 | ||||
-rw-r--r-- | sbin/isakmpd/virtual.c | 47 |
6 files changed, 84 insertions, 98 deletions
diff --git a/sbin/isakmpd/nat_traversal.c b/sbin/isakmpd/nat_traversal.c index a358178b0ee..b3fe65e360a 100644 --- a/sbin/isakmpd/nat_traversal.c +++ b/sbin/isakmpd/nat_traversal.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nat_traversal.c,v 1.5 2004/07/29 08:54:08 ho Exp $ */ +/* $OpenBSD: nat_traversal.c,v 1.6 2004/08/03 10:54:09 ho Exp $ */ /* * Copyright (c) 2004 Håkan Olsson. All rights reserved. @@ -430,8 +430,12 @@ nat_t_setup_keepalive(struct sa *sa) { struct sockaddr *src; struct timeval now; + + if (sa->initiator) + sa->transport->vtbl->get_src(sa->transport, &src); + else + sa->transport->vtbl->get_dst(sa->transport, &src); - sa->transport->vtbl->get_src(sa->transport, &src); if (!virtual_listen_lookup(src)) return; @@ -443,4 +447,7 @@ nat_t_setup_keepalive(struct sa *sa) if (!sa->nat_t_keepalive) log_print("nat_t_setup_keepalive: " "timer_add_event() failed, will not send keepalives"); + + LOG_DBG((LOG_TRANSPORT, 50, "nat_t_setup_keepalive: " + "added event for phase 1 SA %p", sa)); } diff --git a/sbin/isakmpd/transport.c b/sbin/isakmpd/transport.c index 749468b01bb..a64c374e56c 100644 --- a/sbin/isakmpd/transport.c +++ b/sbin/isakmpd/transport.c @@ -1,4 +1,4 @@ -/* $OpenBSD: transport.c,v 1.28 2004/06/21 13:09:00 ho Exp $ */ +/* $OpenBSD: transport.c,v 1.29 2004/08/03 10:54:09 ho Exp $ */ /* $EOM: transport.c,v 1.43 2000/10/10 12:36:39 provos Exp $ */ /* @@ -75,17 +75,21 @@ transport_init(void) void transport_setup(struct transport *t, int toplevel) { - LOG_DBG((LOG_TRANSPORT, 70, "transport_setup: adding %p%s", t, - toplevel ? " (virtual)" : "")); - if (toplevel == 0) - LIST_INSERT_HEAD(&transport_list, t, link); - else { - /* Only the toplevel (virtual) transport has the sendqueues. */ + if (toplevel) { + /* Only the toplevel (virtual) transport has sendqueues. */ + LOG_DBG((LOG_TRANSPORT, 70, + "transport_setup: virtual transport %p", t)); TAILQ_INIT(&t->sendq); TAILQ_INIT(&t->prio_sendq); + t->refcnt = 0; + } else { + /* udp and udp_encap trp goes into the transport list. */ + LOG_DBG((LOG_TRANSPORT, 70, + "transport_setup: added %p to transport list", t)); + LIST_INSERT_HEAD(&transport_list, t, link); + t->refcnt = 1; } t->flags = 0; - t->refcnt = 0; } /* Add a referer to transport T. */ @@ -111,15 +115,6 @@ transport_release(struct transport *t) return; LOG_DBG((LOG_TRANSPORT, 70, "transport_release: freeing %p", t)); - if (t->virtual) { - struct virtual_transport *v = - (struct virtual_transport *)t->virtual; - if (v->main == t) - v->main = 0; - else - v->encap = 0; - LIST_REMOVE(t, link); - } t->vtbl->remove(t); } @@ -204,7 +199,7 @@ transport_fd_set(fd_set * fds) if (n > max) max = n; - LOG_DBG((LOG_TRANSPORT,95,"transport_fd_set: " + LOG_DBG((LOG_TRANSPORT, 95, "transport_fd_set: " "transport %p (virtual %p) fd %d", t, t->virtual, n)); } @@ -228,7 +223,8 @@ transport_pending_wfd_set(fd_set * fds) if (TAILQ_FIRST(&t->virtual->sendq) || TAILQ_FIRST(&t->virtual->prio_sendq)) { n = t->vtbl->fd_set(t, fds, 1); - LOG_DBG((LOG_TRANSPORT,95,"transport_pending_wfd_set: " + LOG_DBG((LOG_TRANSPORT, 95, + "transport_pending_wfd_set: " "transport %p (virtual %p) fd %d pending", t, t->virtual, n)); if (n > max) @@ -278,10 +274,8 @@ transport_send_messages(fd_set * fds) * Reference all transports first so noone will disappear while in * use. */ - for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) { + for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) transport_reference(t->virtual); - transport_reference(t); - } for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) { if ((TAILQ_FIRST(&t->virtual->sendq) || @@ -353,6 +347,10 @@ transport_send_messages(fd_set * fds) "scan"); } exchange->last_sent = 0; +#ifdef notyet + exchange_free(exchange); + exchange = 0; +#endif } else { gettimeofday(&expiration, 0); @@ -412,7 +410,6 @@ transport_send_messages(fd_set * fds) for (t = LIST_FIRST(&transport_list); t; t = next) { next = LIST_NEXT(t, link); transport_release(t->virtual); - transport_release(t); } } diff --git a/sbin/isakmpd/udp.c b/sbin/isakmpd/udp.c index 20c2ce42a88..65b88e92c5e 100644 --- a/sbin/isakmpd/udp.c +++ b/sbin/isakmpd/udp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp.c,v 1.77 2004/06/25 19:42:38 mcbride Exp $ */ +/* $OpenBSD: udp.c,v 1.78 2004/08/03 10:54:09 ho Exp $ */ /* $EOM: udp.c,v 1.57 2001/01/26 10:09:57 niklas Exp $ */ /* @@ -76,9 +76,9 @@ int udp_fd_isset(struct transport *, fd_set *); void udp_get_dst(struct transport *, struct sockaddr **); void udp_get_src(struct transport *, struct sockaddr **); char *udp_decode_ids(struct transport *); +void udp_remove(struct transport *); static struct transport *udp_create(char *); -static void udp_remove(struct transport *); static void udp_report(struct transport *); static void udp_handle_message(struct transport *); static struct transport *udp_make(struct sockaddr *); @@ -193,7 +193,6 @@ udp_make(struct sockaddr *laddr) free (tstr); } transport_setup(&t->transport, 0); - transport_reference(&t->transport); t->transport.flags |= TRANSPORT_LISTEN; return &t->transport; @@ -355,10 +354,8 @@ udp_create(char *name) } t = (struct transport *)v; rv = udp_clone(v->main, dst); - if (rv) { + if (rv) rv->vtbl = &udp_transport_vtbl; - transport_reference(rv->virtual); - } ret: if (addr_list) @@ -376,12 +373,12 @@ udp_remove(struct transport *t) free(u->src); if (u->dst) free(u->dst); - if (t->flags & TRANSPORT_LISTEN) { - if (u->s >= 0) - close(u->s); - if (u->link.le_prev) - LIST_REMOVE(u, link); - } + if ((t->flags & TRANSPORT_LISTEN) && u->s >= 0) + close(u->s); + if (t->link.le_prev) + LIST_REMOVE(t, link); + + LOG_DBG((LOG_TRANSPORT, 90, "udp_remove: removed transport %p", t)); free(t); } diff --git a/sbin/isakmpd/udp.h b/sbin/isakmpd/udp.h index 44916ccc044..dd91a6ce7e4 100644 --- a/sbin/isakmpd/udp.h +++ b/sbin/isakmpd/udp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: udp.h,v 1.9 2004/06/20 15:24:05 ho Exp $ */ +/* $OpenBSD: udp.h,v 1.10 2004/08/03 10:54:09 ho Exp $ */ /* $EOM: udp.h,v 1.4 1998/12/22 02:23:43 niklas Exp $ */ /* @@ -47,7 +47,6 @@ struct udp_transport { struct sockaddr *src; struct sockaddr *dst; int s; - LIST_ENTRY(udp_transport) link; }; #endif /* _UDP_H_ */ diff --git a/sbin/isakmpd/udp_encap.c b/sbin/isakmpd/udp_encap.c index 0ad696d950c..c59bd0c7636 100644 --- a/sbin/isakmpd/udp_encap.c +++ b/sbin/isakmpd/udp_encap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_encap.c,v 1.4 2004/07/07 09:13:01 hshoexer Exp $ */ +/* $OpenBSD: udp_encap.c,v 1.5 2004/08/03 10:54:09 ho Exp $ */ /* * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved. @@ -67,26 +67,26 @@ #endif /* Reused, from udp.c */ -struct transport *udp_clone (struct transport *, struct sockaddr *); +struct transport *udp_clone(struct transport *, struct sockaddr *); int udp_fd_set(struct transport *, fd_set *, int); int udp_fd_isset(struct transport *, fd_set *); -void udp_get_dst (struct transport *, struct sockaddr **); -void udp_get_src (struct transport *, struct sockaddr **); -char *udp_decode_ids (struct transport *); - -static struct transport *udp_encap_create (char *); -static void udp_encap_remove (struct transport *); -static void udp_encap_report (struct transport *); -static void udp_encap_handle_message (struct transport *); -static struct transport *udp_encap_make (struct sockaddr *); -static int udp_encap_send_message (struct message *, +void udp_get_dst(struct transport *, struct sockaddr **); +void udp_get_src(struct transport *, struct sockaddr **); +char *udp_decode_ids(struct transport *); +void udp_remove(struct transport *); + +static struct transport *udp_encap_create(char *); +static void udp_encap_report(struct transport *); +static void udp_encap_handle_message(struct transport *); +static struct transport *udp_encap_make(struct sockaddr *); +static int udp_encap_send_message(struct message *, struct transport *); static struct transport_vtbl udp_encap_transport_vtbl = { { 0 }, "udp_encap", udp_encap_create, 0, - udp_encap_remove, + udp_remove, udp_encap_report, udp_fd_set, udp_fd_isset, @@ -191,7 +191,6 @@ udp_encap_make(struct sockaddr *laddr) free(tstr); } transport_setup(&t->transport, 0); - transport_reference(&t->transport); t->transport.flags |= TRANSPORT_LISTEN; return &t->transport; @@ -201,7 +200,7 @@ err: if (t) { /* Already closed. */ t->s = -1; - udp_encap_remove(&t->transport); + udp_remove(&t->transport); } return 0; } @@ -312,36 +311,16 @@ udp_encap_create(char *name) } t = (struct transport *)v; rv = udp_clone(v->encap, dst); - if (rv) { - rv->vtbl = &udp_encap_transport_vtbl; /* XXX Necessary? */ - transport_reference(rv->virtual); - } - - ret: + if (rv) + rv->vtbl = &udp_encap_transport_vtbl; + +ret: if (addr_list) conf_free_list(addr_list); free(dst); return rv; } -void -udp_encap_remove(struct transport *t) -{ - struct udp_transport *u = (struct udp_transport *)t; - - if (u->src) - free (u->src); - if (u->dst) - free (u->dst); - if (t->flags & TRANSPORT_LISTEN) { - if (u->s >= 0) - close (u->s); - if (u->link.le_prev) - LIST_REMOVE (u, link); - } - free (t); -} - /* Report transport-method specifics of the T transport. */ void udp_encap_report(struct transport *t) diff --git a/sbin/isakmpd/virtual.c b/sbin/isakmpd/virtual.c index 9f5fdfc9774..bd0dcb92415 100644 --- a/sbin/isakmpd/virtual.c +++ b/sbin/isakmpd/virtual.c @@ -1,4 +1,4 @@ -/* $OpenBSD: virtual.c,v 1.5 2004/07/08 19:53:46 hshoexer Exp $ */ +/* $OpenBSD: virtual.c,v 1.6 2004/08/03 10:54:09 ho Exp $ */ /* * Copyright (c) 2004 Håkan Olsson. All rights reserved. @@ -126,6 +126,7 @@ virtual_init(void) return; LIST_INSERT_HEAD(&virtual_listen_list, (struct virtual_transport *)default_transport, link); + transport_reference(default_transport); } if (!bind_family || (bind_family & BIND_FAMILY_INET6)) { @@ -134,7 +135,10 @@ virtual_init(void) return; LIST_INSERT_HEAD(&virtual_listen_list, (struct virtual_transport *)default_transport6, link); + transport_reference(default_transport6); } + + return; } struct virtual_transport * @@ -194,11 +198,18 @@ struct virtual_transport * virtual_listen_lookup(struct sockaddr *addr) { struct virtual_transport *v; - struct udp_transport *u; + struct udp_transport *u; for (v = LIST_FIRST(&virtual_listen_list); v; v = LIST_NEXT(v, link)) { - u = (struct udp_transport *)v->main; + if (!(u = (struct udp_transport *)v->main)) + if (!(u = (struct udp_transport *)v->encap)) { + log_print("virtual_listen_lookup: " + "virtual %p has no low-level transports", + v); + continue; + } + if (u->src->sa_family == addr->sa_family && sockaddr_addrlen(u->src) == sockaddr_addrlen(addr) && memcmp(sockaddr_addrdata (u->src), @@ -207,6 +218,7 @@ virtual_listen_lookup(struct sockaddr *addr) return v; } + LOG_DBG((LOG_TRANSPORT, 40, "virtual_listen_lookup: no match")); return 0; } @@ -267,7 +279,7 @@ virtual_bind(const struct sockaddr *addr) if (*ep != '\0' || lport < 0 || lport > USHRT_MAX) { log_print("virtual_bind: " "port string \"%s\" not convertible to in_port_t", port); - transport_release(v->main); + v->main->vtbl->remove(v->main); free(v); return 0; } @@ -275,7 +287,7 @@ virtual_bind(const struct sockaddr *addr) sockaddr_set_port((struct sockaddr *)&tmp_sa, (in_port_t)lport); v->encap = udp_encap_bind((struct sockaddr *)&tmp_sa); if (!v->encap) { - transport_release(v->main); + v->main->vtbl->remove(v->main); free(v); return 0; } @@ -284,7 +296,6 @@ virtual_bind(const struct sockaddr *addr) v->encap_is_active = 0; transport_setup(&v->transport, 1); - transport_reference(&v->transport); v->transport.flags |= TRANSPORT_LISTEN; return (struct transport *)v; @@ -484,6 +495,7 @@ virtual_bind_if(char *ifname, struct sockaddr *if_addr, void *arg) } LIST_INSERT_HEAD(&virtual_listen_list, (struct virtual_transport *)t, link); + transport_reference(t); return 0; } @@ -503,6 +515,9 @@ virtual_clone(struct transport *vt, struct sockaddr *raddr) v2 = (struct virtual_transport *)t; memcpy(v2, v, sizeof *v); + /* Remove the copy's links into virtual_listen_list. */ + v2->link.le_next = 0; + v2->link.le_prev = 0; if (v->encap_is_active) v2->main = 0; /* No need to clone this. */ @@ -523,13 +538,6 @@ virtual_clone(struct transport *vt, struct sockaddr *raddr) t->flags &= ~TRANSPORT_LISTEN; transport_setup(t, 1); - - transport_reference(t); - if (v2->main) - transport_reference(v2->main); - if (v2->encap) - transport_reference(v2->encap); - return t; } @@ -572,8 +580,6 @@ virtual_create(char *name) if (t2) t2->virtual = (struct transport *)v; transport_setup(&v->transport, 1); - LIST_INSERT_HEAD(&virtual_listen_list, v, link); - return (struct transport *)v; } @@ -589,6 +595,7 @@ virtual_remove(struct transport *t) if (v->link.le_prev) LIST_REMOVE(v, link); + LOG_DBG((LOG_TRANSPORT, 90, "virtual_remove: removed %p", v)); free(t); } @@ -638,7 +645,7 @@ virtual_send_message(struct message *msg, struct transport *t) struct virtual_transport *v = (struct virtual_transport *)msg->transport; #if defined (USE_NAT_TRAVERSAL) - struct sockaddr *sa; + struct sockaddr *dst; in_port_t port; /* @@ -657,11 +664,11 @@ virtual_send_message(struct message *msg, struct transport *t) v->encap_is_active++; /* Copy destination port if it is translated (NAT). */ - v->main->vtbl->get_dst(v->main, &sa); - port = ntohs(sockaddr_port(sa)); + v->main->vtbl->get_dst(v->main, &dst); + port = ntohs(sockaddr_port(dst)); if (port != UDP_DEFAULT_PORT) { - v->main->vtbl->get_dst(v->encap, &sa); - sockaddr_set_port(sa, port); + v->main->vtbl->get_dst(v->encap, &dst); + sockaddr_set_port(dst, port); } } #endif /* USE_NAT_TRAVERSAL */ |