diff options
author | Othmar Gsenger <otti@anytun.org> | 2008-05-25 09:50:42 +0000 |
---|---|---|
committer | Othmar Gsenger <otti@anytun.org> | 2008-05-25 09:50:42 +0000 |
commit | 71da41451212389bea25d67bc5da696b6d194bff (patch) | |
tree | a3b20decbd8bc9e47640af5fa4b39f731477955a /keyexchange/isakmpd-20041012/transport.c | |
parent | improved presentation again (diff) |
moved keyexchange to http://anytun.org/svn/keyexchange
Diffstat (limited to 'keyexchange/isakmpd-20041012/transport.c')
-rw-r--r-- | keyexchange/isakmpd-20041012/transport.c | 431 |
1 files changed, 0 insertions, 431 deletions
diff --git a/keyexchange/isakmpd-20041012/transport.c b/keyexchange/isakmpd-20041012/transport.c deleted file mode 100644 index 023e819..0000000 --- a/keyexchange/isakmpd-20041012/transport.c +++ /dev/null @@ -1,431 +0,0 @@ -/* $OpenBSD: transport.c,v 1.30 2004/08/08 19:11:06 deraadt Exp $ */ -/* $EOM: transport.c,v 1.43 2000/10/10 12:36:39 provos Exp $ */ - -/* - * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. - * Copyright (c) 2001, 2004 Håkan Olsson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This code was written under funding by Ericsson Radio Systems. - */ - -#include <sys/param.h> -#include <sys/queue.h> -#include <string.h> - -#include "sysdep.h" - -#include "conf.h" -#include "exchange.h" -#include "log.h" -#include "message.h" -#include "sa.h" -#include "timer.h" -#include "transport.h" -#include "virtual.h" - -/* If no retransmit limit is given, use this as a default. */ -#define RETRANSMIT_DEFAULT 10 - -LIST_HEAD(transport_list, transport) transport_list; -LIST_HEAD(transport_method_list, transport_vtbl) transport_method_list; - -/* Call the reinit function of the various transports. */ -void -transport_reinit(void) -{ - struct transport_vtbl *method; - - for (method = LIST_FIRST(&transport_method_list); method; - method = LIST_NEXT(method, link)) - if (method->reinit) - method->reinit(); -} - -/* Initialize the transport maintenance module. */ -void -transport_init(void) -{ - LIST_INIT(&transport_list); - LIST_INIT(&transport_method_list); -} - -/* Register another transport T. */ -void -transport_setup(struct transport *t, int toplevel) -{ - 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; -} - -/* Add a referer to transport T. */ -void -transport_reference(struct transport *t) -{ - t->refcnt++; - LOG_DBG((LOG_TRANSPORT, 95, - "transport_reference: transport %p now has %d references", t, - t->refcnt)); -} - -/* - * Remove a referer from transport T, removing all of T when no referers left. - */ -void -transport_release(struct transport *t) -{ - LOG_DBG((LOG_TRANSPORT, 95, - "transport_release: transport %p had %d references", t, - t->refcnt)); - if (--t->refcnt) - return; - - LOG_DBG((LOG_TRANSPORT, 70, "transport_release: freeing %p", t)); - t->vtbl->remove(t); -} - -void -transport_report(void) -{ - struct virtual_transport *v; - struct transport *t; - struct message *msg; - - for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) { - LOG_DBG((LOG_REPORT, 0, - "transport_report: transport %p flags %x refcnt %d", t, - t->flags, t->refcnt)); - - /* XXX Report sth on the virtual transport? */ - t->vtbl->report(t); - - /* - * This is the reason message_dump_raw lives outside - * message.c. - */ - v = (struct virtual_transport *)t->virtual; - if ((v->encap_is_active && v->encap == t) || - (!v->encap_is_active && v->main == t)) { - for (msg = TAILQ_FIRST(&t->virtual->prio_sendq); msg; - msg = TAILQ_NEXT(msg, link)) - message_dump_raw("udp_report(prio)", msg, - LOG_REPORT); - - for (msg = TAILQ_FIRST(&t->virtual->sendq); msg; - msg = TAILQ_NEXT(msg, link)) - message_dump_raw("udp_report", msg, - LOG_REPORT); - } - } -} - -int -transport_prio_sendqs_empty(void) -{ - struct transport *t; - - for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) - if (TAILQ_FIRST(&t->virtual->prio_sendq)) - return 0; - return 1; -} - -/* Register another transport method T. */ -void -transport_method_add(struct transport_vtbl *t) -{ - LIST_INSERT_HEAD(&transport_method_list, t, link); -} - -/* Apply a function FUNC on all registered (non-toplevel) transports. */ -void -transport_map(void (*func) (struct transport *)) -{ - struct transport *t; - - for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) - (*func) (t); -} - -/* - * Build up a file descriptor set FDS with all transport descriptors we want - * to read from. Return the number of file descriptors select(2) needs to - * check in order to cover the ones we setup in here. - */ -int -transport_fd_set(fd_set * fds) -{ - struct transport *t; - int n; - int max = -1; - - for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) - if (t->virtual->flags & TRANSPORT_LISTEN) { - n = t->vtbl->fd_set(t, fds, 1); - if (n > max) - max = n; - - LOG_DBG((LOG_TRANSPORT, 95, "transport_fd_set: " - "transport %p (virtual %p) fd %d", t, - t->virtual, n)); - } - return max + 1; -} - -/* - * Build up a file descriptor set FDS with all the descriptors belonging to - * transport where messages are queued for transmittal. Return the number - * of file descriptors select(2) needs to check in order to cover the ones - * we setup in here. - */ -int -transport_pending_wfd_set(fd_set * fds) -{ - struct transport *t; - int n; - int max = -1; - - for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) { - 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: " - "transport %p (virtual %p) fd %d pending", t, - t->virtual, n)); - if (n > max) - max = n; - } - } - return max + 1; -} - -/* - * For each transport with a file descriptor in FDS, try to get an - * incoming message and start processing it. - */ -void -transport_handle_messages(fd_set *fds) -{ - struct transport *t; - - for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) { - if ((t->flags & TRANSPORT_LISTEN) && - (*t->vtbl->fd_isset)(t, fds)) { - (*t->virtual->vtbl->handle_message)(t); - (*t->vtbl->fd_set)(t, fds, 0); - } - } -} - -/* - * Send the first queued message on the transports found whose file - * descriptor is in FDS and has messages queued. Remove the fd bit from - * FDS as soon as one message has been sent on it so other transports - * sharing the socket won't get service without an intervening select - * call. Perhaps a fairness strategy should be implemented between - * such transports. Now early transports in the list will potentially - * be favoured to later ones sharing the file descriptor. - */ -void -transport_send_messages(fd_set * fds) -{ - struct transport *t, *next; - struct message *msg; - struct exchange *exchange; - struct timeval expiration; - int expiry, ok_to_drop_message; - - /* - * Reference all transports first so noone will disappear while in - * use. - */ - for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) - transport_reference(t->virtual); - - for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) { - if ((TAILQ_FIRST(&t->virtual->sendq) || - TAILQ_FIRST(&t->virtual->prio_sendq)) && - t->vtbl->fd_isset(t, fds)) { - /* Remove fd bit. */ - t->vtbl->fd_set(t, fds, 0); - - /* Prefer a message from the prioritized sendq. */ - if (TAILQ_FIRST(&t->virtual->prio_sendq)) { - msg = TAILQ_FIRST(&t->virtual->prio_sendq); - TAILQ_REMOVE(&t->virtual->prio_sendq, msg, - link); - } else { - msg = TAILQ_FIRST(&t->virtual->sendq); - TAILQ_REMOVE(&t->virtual->sendq, msg, link); - } - - msg->flags &= ~MSG_IN_TRANSIT; - exchange = msg->exchange; - exchange->in_transit = 0; - - /* - * We disregard the potential error message here, - * hoping that the retransmit will go better. - * XXX Consider a retry/fatal error discriminator. - */ - t->virtual->vtbl->send_message(msg, 0); - msg->xmits++; - - /* - * This piece of code has been proven to be quite - * delicate. Think twice for before altering. - * Here's an outline: - * - * If this message is not the one which finishes an - * exchange, check if we have reached the number of - * retransmit before queuing it up for another. - * - * If it is a finishing message we still may have to - * keep it around for an on-demand retransmit when - * seeing a duplicate of our peer's previous message. - * - */ - if ((msg->flags & MSG_LAST) == 0) { - if (msg->xmits > conf_get_num("General", - "retransmits", RETRANSMIT_DEFAULT)) { - log_print("transport_send_messages: " - "giving up on message %p, " - "exchange %s", msg, - exchange->name ? exchange->name : - "<unnamed>"); - /* Be more verbose here. */ - if (exchange->phase == 1) { - log_print( - "transport_send_messages: " - "either this message did " - "not reach the other " - "peer"); - if (exchange->initiator) - log_print("transport_send_messages: " - "or the response" - "message did not " - "reach us back"); - else - log_print("transport_send_messages: " - "or this is an " - "attempted IKE " - "scan"); - } - exchange->last_sent = 0; -#ifdef notyet - exchange_free(exchange); - exchange = 0; -#endif - } else { - gettimeofday(&expiration, 0); - - /* - * XXX Calculate from round trip - * timings and a backoff func. - */ - expiry = msg->xmits * 2 + 5; - expiration.tv_sec += expiry; - LOG_DBG((LOG_TRANSPORT, 30, - "transport_send_messages: " - "message %p scheduled for " - "retransmission %d in %d secs", - msg, msg->xmits, expiry)); - if (msg->retrans) - timer_remove_event(msg->retrans); - msg->retrans - = timer_add_event("message_send_expire", - (void (*) (void *)) message_send_expire, - msg, &expiration); - /* - * If we cannot retransmit, we - * cannot... - */ - exchange->last_sent = - msg->retrans ? msg : 0; - } - } else - exchange->last_sent = - exchange->last_received ? msg : 0; - - /* - * If this message is not referred to for later - * retransmission it will be ok for us to drop it - * after the post-send function. But as the post-send - * function may remove the exchange, we need to - * remember this fact here. - */ - ok_to_drop_message = exchange->last_sent == 0; - - /* - * If this is not a retransmit call post-send - * functions that allows parallel work to be done - * while the network and peer does their share of - * the job. Note that a post-send function may take - * away the exchange we belong to, but only if no - * retransmits are possible. - */ - if (msg->xmits == 1) - message_post_send(msg); - - if (ok_to_drop_message) - message_free(msg); - } - } - - for (t = LIST_FIRST(&transport_list); t; t = next) { - next = LIST_NEXT(t, link); - transport_release(t->virtual); - } -} - -/* - * Textual search after the transport method denoted by NAME, then create - * a transport connected to the peer with address ADDR, given in a transport- - * specific string format. - */ -struct transport * -transport_create(char *name, char *addr) -{ - struct transport_vtbl *method; - - for (method = LIST_FIRST(&transport_method_list); method; - method = LIST_NEXT(method, link)) - if (strcmp(method->name, name) == 0) - return (*method->create) (addr); - return 0; -} |