summaryrefslogtreecommitdiff
path: root/sbin/isakmpd/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/isakmpd/udp.c')
-rw-r--r--sbin/isakmpd/udp.c84
1 files changed, 71 insertions, 13 deletions
diff --git a/sbin/isakmpd/udp.c b/sbin/isakmpd/udp.c
index 2597d628ff6..c21596b71a4 100644
--- a/sbin/isakmpd/udp.c
+++ b/sbin/isakmpd/udp.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: udp.c,v 1.6 1998/12/22 02:25:15 niklas Exp $ */
-/* $EOM: udp.c,v 1.25 1998/12/22 02:23:42 niklas Exp $ */
+/* $OpenBSD: udp.c,v 1.7 1999/02/26 03:51:33 niklas Exp $ */
+/* $EOM: udp.c,v 1.30 1999/02/25 11:39:25 niklas Exp $ */
/*
* Copyright (c) 1998 Niklas Hallqvist. All rights reserved.
@@ -46,6 +46,8 @@
#include <string.h>
#include <unistd.h>
+#include "sysdep.h"
+
#include "conf.h"
#include "if.h"
#include "isakmp.h"
@@ -70,7 +72,7 @@ struct udp_transport {
static struct transport *udp_clone (struct udp_transport *,
struct sockaddr_in *);
static struct transport *udp_create (char *);
-static int udp_fd_set (struct transport *, fd_set *);
+static int udp_fd_set (struct transport *, fd_set *, int);
static int udp_fd_isset (struct transport *, fd_set *);
static void udp_handle_message (struct transport *);
static struct transport *udp_make (struct sockaddr_in *);
@@ -120,12 +122,24 @@ udp_make (struct sockaddr_in *laddr)
/* Make sure we don't get our traffic encrypted. */
sysdep_cleartext (s);
+ /*
+ * In order to have several bound specific address-port combinations
+ * with the same port SO_REUSEADDR is needed.
+ * If this is a wildcard socket and we are not listening there, but only
+ * sending from it make it is entirely reuseable with SO_REUSEPORT.
+ */
on = 1;
- /* XXX Is this redundant considering SO_REUSEPORT below? */
- if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof on) == -1)
+ if (setsockopt (s, SOL_SOCKET,
+ (laddr->sin_addr.s_addr == INADDR_ANY
+ && conf_get_str ("General", "Listen-on"))
+ ? SO_REUSEPORT : SO_REUSEADDR,
+ (void *)&on, sizeof on) == -1)
{
log_error ("udp_make: setsockopt (%d, %d, %d, %p, %d)", s, SOL_SOCKET,
- SO_REUSEADDR, &on, sizeof on);
+ (laddr->sin_addr.s_addr == INADDR_ANY
+ && conf_get_str ("General", "Listen-on"))
+ ? SO_REUSEPORT : SO_REUSEADDR,
+ &on, sizeof on);
goto err;
}
@@ -139,9 +153,8 @@ udp_make (struct sockaddr_in *laddr)
memset (&t->dst, 0, sizeof t->dst);
t->s = s;
- t->transport.flags |= TRANSPORT_LISTEN;
-
transport_add ((struct transport *)t);
+ t->transport.flags |= TRANSPORT_LISTEN;
return (struct transport *)t;
err:
@@ -164,7 +177,7 @@ udp_clone (struct udp_transport *u, struct sockaddr_in *raddr)
return 0;
u2 = (struct udp_transport *)t;
- memcpy (t, u, sizeof *u);
+ memcpy (u2, u, sizeof *u);
memcpy (&u2->dst, raddr, sizeof u2->dst);
t->flags &= ~TRANSPORT_LISTEN;
@@ -200,6 +213,10 @@ static void
udp_bind_if (struct ifreq *ifrp, void *arg)
{
in_port_t port = *(in_port_t *)arg;
+ in_addr_t if_addr = ((struct sockaddr_in *)&ifrp->ifr_addr)->sin_addr.s_addr;
+ struct conf_list *listen_on;
+ struct conf_list_node *address;
+ struct in_addr addr;
/*
* Well UDP is an internet protocol after all so drop other ifreqs.
@@ -209,8 +226,42 @@ udp_bind_if (struct ifreq *ifrp, void *arg)
|| ifrp->ifr_addr.sa_len != sizeof (struct sockaddr_in))
return;
+ /*
+ * If we are explicit about what addresses we can listen to, be sure
+ * to respect that option.
+ * XXX This is quite wasteful redoing the list-run for every interface,
+ * but who cares? This is not an operation that needs to be fast.
+ */
+ listen_on = conf_get_list ("General", "Listen-on");
+ if (listen_on)
+ {
+ for (address = TAILQ_FIRST (&listen_on->fields); address;
+ address = TAILQ_NEXT (address, link))
+ {
+ if (!inet_aton (address->field, &addr))
+ {
+ log_print ("udp_bind_if: invalid address %s in \"Listen-on\"",
+ address->field);
+ continue;
+ }
+
+ /* If found, take the easy way out. */
+ if (addr.s_addr == if_addr)
+ break;
+ }
+
+ /*
+ * If address is zero then we did not find the address among the ones
+ * we should listen to.
+ * XXX We do not discover if we do not find our listen addresses...
+ * Maybe this should be the other way round.
+ */
+ if (!address)
+ return;
+ }
+
/* XXX Deal with errors better. */
- udp_bind (((struct sockaddr_in *)&ifrp->ifr_addr)->sin_addr.s_addr, port);
+ udp_bind (if_addr, port);
}
/*
@@ -280,13 +331,16 @@ udp_init ()
if_map (udp_bind_if, &port);
/*
- * Bind to INADDR_ANY in case of new addresses popping up.
+ * If we don't bind to specific addresses via the Listen-on configuration
+ * option, bind to INADDR_ANY in case of new addresses popping up.
* XXX We should use packets coming in on this socket as a signal
* to reprobe for new interfaces.
*/
default_transport = udp_bind (INADDR_ANY, port);
if (!default_transport)
log_error ("udp_init: could not allocate default ISAKMP UDP port");
+ else if (conf_get_str ("General", "Listen-on"))
+ default_transport->flags &= ~TRANSPORT_LISTEN;
transport_method_add (&udp_transport_vtbl);
}
@@ -296,11 +350,15 @@ udp_init ()
* as the number of file descriptors to check.
*/
static int
-udp_fd_set (struct transport *t, fd_set *fds)
+udp_fd_set (struct transport *t, fd_set *fds, int bit)
{
struct udp_transport *u = (struct udp_transport *)t;
- FD_SET (u->s, fds);
+ if (bit)
+ FD_SET (u->s, fds);
+ else
+ FD_CLR (u->s, fds);
+
return u->s + 1;
}