diff options
-rw-r--r-- | usr.sbin/sasyncd/conf.y | 83 | ||||
-rw-r--r-- | usr.sbin/sasyncd/net.c | 405 | ||||
-rw-r--r-- | usr.sbin/sasyncd/sasyncd.conf.5 | 36 | ||||
-rw-r--r-- | usr.sbin/sasyncd/sasyncd.h | 3 |
4 files changed, 328 insertions, 199 deletions
diff --git a/usr.sbin/sasyncd/conf.y b/usr.sbin/sasyncd/conf.y index b9ddc7a965d..1ae00cf5879 100644 --- a/usr.sbin/sasyncd/conf.y +++ b/usr.sbin/sasyncd/conf.y @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.y,v 1.2 2005/05/22 20:35:48 ho Exp $ */ +/* $OpenBSD: conf.y,v 1.3 2005/05/24 19:18:10 ho Exp $ */ /* * Copyright (c) 2005 Håkan Olsson. All rights reserved. @@ -29,6 +29,7 @@ %{ #include <sys/types.h> #include <sys/stat.h> +#include <sys/socket.h> #include <ctype.h> #include <fcntl.h> #include <stdio.h> @@ -40,10 +41,10 @@ #include "net.h" /* Global configuration context. */ -struct cfgstate cfgstate; +struct cfgstate cfgstate; -struct syncpeer *peer; -int conflen = 0; +/* Local variables */ +int conflen = 0; char *confbuf, *confptr; int yyparse(void); @@ -57,9 +58,10 @@ void yyerror(const char *); } %token MODE CARP INTERFACE INTERVAL LISTEN ON PORT PEER SHAREDKEY -%token Y_SLAVE Y_MASTER +%token Y_SLAVE Y_MASTER INET INET6 %token <string> STRING -%token <val> VALUE +%token <val> VALUE +%type <val> af port interval mode %% /* Rules */ @@ -68,21 +70,37 @@ settings : /* empty */ | settings setting ; -setting : CARP INTERFACE STRING +af : /* empty */ { $$ = AF_UNSPEC; } + | INET { $$ = AF_INET; } + | INET6 { $$ = AF_INET6; } + ; + +port : /* empty */ { $$ = SASYNCD_DEFAULT_PORT; } + | PORT VALUE { $$ = $2; } + ; + +mode : MODE Y_MASTER { $$ = MASTER; } + | MODE Y_SLAVE { $$ = SLAVE; } + ; + +interval : /* empty */ { $$ = CARP_DEFAULT_INTERVAL; } + | INTERVAL VALUE { $$ = $2; } + ; + +setting : CARP INTERFACE STRING interval { if (cfgstate.carp_ifname) free(cfgstate.carp_ifname); cfgstate.carp_ifname = $3; - log_msg(2, "config: carp interface %s", $3); - } - | CARP INTERVAL VALUE - { - cfgstate.carp_check_interval = $3; - log_msg(2, "config: carp interval %d", $3); + cfgstate.carp_check_interval = $4; + log_msg(2, "config: carp interface %s interval %d", + $3, $4); } | PEER STRING { - int dup = 0; + struct syncpeer *peer; + int dup = 0; + for (peer = LIST_FIRST(&cfgstate.peerlist); peer; peer = LIST_NEXT(peer, link)) if (strcmp($2, peer->name) == 0) { @@ -104,34 +122,33 @@ setting : CARP INTERFACE STRING LIST_INSERT_HEAD(&cfgstate.peerlist, peer, link); log_msg(2, "config: add peer %s", peer->name); } - | LISTEN ON STRING + | LISTEN ON STRING af port { + char pstr[20]; + if (cfgstate.listen_on) free(cfgstate.listen_on); cfgstate.listen_on = $3; - log_msg(2, "config: listen on %s", cfgstate.listen_on); - } - | LISTEN PORT VALUE - { - cfgstate.listen_port = $3; + cfgstate.listen_family = $4; + cfgstate.listen_port = $5; if (cfgstate.listen_port < 1 || cfgstate.listen_port > 65534) { cfgstate.listen_port = SASYNCD_DEFAULT_PORT; log_msg(0, "config: bad port, listen-port " "reset to %u", SASYNCD_DEFAULT_PORT); - } else - log_msg(2, "config: listen port %u", - cfgstate.listen_port); - } - | MODE Y_MASTER - { - cfgstate.lockedstate = MASTER; - log_msg(2, "config: mode set to MASTER"); + } + if ($5 != SASYNCD_DEFAULT_PORT) + snprintf(pstr, sizeof pstr, "port %d",$5); + log_msg(2, "config: listen on %s %s%s", + cfgstate.listen_on, $4 == AF_INET6 ? "(IPv6) " : + ($4 == AF_INET ? "(IPv4) " : ""), + $5 != SASYNCD_DEFAULT_PORT ? pstr : ""); } - | MODE Y_SLAVE + | mode { - cfgstate.lockedstate = SLAVE; - log_msg(2, "config: mode set to SLAVE"); + cfgstate.lockedstate = $1; + log_msg(2, "config: mode set to %s", + $1 == MASTER ? "MASTER" : "SLAVE"); } | SHAREDKEY STRING { @@ -162,6 +179,8 @@ match(char *token) /* Sorted */ static const struct keyword keywords[] = { { "carp", CARP }, + { "inet", INET }, + { "inet6", INET6 }, { "interface", INTERFACE }, { "interval", INTERVAL }, { "listen", LISTEN }, @@ -209,7 +228,7 @@ yylex(void) yylval.val = v; return VALUE; } - + is_string: v = match(confptr); if (v == STRING) { diff --git a/usr.sbin/sasyncd/net.c b/usr.sbin/sasyncd/net.c index 71812e2735b..63b6b938038 100644 --- a/usr.sbin/sasyncd/net.c +++ b/usr.sbin/sasyncd/net.c @@ -1,4 +1,4 @@ -/* $OpenBSD: net.c,v 1.5 2005/05/24 02:35:39 ho Exp $ */ +/* $OpenBSD: net.c,v 1.6 2005/05/24 19:18:11 ho Exp $ */ /* * Copyright (c) 2005 Håkan Olsson. All rights reserved. @@ -29,7 +29,6 @@ * This code was written under funding by Multicom Security AB. */ - #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> @@ -61,7 +60,7 @@ struct qmsg { struct msg *msg; }; -int listen_socket; +int *listeners; AES_KEY aes_key[2]; #define AES_IV_LEN AES_BLOCK_SIZE @@ -88,7 +87,7 @@ dump_buf(int lvl, u_int8_t *b, u_int32_t len, char *title) blen = 2 * (len + len / 36) + 3 + (title ? strlen(title) : sizeof def); if (!(buf = (u_int8_t *)calloc(1, blen))) return; - + snprintf(buf, blen, "%s\n ", title ? title : def); off = strlen(buf); for (i = 0; i < len; i++, off+=2) { @@ -102,69 +101,193 @@ dump_buf(int lvl, u_int8_t *b, u_int32_t len, char *title) free(buf); } -int -net_init(void) +/* Add a listening socket. */ +static int +net_add_listener(struct sockaddr *sa) { - struct sockaddr_storage sa_storage; - struct sockaddr *sa = (struct sockaddr *)&sa_storage; - struct syncpeer *p; - char host[NI_MAXHOST], port[NI_MAXSERV]; - int r; + char host[NI_MAXHOST], port[NI_MAXSERV]; + int r, s; - /* The shared key needs to be 128, 192 or 256 bits */ - r = strlen(cfgstate.sharedkey) << 3; - if (r != 128 && r != 192 && r != 256) { - fprintf(stderr, "Bad shared key length (%d bits), " - "should be 128, 192 or 256\n", r); + s = socket(sa->sa_family, SOCK_STREAM, 0); + if (s < 0) { + perror("net_add_listener: socket()"); + close(s); return -1; } - - if (AES_set_encrypt_key(cfgstate.sharedkey, r, &aes_key[0]) || - AES_set_decrypt_key(cfgstate.sharedkey, r, &aes_key[1])) { - fprintf(stderr, "Bad AES shared key\n"); + + r = 1; + if (setsockopt(s, SOL_SOCKET, + cfgstate.listen_on ? SO_REUSEADDR : SO_REUSEPORT, (void *)&r, + sizeof r)) { + perror("net_add_listener: setsockopt()"); + close(s); return -1; } - /* Setup listening socket. */ + if (bind(s, sa, sa->sa_family == AF_INET ? sizeof(struct sockaddr_in) : + sizeof (struct sockaddr_in6))) { + perror("net_add_listener: bind()"); + close(s); + return -1; + } + + if (listen(s, 3)) { + perror("net_add_listener: listen()"); + close(s); + return -1; + } + + if (getnameinfo(sa, sa->sa_len, host, sizeof host, port, sizeof port, + NI_NUMERICHOST | NI_NUMERICSERV)) + log_msg(2, "listening on port %u fd %d", cfgstate.listen_port, + s); + else + log_msg(2, "listening on %s port %s fd %d", host, port, s); + + return s; +} + +/* Allocate and fill in listeners array. */ +static int +net_setup_listeners(void) +{ + struct sockaddr_storage sa_storage; + struct sockaddr *sa = (struct sockaddr *)&sa_storage; + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; + struct ifaddrs *ifap = 0, *ifa; + int i, count; + + /* Setup listening sockets. */ memset(&sa_storage, 0, sizeof sa_storage); - if (net_set_sa(sa, cfgstate.listen_on, cfgstate.listen_port)) { - log_msg(0, "net_init: could not find listen address (%s)", - cfgstate.listen_on); + if (net_set_sa(sa, cfgstate.listen_on, cfgstate.listen_port) == 0) { + listeners = (int *)calloc(2, sizeof(int)); + if (!listeners) { + perror("net_setup_listeners: calloc()"); + return -1; + } + listeners[1] = -1; + listeners[0] = net_add_listener(sa); + if (listeners[0] == -1) { + log_msg(0, "net_setup_listeners: could not find " + "listen address (%s)", cfgstate.listen_on); + goto errout; + } + return 0; + } + + /* + * If net_set_sa() failed, cfgstate.listen_on is probably an + * interface name, so we should listen on all it's addresses. + */ + + if (getifaddrs(&ifap) != 0) { + perror("net_setup_listeners: getifaddrs()"); return -1; } - listen_socket = socket(sa->sa_family, SOCK_STREAM, 0); - if (listen_socket < 0) { - perror("socket()"); - close(listen_socket); + /* How many addresses matches? */ + for (count = 0, ifa = ifap; ifa; ifa = ifa->ifa_next) { + if (!ifa->ifa_name || !ifa->ifa_addr || + (ifa->ifa_addr->sa_family != AF_INET && + ifa->ifa_addr->sa_family != AF_INET6)) + continue; + if (cfgstate.listen_family && + cfgstate.listen_family != ifa->ifa_addr->sa_family) + continue; + if (strcmp(ifa->ifa_name, cfgstate.listen_on) != 0) + continue; + count++; + } + + if (!count) { + log_msg(0, "net_setup_listeners: no listeners found for %s", + cfgstate.listen_on); return -1; } - r = 1; - if (setsockopt(listen_socket, SOL_SOCKET, - cfgstate.listen_on ? SO_REUSEADDR : SO_REUSEPORT, (void *)&r, - sizeof r)) { - perror("setsockopt()"); - close(listen_socket); + + /* Allocate one extra slot and set to -1, marking end of array. */ + listeners = (int *)calloc(count + 1, sizeof(int)); + if (!listeners) { + perror("net_setup_listeners: calloc()"); return -1; } - if (bind(listen_socket, sa, sizeof(struct sockaddr_in))) { - perror("bind()"); - close(listen_socket); + for (i = 0; i <= count; i++) + listeners[i] = -1; + + /* Create listening sockets */ + for (count = 0, ifa = ifap; ifa; ifa = ifa->ifa_next) { + if (!ifa->ifa_name || !ifa->ifa_addr || + (ifa->ifa_addr->sa_family != AF_INET && + ifa->ifa_addr->sa_family != AF_INET6)) + continue; + if (cfgstate.listen_family && + cfgstate.listen_family != ifa->ifa_addr->sa_family) + continue; + if (strcmp(ifa->ifa_name, cfgstate.listen_on) != 0) + continue; + + memset(&sa_storage, 0, sizeof sa_storage); + sa->sa_family = ifa->ifa_addr->sa_family; + switch (sa->sa_family) { + case AF_INET: + sin->sin_port = htons(cfgstate.listen_port); + sin->sin_len = sizeof *sin; + memcpy(&sin->sin_addr, + &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, + sizeof sin->sin_addr); + break; + case AF_INET6: + sin6->sin6_port = htons(cfgstate.listen_port); + sin6->sin6_len = sizeof *sin6; + memcpy(&sin6->sin6_addr, + &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, + sizeof sin6->sin6_addr); + break; + } + + listeners[count] = net_add_listener(sa); + if (listeners[count] == -1) { + log_msg(4, "net_setup_listeners(setup): failed to " + "add listener, count = %d", count); + goto errout; + } + count++; + } + freeifaddrs(ifap); + return 0; + + errout: + if (ifap) + freeifaddrs(ifap); + for (i = 0; listeners[i] != -1; i++) + close(listeners[i]); + free(listeners); + return -1; +} + +int +net_init(void) +{ + struct syncpeer *p; + int r; + + /* The shared key needs to be 128, 192 or 256 bits */ + r = strlen(cfgstate.sharedkey) << 3; + if (r != 128 && r != 192 && r != 256) { + fprintf(stderr, "Bad shared key length (%d bits), " + "should be 128, 192 or 256\n", r); return -1; } - if (listen(listen_socket, 10)) { - perror("listen()"); - close(listen_socket); + + if (AES_set_encrypt_key(cfgstate.sharedkey, r, &aes_key[0]) || + AES_set_decrypt_key(cfgstate.sharedkey, r, &aes_key[1])) { + fprintf(stderr, "Bad AES shared key\n"); return -1; } - if (getnameinfo(sa, sa->sa_len, host, sizeof host, port, sizeof port, - NI_NUMERICHOST | NI_NUMERICSERV)) - log_msg(2, "listening on port %u fd %d", cfgstate.listen_port, - listen_socket); - else - log_msg(2, "listening on %s port %s fd %d", host, port, - listen_socket); + if (net_setup_listeners()) + return -1; for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) { p->socket = -1; @@ -185,7 +308,7 @@ net_enqueue(struct syncpeer *p, struct msg *m) qm = (struct qmsg *)malloc(sizeof *qm); if (!qm) { - log_err("malloc()"); + log_err("net_enqueue: malloc()"); return; } @@ -214,7 +337,7 @@ net_queue(struct syncpeer *p0, u_int32_t msgtype, u_int8_t *buf, u_int32_t len) m = (struct msg *)calloc(1, sizeof *m); if (!m) { - log_err("calloc()"); + log_err("net_queue: calloc()"); free(buf); return -1; } @@ -323,7 +446,7 @@ int net_set_rfds(fd_set *fds) { struct syncpeer *p; - int max_fd = -1; + int i, max_fd = -1; for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) { if (p->socket > -1) @@ -331,73 +454,82 @@ net_set_rfds(fd_set *fds) if (p->socket > max_fd) max_fd = p->socket; } - FD_SET(listen_socket, fds); - if (listen_socket > max_fd) - max_fd = listen_socket; + for (i = 0; listeners[i] != -1; i++) { + FD_SET(listeners[i], fds); + if (listeners[i] > max_fd) + max_fd = listeners[i]; + } return max_fd + 1; } +static void +net_accept(int accept_socket) +{ + struct sockaddr_storage sa_storage, sa_storage2; + struct sockaddr *sa = (struct sockaddr *)&sa_storage; + struct sockaddr *sa2 = (struct sockaddr *)&sa_storage2; + struct sockaddr_in *sin, *sin2; + struct sockaddr_in6 *sin6, *sin62; + struct syncpeer *p; + socklen_t socklen; + int s, found; + + /* Accept a new incoming connection */ + socklen = sizeof sa_storage; + memset(&sa_storage, 0, socklen); + memset(&sa_storage2, 0, socklen); + s = accept(accept_socket, sa, &socklen); + if (s > -1) { + /* Setup the syncpeer structure */ + found = 0; + for (p = LIST_FIRST(&cfgstate.peerlist); p && !found; + p = LIST_NEXT(p, link)) { + + /* Match? */ + if (net_set_sa(sa2, p->name, 0)) + continue; + if (sa->sa_family != sa2->sa_family) + continue; + if (sa->sa_family == AF_INET) { + sin = (struct sockaddr_in *)sa; + sin2 = (struct sockaddr_in *)sa2; + if (memcmp(&sin->sin_addr, &sin2->sin_addr, + sizeof(struct in_addr))) + continue; + } else { + sin6 = (struct sockaddr_in6 *)sa; + sin62 = (struct sockaddr_in6 *)sa2; + if (memcmp(&sin6->sin6_addr, &sin62->sin6_addr, + sizeof(struct in6_addr))) + continue; + } + /* Match! */ + found++; + p->socket = s; + log_msg(1, "net: peer \"%s\" connected", p->name); + if (cfgstate.runstate == MASTER) + timer_add("pfkey_snap", 2, pfkey_snapshot, p); + } + if (!found) { + log_msg(1, "net: found no matching peer for accepted " + "socket, closing."); + close(s); + } + } else + log_err("net: accept()"); +} + void net_handle_messages(fd_set *fds) { - struct sockaddr_storage sa_storage, sa_storage2; - struct sockaddr *sa = (struct sockaddr *)&sa_storage; - struct sockaddr *sa2 = (struct sockaddr *)&sa_storage2; - socklen_t socklen; struct syncpeer *p; u_int8_t *msg; u_int32_t msgtype, msglen; - int newsock, found; - - if (FD_ISSET(listen_socket, fds)) { - /* Accept a new incoming connection */ - socklen = sizeof sa_storage; - newsock = accept(listen_socket, sa, &socklen); - if (newsock > -1) { - /* Setup the syncpeer structure */ - found = 0; - for (p = LIST_FIRST(&cfgstate.peerlist); p && !found; - p = LIST_NEXT(p, link)) { - struct sockaddr_in *sin, *sin2; - struct sockaddr_in6 *sin6, *sin62; - - /* Match? */ - if (net_set_sa(sa2, p->name, 0)) - continue; - if (sa->sa_family != sa2->sa_family) - continue; - if (sa->sa_family == AF_INET) { - sin = (struct sockaddr_in *)sa; - sin2 = (struct sockaddr_in *)sa2; - if (memcmp(&sin->sin_addr, - &sin2->sin_addr, - sizeof(struct in_addr))) - continue; - } else { - sin6 = (struct sockaddr_in6 *)sa; - sin62 = (struct sockaddr_in6 *)sa2; - if (memcmp(&sin6->sin6_addr, - &sin62->sin6_addr, - sizeof(struct in6_addr))) - continue; - } - /* Match! */ - found++; - p->socket = newsock; - log_msg(1, "net: peer \"%s\" connected", - p->name); - if (cfgstate.runstate == MASTER) - timer_add("pfkey_snapshot", 2, - pfkey_snapshot, p); - } - if (!found) { - log_msg(1, "net: found no matching peer for " - "accepted socket, closing."); - close(newsock); - } - } else - log_err("accept()"); - } + int i; + + for (i = 0; listeners[i] != -1; i++) + if (FD_ISSET(listeners[i], fds)) + net_accept(listeners[i]); for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) { if (p->socket < 0 || !FD_ISSET(p->socket, fds)) @@ -500,6 +632,7 @@ net_shutdown(void) struct syncpeer *p; struct qmsg *qm; struct msg *m; + int i; while ((p = LIST_FIRST(&cfgstate.peerlist))) { while ((qm = SIMPLEQ_FIRST(&p->msgs))) { @@ -518,8 +651,12 @@ net_shutdown(void) free(p); } - if (listen_socket > -1) - close(listen_socket); + if (listeners) { + for (i = 0; listeners[i] != -1; i++) + close(listeners[i]); + free(listeners); + listeners = 0; + } } /* @@ -541,7 +678,7 @@ net_read(struct syncpeer *p, u_int32_t *msgtype, u_int32_t *msglen) net_disconnect_peer(p); return NULL; } - + blob_len = ntohl(v); if (blob_len < sizeof hash + AES_IV_LEN + 2 * sizeof(u_int32_t)) return NULL; @@ -616,7 +753,6 @@ net_set_sa(struct sockaddr *sa, char *name, in_port_t port) { struct sockaddr_in *sin = (struct sockaddr_in *)sa; struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; - struct ifaddrs *ifap, *ifa; if (!name) { /* XXX Assume IPv4 */ @@ -632,7 +768,7 @@ net_set_sa(struct sockaddr *sa, char *name, in_port_t port) sin->sin_len = sizeof *sin; return 0; } - + if (inet_pton(AF_INET6, name, &sin6->sin6_addr) == 1) { sa->sa_family = AF_INET6; sin6->sin6_port = htons(port); @@ -640,47 +776,8 @@ net_set_sa(struct sockaddr *sa, char *name, in_port_t port) return 0; } - /* inet_pton failed. fail here if name is not cfgstate.listen_on */ - if (strcmp(cfgstate.listen_on, name) != 0) - return -1; - - /* Is cfgstate.listen_on the name of one our interfaces? */ - if (getifaddrs(&ifap) != 0) { - perror("getifaddrs()"); - return -1; - } - sa->sa_family = AF_UNSPEC; - for (ifa = ifap; ifa && sa->sa_family == AF_UNSPEC; - ifa = ifa->ifa_next) { - if (!ifa->ifa_name || !ifa->ifa_addr) - continue; - if (strcmp(ifa->ifa_name, name) != 0) - continue; - - switch (ifa->ifa_addr->sa_family) { - case AF_INET: - sa->sa_family = AF_INET; - sin->sin_port = htons(port); - sin->sin_len = sizeof *sin; - memcpy(&sin->sin_addr, - &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, - sizeof sin->sin_addr); - break; - - case AF_INET6: - sa->sa_family = AF_INET6; - sin6->sin6_port = htons(port); - sin6->sin6_len = sizeof *sin6; - memcpy(&sin6->sin6_addr, - &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, - sizeof sin6->sin6_addr); - break; - } - } - freeifaddrs(ifap); - return sa->sa_family == AF_UNSPEC ? -1 : 0; + return -1; } - static void got_sigalrm(int s) @@ -745,7 +842,5 @@ static void net_check_peers(void *arg) { net_connect(); - (void)timer_add("peer recheck", 600, net_check_peers, 0); } - diff --git a/usr.sbin/sasyncd/sasyncd.conf.5 b/usr.sbin/sasyncd/sasyncd.conf.5 index d12dcc9d9f4..3cc141d45ec 100644 --- a/usr.sbin/sasyncd/sasyncd.conf.5 +++ b/usr.sbin/sasyncd/sasyncd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sasyncd.conf.5,v 1.5 2005/05/23 20:45:41 jmc Exp $ +.\" $OpenBSD: sasyncd.conf.5,v 1.6 2005/05/24 19:18:11 ho Exp $ .\" .\" Copyright (c) 2005 Håkan Olsson. All rights reserved. .\" @@ -58,26 +58,40 @@ pseudo user and be readable only by this owner, e.g.\& .Pp The following configuration settings are understood: .Bl -tag -width Ds -.It Ic carp interface Ar interface +.It Xo +.Ic carp interface +.Ar interface Op Ic interval Ar seconds +.Xc Specify which .Xr carp 4 interface .Nm sasyncd should track master/slave state on. -.It Ic carp interval Ar seconds -Specify how often the daemon should check the above interface for -state changes. +Optionally state how often the daemon should check the interface +for state changes. Defaults to once every 10 seconds. -.It Ic listen on Ar address +.It Xo +.Ic listen on Ar address +.Op Ar family +.Op Ic port Ar port +.Xc Specify a local IP address, hostname, or interface the .Xr sasyncd 8 daemon should listen on. -The default is to listen on all local addresses. -.It Ic listen port Ar port -Specify a local TCP port the +The default is to listen on all local addresses. +When using an interface name, +.Ar family +may be given as +.Dq inet +or +.Dq inet6 +to only bind using the specified address family. +Finally, +.Ar port +can be used to specify which TCP port .Xr sasyncd 8 -daemon should listen on. -The default is to listen on port 500. +should listen to. +The default is to listen to port 500. .It Ic mode master | slave Force the daemon to run as master or slave. Normally only intended for debugging use. diff --git a/usr.sbin/sasyncd/sasyncd.h b/usr.sbin/sasyncd/sasyncd.h index b5f21f01d1f..7409cfff715 100644 --- a/usr.sbin/sasyncd/sasyncd.h +++ b/usr.sbin/sasyncd/sasyncd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sasyncd.h,v 1.5 2005/05/24 02:35:39 ho Exp $ */ +/* $OpenBSD: sasyncd.h,v 1.6 2005/05/24 19:18:11 ho Exp $ */ /* * Copyright (c) 2005 Håkan Olsson. All rights reserved. @@ -53,6 +53,7 @@ struct cfgstate { char *listen_on; in_port_t listen_port; + sa_family_t listen_family; LIST_HEAD(, syncpeer) peerlist; }; |