11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: misc.c,v 1.85 2011/03/29 18:54:17 stevesk Exp $ */
21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2000 Markus Friedl.  All rights reserved.
41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2005,2006 Damien Miller.  All rights reserved.
51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Redistribution and use in source and binary forms, with or without
71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * modification, are permitted provided that the following conditions
81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * are met:
91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 1. Redistributions of source code must retain the above copyright
101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    notice, this list of conditions and the following disclaimer.
111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 2. Redistributions in binary form must reproduce the above copyright
121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    notice, this list of conditions and the following disclaimer in the
131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    documentation and/or other materials provided with the distribution.
141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h"
281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h>
301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/ioctl.h>
311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/socket.h>
321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/param.h>
331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h>
351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdio.h>
361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdlib.h>
371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h>
381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <time.h>
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <unistd.h>
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <netinet/in.h>
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <netinet/in_systm.h>
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <netinet/ip.h>
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <netinet/tcp.h>
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <errno.h>
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <fcntl.h>
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <netdb.h>
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_PATHS_H
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <paths.h>
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <pwd.h>
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef SSH_TUN_OPENBSD
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <net/if.h>
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h"
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "misc.h"
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h"
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh.h"
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* remove newline at end of string */
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchar *
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchop(char *s)
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *t = s;
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (*t) {
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*t == '\n' || *t == '\r') {
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*t = '\0';
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return s;
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		t++;
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return s;
751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* set/unset filedescriptor to non-blocking */
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodset_nonblock(int fd)
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int val;
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	val = fcntl(fd, F_GETFL, 0);
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (val < 0) {
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (val & O_NONBLOCK) {
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug3("fd %d is O_NONBLOCK", fd);
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (0);
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("fd %d setting O_NONBLOCK", fd);
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	val |= O_NONBLOCK;
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (fcntl(fd, F_SETFL, val) == -1) {
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd,
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    strerror(errno));
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (0);
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodunset_nonblock(int fd)
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int val;
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	val = fcntl(fd, F_GETFL, 0);
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (val < 0) {
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!(val & O_NONBLOCK)) {
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug3("fd %d is not O_NONBLOCK", fd);
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (0);
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("fd %d clearing O_NONBLOCK", fd);
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	val &= ~O_NONBLOCK;
1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (fcntl(fd, F_SETFL, val) == -1) {
1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s",
1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    fd, strerror(errno));
1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (0);
1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodconst char *
1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodssh_gai_strerror(int gaierr)
1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (gaierr == EAI_SYSTEM)
1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return strerror(errno);
1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return gai_strerror(gaierr);
1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* disable nagle on socket */
1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodset_nodelay(int fd)
1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int opt;
1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	socklen_t optlen;
1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	optlen = sizeof opt;
1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) {
1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("getsockopt TCP_NODELAY: %.100s", strerror(errno));
1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (opt == 1) {
1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug2("fd %d is TCP_NODELAY", fd);
1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	opt = 1;
1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("fd %d setting TCP_NODELAY", fd);
1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1)
1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Characters considered whitespace in strsep calls. */
1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define WHITESPACE " \t\r\n"
1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define QUOTE	"\""
1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* return next token in configuration line */
1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchar *
1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstrdelim(char **s)
1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *old;
1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int wspace = 0;
1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*s == NULL)
1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NULL;
1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	old = *s;
1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*s = strpbrk(*s, WHITESPACE QUOTE "=");
1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*s == NULL)
1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (old);
1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*s[0] == '\"') {
1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		memmove(*s, *s + 1, strlen(*s)); /* move nul too */
1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Find matching quote */
1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((*s = strpbrk(*s, QUOTE)) == NULL) {
1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return (NULL);		/* no matching quote */
1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*s[0] = '\0';
1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*s += strspn(*s + 1, WHITESPACE) + 1;
1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return (old);
1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Allow only one '=' to be skipped */
1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*s[0] == '=')
1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		wspace = 1;
1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*s[0] = '\0';
1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Skip any extra whitespace after first token */
1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*s += strspn(*s + 1, WHITESPACE) + 1;
1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*s[0] == '=' && !wspace)
1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*s += strspn(*s + 1, WHITESPACE) + 1;
1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (old);
2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstruct passwd *
2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpwcopy(struct passwd *pw)
2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct passwd *copy = xcalloc(1, sizeof(*copy));
2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	copy->pw_name = xstrdup(pw->pw_name);
208d62cf1eb84c245692d63a45c9ef71583bd2bfda1Mike Lockwood	copy->pw_passwd = pw->pw_passwd ? xstrdup(pw->pw_passwd) : NULL;
209d62cf1eb84c245692d63a45c9ef71583bd2bfda1Mike Lockwood#ifdef HAVE_PW_GECOS_IN_PASSWD
2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	copy->pw_gecos = xstrdup(pw->pw_gecos);
211d62cf1eb84c245692d63a45c9ef71583bd2bfda1Mike Lockwood#endif
2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	copy->pw_uid = pw->pw_uid;
2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	copy->pw_gid = pw->pw_gid;
2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_PW_EXPIRE_IN_PASSWD
2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	copy->pw_expire = pw->pw_expire;
2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_PW_CHANGE_IN_PASSWD
2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	copy->pw_change = pw->pw_change;
2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_PW_CLASS_IN_PASSWD
2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	copy->pw_class = xstrdup(pw->pw_class);
2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	copy->pw_dir = xstrdup(pw->pw_dir);
2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	copy->pw_shell = xstrdup(pw->pw_shell);
2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return copy;
2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Convert ASCII string to TCP/IP port number.
2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Port must be >=0 and <=65535.
2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Return -1 if invalid.
2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooda2port(const char *s)
2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	long long port;
2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *errstr;
2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	port = strtonum(s, 0, 65535, &errstr);
2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (errstr != NULL)
2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (int)port;
2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooda2tun(const char *s, int *remote)
2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *errstr = NULL;
2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *sp, *ep;
2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int tun;
2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (remote != NULL) {
2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*remote = SSH_TUNID_ANY;
2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sp = xstrdup(s);
2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((ep = strchr(sp, ':')) == NULL) {
2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(sp);
2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return (a2tun(s, NULL));
2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ep[0] = '\0'; ep++;
2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*remote = a2tun(ep, NULL);
2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		tun = a2tun(sp, NULL);
2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(sp);
2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (*remote == SSH_TUNID_ERR ? *remote : tun);
2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (strcasecmp(s, "any") == 0)
2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (SSH_TUNID_ANY);
2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr);
2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (errstr != NULL)
2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (SSH_TUNID_ERR);
2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (tun);
2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define SECONDS		1
2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define MINUTES		(SECONDS * 60)
2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define HOURS		(MINUTES * 60)
2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DAYS		(HOURS * 24)
2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define WEEKS		(DAYS * 7)
2811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
2831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Convert a time string into seconds; format is
2841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * a sequence of:
2851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *      time[qualifier]
2861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
2871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Valid time qualifiers are:
2881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *      <none>  seconds
2891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *      s|S     seconds
2901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *      m|M     minutes
2911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *      h|H     hours
2921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *      d|D     days
2931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *      w|W     weeks
2941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
2951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Examples:
2961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *      90m     90 minutes
2971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *      1h30m   90 minutes
2981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *      2d      2 days
2991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *      1w      1 week
3001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
3011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Return -1 if time string is invalid.
3021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
3031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodlong
3041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodconvtime(const char *s)
3051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	long total, secs;
3071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *p;
3081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *endp;
3091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	errno = 0;
3111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	total = 0;
3121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	p = s;
3131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (p == NULL || *p == '\0')
3151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
3161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (*p) {
3181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		secs = strtol(p, &endp, 10);
3191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (p == endp ||
3201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) ||
3211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    secs < 0)
3221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
3231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch (*endp++) {
3251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case '\0':
3261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			endp--;
3271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
3281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 's':
3291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 'S':
3301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
3311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 'm':
3321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 'M':
3331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			secs *= MINUTES;
3341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
3351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 'h':
3361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 'H':
3371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			secs *= HOURS;
3381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
3391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 'd':
3401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 'D':
3411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			secs *= DAYS;
3421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
3431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 'w':
3441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 'W':
3451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			secs *= WEEKS;
3461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
3471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		default:
3481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
3491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
3501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		total += secs;
3511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (total < 0)
3521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
3531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		p = endp;
3541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return total;
3571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
3581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
3601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Returns a standardized host+port identifier string.
3611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Caller must free returned string.
3621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
3631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchar *
3641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodput_host_port(const char *host, u_short port)
3651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *hoststr;
3671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (port == 0 || port == SSH_DEFAULT_PORT)
3691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return(xstrdup(host));
3701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (asprintf(&hoststr, "[%s]:%d", host, (int)port) < 0)
3711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("put_host_port: asprintf: %s", strerror(errno));
3721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("put_host_port: %s", hoststr);
3731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return hoststr;
3741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
3751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
3771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Search for next delimiter between hostnames/addresses and ports.
3781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Argument may be modified (for termination).
3791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Returns *cp if parsing succeeds.
3801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * *cp is set to the start of the next delimiter, if one was found.
3811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * If this is the last field, *cp is set to NULL.
3821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
3831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchar *
3841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodhpdelim(char **cp)
3851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *s, *old;
3871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (cp == NULL || *cp == NULL)
3891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NULL;
3901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	old = s = *cp;
3921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*s == '[') {
3931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((s = strchr(s, ']')) == NULL)
3941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return NULL;
3951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		else
3961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			s++;
3971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if ((s = strpbrk(s, ":/")) == NULL)
3981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s = *cp + strlen(*cp); /* skip to end (see first case below) */
3991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (*s) {
4011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case '\0':
4021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*cp = NULL;	/* no more fields*/
4031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
4041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case ':':
4061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case '/':
4071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*s = '\0';	/* terminate */
4081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*cp = s + 1;
4091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
4101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
4121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NULL;
4131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return old;
4161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchar *
4191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcleanhostname(char *host)
4201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*host == '[' && host[strlen(host) - 1] == ']') {
4221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		host[strlen(host) - 1] = '\0';
4231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (host + 1);
4241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else
4251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return host;
4261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchar *
4291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcolon(char *cp)
4301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int flag = 0;
4321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*cp == ':')		/* Leading colon is part of file name. */
4341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NULL;
4351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*cp == '[')
4361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		flag = 1;
4371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (; *cp; ++cp) {
4391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*cp == '@' && *(cp+1) == '[')
4401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			flag = 1;
4411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*cp == ']' && *(cp+1) == ':' && flag)
4421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return (cp+1);
4431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*cp == ':' && !flag)
4441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return (cp);
4451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*cp == '/')
4461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return NULL;
4471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return NULL;
4491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* function to assist building execv() arguments */
4521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
4531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodaddargs(arglist *args, char *fmt, ...)
4541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	va_list ap;
4561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *cp;
4571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int nalloc;
4581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int r;
4591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	va_start(ap, fmt);
4611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	r = vasprintf(&cp, fmt, ap);
4621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	va_end(ap);
4631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (r == -1)
4641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("addargs: argument too long");
4651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	nalloc = args->nalloc;
4671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (args->list == NULL) {
4681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		nalloc = 32;
4691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		args->num = 0;
4701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (args->num+2 >= nalloc)
4711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		nalloc *= 2;
4721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	args->list = xrealloc(args->list, nalloc, sizeof(char *));
4741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	args->nalloc = nalloc;
4751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	args->list[args->num++] = cp;
4761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	args->list[args->num] = NULL;
4771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
4801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodreplacearg(arglist *args, u_int which, char *fmt, ...)
4811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	va_list ap;
4831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *cp;
4841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int r;
4851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	va_start(ap, fmt);
4871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	r = vasprintf(&cp, fmt, ap);
4881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	va_end(ap);
4891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (r == -1)
4901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("replacearg: argument too long");
4911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (which >= args->num)
4931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("replacearg: tried to replace invalid arg %d >= %d",
4941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    which, args->num);
4951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(args->list[which]);
4961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	args->list[which] = cp;
4971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
5001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodfreeargs(arglist *args)
5011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
5021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i;
5031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (args->list != NULL) {
5051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (i = 0; i < args->num; i++)
5061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(args->list[i]);
5071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(args->list);
5081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		args->nalloc = args->num = 0;
5091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		args->list = NULL;
5101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
5121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
5141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Expands tildes in the file name.  Returns data allocated by xmalloc.
5151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Warning: this calls getpw*.
5161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
5171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchar *
5181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodtilde_expand_filename(const char *filename, uid_t uid)
5191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
5201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *path;
5211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char user[128], ret[MAXPATHLEN];
5221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct passwd *pw;
5231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int len, slash;
5241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*filename != '~')
5261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (xstrdup(filename));
5271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	filename++;
5281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	path = strchr(filename, '/');
5301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (path != NULL && path > filename) {		/* ~user/path */
5311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		slash = path - filename;
5321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (slash > sizeof(user) - 1)
5331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("tilde_expand_filename: ~username too long");
5341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		memcpy(user, filename, slash);
5351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		user[slash] = '\0';
5361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((pw = getpwnam(user)) == NULL)
5371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("tilde_expand_filename: No such user %s", user);
5381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if ((pw = getpwuid(uid)) == NULL)	/* ~/path */
5391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("tilde_expand_filename: No such uid %ld", (long)uid);
5401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (strlcpy(ret, pw->pw_dir, sizeof(ret)) >= sizeof(ret))
5421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("tilde_expand_filename: Path too long");
5431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Make sure directory has a trailing '/' */
5451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	len = strlen(pw->pw_dir);
5461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((len == 0 || pw->pw_dir[len - 1] != '/') &&
5471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    strlcat(ret, "/", sizeof(ret)) >= sizeof(ret))
5481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("tilde_expand_filename: Path too long");
5491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Skip leading '/' from specified path */
5511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (path != NULL)
5521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		filename = path + 1;
5531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (strlcat(ret, filename, sizeof(ret)) >= sizeof(ret))
5541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("tilde_expand_filename: Path too long");
5551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (xstrdup(ret));
5571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
5581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
5601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Expand a string with a set of %[char] escapes. A number of escapes may be
5611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * specified as (char *escape_chars, char *replacement) pairs. The list must
5621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * be terminated by a NULL escape_char. Returns replaced string in memory
5631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * allocated by xmalloc.
5641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
5651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchar *
5661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpercent_expand(const char *string, ...)
5671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
5681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define EXPAND_MAX_KEYS	16
5691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int num_keys, i, j;
5701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct {
5711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		const char *key;
5721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		const char *repl;
5731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} keys[EXPAND_MAX_KEYS];
5741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char buf[4096];
5751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	va_list ap;
5761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Gather keys */
5781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	va_start(ap, string);
5791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) {
5801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		keys[num_keys].key = va_arg(ap, char *);
5811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (keys[num_keys].key == NULL)
5821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
5831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		keys[num_keys].repl = va_arg(ap, char *);
5841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (keys[num_keys].repl == NULL)
5851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("%s: NULL replacement", __func__);
5861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (num_keys == EXPAND_MAX_KEYS && va_arg(ap, char *) != NULL)
5881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: too many keys", __func__);
5891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	va_end(ap);
5901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Expand string */
5921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*buf = '\0';
5931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; *string != '\0'; string++) {
5941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*string != '%') {
5951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood append:
5961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buf[i++] = *string;
5971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (i >= sizeof(buf))
5981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fatal("%s: string too long", __func__);
5991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buf[i] = '\0';
6001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
6011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
6021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		string++;
6031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* %% case */
6041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*string == '%')
6051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto append;
6061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (j = 0; j < num_keys; j++) {
6071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (strchr(keys[j].key, *string) != NULL) {
6081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				i = strlcat(buf, keys[j].repl, sizeof(buf));
6091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (i >= sizeof(buf))
6101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					fatal("%s: string too long", __func__);
6111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
6121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
6131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
6141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (j >= num_keys)
6151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("%s: unknown key %%%c", __func__, *string);
6161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (xstrdup(buf));
6181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#undef EXPAND_MAX_KEYS
6191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
6201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
6221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Read an entire line from a public key file into a static buffer, discarding
6231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * lines that exceed the buffer size.  Returns 0 on success, -1 on failure.
6241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
6251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
6261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodread_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz,
6271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   u_long *lineno)
6281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
6291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (fgets(buf, bufsz, f) != NULL) {
6301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (buf[0] == '\0')
6311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
6321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		(*lineno)++;
6331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (buf[strlen(buf) - 1] == '\n' || feof(f)) {
6341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 0;
6351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
6361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("%s: %s line %lu exceeds size limit", __func__,
6371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    filename, *lineno);
6381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* discard remainder of line */
6391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			while (fgetc(f) != '\n' && !feof(f))
6401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				;	/* nothing */
6411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
6421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return -1;
6441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
6451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
6471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodtun_open(int tun, int mode)
6481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
6491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if defined(CUSTOM_SYS_TUN_OPEN)
6501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (sys_tun_open(tun, mode));
6511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#elif defined(SSH_TUN_OPENBSD)
6521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct ifreq ifr;
6531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char name[100];
6541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int fd = -1, sock;
6551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Open the tunnel device */
6571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (tun <= SSH_TUNID_MAX) {
6581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		snprintf(name, sizeof(name), "/dev/tun%d", tun);
6591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fd = open(name, O_RDWR);
6601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (tun == SSH_TUNID_ANY) {
6611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (tun = 100; tun >= 0; tun--) {
6621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			snprintf(name, sizeof(name), "/dev/tun%d", tun);
6631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if ((fd = open(name, O_RDWR)) >= 0)
6641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
6651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
6661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
6671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("%s: invalid tunnel %u", __func__, tun);
6681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
6691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (fd < 0) {
6721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("%s: %s open failed: %s", __func__, name, strerror(errno));
6731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
6741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("%s: %s mode %d fd %d", __func__, name, mode, fd);
6771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Set the tunnel device operation mode */
6791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tun%d", tun);
6801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
6811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto failed;
6821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)
6841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto failed;
6851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Set interface mode */
6871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ifr.ifr_flags &= ~IFF_UP;
6881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (mode == SSH_TUNMODE_ETHERNET)
6891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ifr.ifr_flags |= IFF_LINK0;
6901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else
6911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ifr.ifr_flags &= ~IFF_LINK0;
6921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
6931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto failed;
6941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Bring interface up */
6961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ifr.ifr_flags |= IFF_UP;
6971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
6981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto failed;
6991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	close(sock);
7011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (fd);
7021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood failed:
7041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (fd >= 0)
7051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(fd);
7061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sock >= 0)
7071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(sock);
7081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("%s: failed to set %s mode %d: %s", __func__, name,
7091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    mode, strerror(errno));
7101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (-1);
7111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else
7121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	error("Tunnel interfaces are not supported on this platform");
7131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (-1);
7141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
7151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
7161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
7181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsanitise_stdfd(void)
7191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
7201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int nullfd, dupfd;
7211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
7231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fprintf(stderr, "Couldn't open /dev/null: %s\n",
7241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    strerror(errno));
7251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		exit(1);
7261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (++dupfd <= 2) {
7281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Only clobber closed fds */
7291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (fcntl(dupfd, F_GETFL, 0) >= 0)
7301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
7311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (dup2(nullfd, dupfd) == -1) {
7321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fprintf(stderr, "dup2: %s\n", strerror(errno));
7331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			exit(1);
7341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (nullfd > 2)
7371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(nullfd);
7381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
7391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchar *
7411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodtohex(const void *vp, size_t l)
7421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
7431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const u_char *p = (const u_char *)vp;
7441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char b[3], *r;
7451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	size_t i, hl;
7461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (l > 65536)
7481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return xstrdup("tohex: length > 65536");
7491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	hl = l * 2 + 1;
7511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	r = xcalloc(1, hl);
7521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < l; i++) {
7531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		snprintf(b, sizeof(b), "%02x", p[i]);
7541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		strlcat(r, b, hl);
7551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (r);
7571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
7581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodu_int64_t
7601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodget_u64(const void *vp)
7611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
7621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const u_char *p = (const u_char *)vp;
7631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int64_t v;
7641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	v  = (u_int64_t)p[0] << 56;
7661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	v |= (u_int64_t)p[1] << 48;
7671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	v |= (u_int64_t)p[2] << 40;
7681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	v |= (u_int64_t)p[3] << 32;
7691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	v |= (u_int64_t)p[4] << 24;
7701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	v |= (u_int64_t)p[5] << 16;
7711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	v |= (u_int64_t)p[6] << 8;
7721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	v |= (u_int64_t)p[7];
7731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (v);
7751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
7761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodu_int32_t
7781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodget_u32(const void *vp)
7791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
7801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const u_char *p = (const u_char *)vp;
7811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int32_t v;
7821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	v  = (u_int32_t)p[0] << 24;
7841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	v |= (u_int32_t)p[1] << 16;
7851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	v |= (u_int32_t)p[2] << 8;
7861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	v |= (u_int32_t)p[3];
7871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (v);
7891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
7901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodu_int16_t
7921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodget_u16(const void *vp)
7931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
7941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const u_char *p = (const u_char *)vp;
7951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int16_t v;
7961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	v  = (u_int16_t)p[0] << 8;
7981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	v |= (u_int16_t)p[1];
7991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (v);
8011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
8041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodput_u64(void *vp, u_int64_t v)
8051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *p = (u_char *)vp;
8071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	p[0] = (u_char)(v >> 56) & 0xff;
8091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	p[1] = (u_char)(v >> 48) & 0xff;
8101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	p[2] = (u_char)(v >> 40) & 0xff;
8111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	p[3] = (u_char)(v >> 32) & 0xff;
8121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	p[4] = (u_char)(v >> 24) & 0xff;
8131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	p[5] = (u_char)(v >> 16) & 0xff;
8141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	p[6] = (u_char)(v >> 8) & 0xff;
8151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	p[7] = (u_char)v & 0xff;
8161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
8191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodput_u32(void *vp, u_int32_t v)
8201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *p = (u_char *)vp;
8221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	p[0] = (u_char)(v >> 24) & 0xff;
8241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	p[1] = (u_char)(v >> 16) & 0xff;
8251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	p[2] = (u_char)(v >> 8) & 0xff;
8261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	p[3] = (u_char)v & 0xff;
8271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
8311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodput_u16(void *vp, u_int16_t v)
8321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *p = (u_char *)vp;
8341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	p[0] = (u_char)(v >> 8) & 0xff;
8361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	p[1] = (u_char)v & 0xff;
8371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
8401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodms_subtract_diff(struct timeval *start, int *ms)
8411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct timeval diff, finish;
8431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	gettimeofday(&finish, NULL);
8451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	timersub(&finish, start, &diff);
8461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*ms -= (diff.tv_sec * 1000) + (diff.tv_usec / 1000);
8471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
8501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodms_to_timeval(struct timeval *tv, int ms)
8511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ms < 0)
8531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ms = 0;
8541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	tv->tv_sec = ms / 1000;
8551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	tv->tv_usec = (ms % 1000) * 1000;
8561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
8591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodbandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen)
8601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bw->buflen = buflen;
8621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bw->rate = kbps;
8631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bw->thresh = bw->rate;
8641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bw->lamt = 0;
8651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	timerclear(&bw->bwstart);
8661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	timerclear(&bw->bwend);
8671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Callback from read/write loop to insert bandwidth-limiting delays */
8701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
8711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodbandwidth_limit(struct bwlimit *bw, size_t read_len)
8721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int64_t waitlen;
8741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct timespec ts, rm;
8751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!timerisset(&bw->bwstart)) {
8771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		gettimeofday(&bw->bwstart, NULL);
8781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
8791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bw->lamt += read_len;
8821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (bw->lamt < bw->thresh)
8831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
8841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	gettimeofday(&bw->bwend, NULL);
8861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	timersub(&bw->bwend, &bw->bwstart, &bw->bwend);
8871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!timerisset(&bw->bwend))
8881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
8891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bw->lamt *= 8;
8911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	waitlen = (double)1000000L * bw->lamt / bw->rate;
8921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bw->bwstart.tv_sec = waitlen / 1000000L;
8941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bw->bwstart.tv_usec = waitlen % 1000000L;
8951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (timercmp(&bw->bwstart, &bw->bwend, >)) {
8971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		timersub(&bw->bwstart, &bw->bwend, &bw->bwend);
8981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Adjust the wait time */
9001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (bw->bwend.tv_sec) {
9011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			bw->thresh /= 2;
9021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (bw->thresh < bw->buflen / 4)
9031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				bw->thresh = bw->buflen / 4;
9041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (bw->bwend.tv_usec < 10000) {
9051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			bw->thresh *= 2;
9061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (bw->thresh > bw->buflen * 8)
9071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				bw->thresh = bw->buflen * 8;
9081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
9091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		TIMEVAL_TO_TIMESPEC(&bw->bwend, &ts);
9111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		while (nanosleep(&ts, &rm) == -1) {
9121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (errno != EINTR)
9131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
9141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ts = rm;
9151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
9161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bw->lamt = 0;
9191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	gettimeofday(&bw->bwstart, NULL);
9201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
9211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Make a template filename for mk[sd]temp() */
9231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
9241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodmktemp_proto(char *s, size_t len)
9251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *tmpdir;
9271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int r;
9281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((tmpdir = getenv("TMPDIR")) != NULL) {
9301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		r = snprintf(s, len, "%s/ssh-XXXXXXXXXXXX", tmpdir);
9311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (r > 0 && (size_t)r < len)
9321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return;
9331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXXXX");
9351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (r < 0 || (size_t)r >= len)
9361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: template string too short", __func__);
9371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
9381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic const struct {
9401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *name;
9411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int value;
9421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} ipqos[] = {
9431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "af11", IPTOS_DSCP_AF11 },
9441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "af12", IPTOS_DSCP_AF12 },
9451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "af13", IPTOS_DSCP_AF13 },
9461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "af14", IPTOS_DSCP_AF21 },
9471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "af22", IPTOS_DSCP_AF22 },
9481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "af23", IPTOS_DSCP_AF23 },
9491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "af31", IPTOS_DSCP_AF31 },
9501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "af32", IPTOS_DSCP_AF32 },
9511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "af33", IPTOS_DSCP_AF33 },
9521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "af41", IPTOS_DSCP_AF41 },
9531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "af42", IPTOS_DSCP_AF42 },
9541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "af43", IPTOS_DSCP_AF43 },
9551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "cs0", IPTOS_DSCP_CS0 },
9561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "cs1", IPTOS_DSCP_CS1 },
9571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "cs2", IPTOS_DSCP_CS2 },
9581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "cs3", IPTOS_DSCP_CS3 },
9591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "cs4", IPTOS_DSCP_CS4 },
9601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "cs5", IPTOS_DSCP_CS5 },
9611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "cs6", IPTOS_DSCP_CS6 },
9621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "cs7", IPTOS_DSCP_CS7 },
9631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "ef", IPTOS_DSCP_EF },
9641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "lowdelay", IPTOS_LOWDELAY },
9651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "throughput", IPTOS_THROUGHPUT },
9661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ "reliability", IPTOS_RELIABILITY },
9671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{ NULL, -1 }
9681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood};
9691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
9711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodparse_ipqos(const char *cp)
9721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i;
9741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *ep;
9751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	long val;
9761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (cp == NULL)
9781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
9791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; ipqos[i].name != NULL; i++) {
9801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strcasecmp(cp, ipqos[i].name) == 0)
9811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return ipqos[i].value;
9821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Try parsing as an integer */
9841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	val = strtol(cp, &ep, 0);
9851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*cp == '\0' || *ep != '\0' || val < 0 || val > 255)
9861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
9871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return val;
9881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
9891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodconst char *
9911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodiptos2str(int iptos)
9921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
9941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	static char iptos_str[sizeof "0xff"];
9951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; ipqos[i].name != NULL; i++) {
9971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (ipqos[i].value == iptos)
9981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return ipqos[i].name;
9991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
10001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	snprintf(iptos_str, sizeof iptos_str, "0x%02x", iptos);
10011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return iptos_str;
10021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
10031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
10041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsock_set_v6only(int s)
10051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
10061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef IPV6_V6ONLY
10071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int on = 1;
10081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("%s: set socket %d IPV6_V6ONLY", __func__, s);
10101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1)
10111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("setsockopt IPV6_V6ONLY: %s", strerror(errno));
10121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
10131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1014