- stevesk@cvs.openbsd.org 2001/04/06 22:25:25
     [servconf.c]
     in addition to:
     ListenAddress host|ipv4_addr|ipv6_addr
     permit:
     ListenAddress [host|ipv4_addr|ipv6_addr]:port
     ListenAddress host|ipv4_addr:port
     sshd.8 updates coming.  ok markus@
diff --git a/servconf.c b/servconf.c
index 8094d34..4d5eb53 100644
--- a/servconf.c
+++ b/servconf.c
@@ -10,7 +10,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: servconf.c,v 1.73 2001/04/02 14:20:23 stevesk Exp $");
+RCSID("$OpenBSD: servconf.c,v 1.74 2001/04/06 22:25:25 stevesk Exp $");
 
 #ifdef KRB4
 #include <krb.h>
@@ -32,7 +32,8 @@
 #include "mac.h"
 
 /* add listen address */
-void add_listen_addr(ServerOptions *options, char *addr);
+void add_listen_addr(ServerOptions *options, char *addr, char *port);
+void add_one_listen_addr(ServerOptions *options, char *addr, u_short port);
 
 /* AF_UNSPEC or AF_INET or AF_INET6 */
 extern int IPv4or6;
@@ -114,7 +115,7 @@
 	if (options->num_ports == 0)
 		options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
 	if (options->listen_addrs == NULL)
-		add_listen_addr(options, NULL);
+		add_listen_addr(options, NULL, NULL);
 	if (options->pid_file == NULL)
 		options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
 	if (options->server_key_bits == -1)
@@ -306,30 +307,39 @@
  * add listen address
  */
 void
-add_listen_addr(ServerOptions *options, char *addr)
+add_listen_addr(ServerOptions *options, char *addr, char *port)
 {
-	struct addrinfo hints, *ai, *aitop;
-	char strport[NI_MAXSERV];
-	int gaierr;
 	int i;
 
 	if (options->num_ports == 0)
 		options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
-	for (i = 0; i < options->num_ports; i++) {
-		memset(&hints, 0, sizeof(hints));
-		hints.ai_family = IPv4or6;
-		hints.ai_socktype = SOCK_STREAM;
-		hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
-		snprintf(strport, sizeof strport, "%d", options->ports[i]);
-		if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
-			fatal("bad addr or host: %s (%s)",
-			    addr ? addr : "<NULL>",
-			    gai_strerror(gaierr));
-		for (ai = aitop; ai->ai_next; ai = ai->ai_next)
-			;
-		ai->ai_next = options->listen_addrs;
-		options->listen_addrs = aitop;
-	}
+	if (port == NULL)
+		for (i = 0; i < options->num_ports; i++)
+			add_one_listen_addr(options, addr, options->ports[i]);
+	else
+		add_one_listen_addr(options, addr, atoi(port));
+}
+
+void
+add_one_listen_addr(ServerOptions *options, char *addr, u_short port)
+{
+	struct addrinfo hints, *ai, *aitop;
+	char strport[NI_MAXSERV];
+	int gaierr;
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = IPv4or6;
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
+	snprintf(strport, sizeof strport, "%d", port);
+	if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
+		fatal("bad addr or host: %s (%s)",
+		    addr ? addr : "<NULL>",
+		    gai_strerror(gaierr));
+	for (ai = aitop; ai->ai_next; ai = ai->ai_next)
+		;
+	ai->ai_next = options->listen_addrs;
+	options->listen_addrs = aitop;
 }
 
 /* Reads the server configuration file. */
@@ -339,7 +349,7 @@
 {
 	FILE *f;
 	char line[1024];
-	char *cp, **charptr, *arg;
+	char *cp, **charptr, *arg, *p;
 	int linenum, *intptr, value;
 	int bad_options = 0;
 	ServerOpCodes opcode;
@@ -408,10 +418,34 @@
 
 		case sListenAddress:
 			arg = strdelim(&cp);
-			if (!arg || *arg == '\0')
+			if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0)
 				fatal("%s line %d: missing inet addr.",
 				    filename, linenum);
-			add_listen_addr(options, arg);
+			if (*arg == '[') {
+				if ((p = strchr(arg, ']')) == NULL)
+					fatal("%s line %d: bad ipv6 inet addr usage.",
+					    filename, linenum);
+				arg++;
+				memmove(p, p+1, strlen(p+1)+1);
+			} else if (((p = strchr(arg, ':')) == NULL) ||
+				    (strchr(p+1, ':') != NULL)) {
+				add_listen_addr(options, arg, NULL);
+				break;
+			}
+			if (*p == ':') {
+				p++;
+				if (*p == '\0')
+					fatal("%s line %d: bad inet addr:port usage.",
+					    filename, linenum);
+				else {
+					*(p-1) = '\0';
+					add_listen_addr(options, arg, p);
+				}
+			} else if (*p == '\0')
+				add_listen_addr(options, arg, NULL);
+			else
+				fatal("%s line %d: bad inet addr usage.",
+				    filename, linenum);
 			break;
 
 		case sHostKeyFile: