another tcp apps IPv6 updates.(should be make world safe)

ftp, telnet, ftpd, faithd
  also telnet related sync with crypto, secure, kerberosIV

Obtained from: KAME project


git-svn-id: http://svn0.us-east.freebsd.org/base/head/contrib/telnet@56668 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f
This commit is contained in:
shin 2000-01-27 09:28:38 +00:00
parent afe31edad1
commit 32ca7e751c
6 changed files with 398 additions and 196 deletions

View File

@ -29,6 +29,8 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*
* $FreeBSD$
*/ */
#ifndef lint #ifndef lint
@ -83,6 +85,7 @@ static const char sccsid[] = "@(#)commands.c 8.4 (Berkeley) 5/30/95";
# endif /* vax */ # endif /* vax */
#endif /* !defined(CRAY) && !defined(sysV88) */ #endif /* !defined(CRAY) && !defined(sysV88) */
#include <netinet/ip.h> #include <netinet/ip.h>
#include <netinet/ip6.h>
#ifndef MAXHOSTNAMELEN #ifndef MAXHOSTNAMELEN
@ -2270,27 +2273,76 @@ ayt_status()
} }
#endif #endif
unsigned long inet_addr(); static const char *
sockaddr_ntop(sa)
struct sockaddr *sa;
{
void *addr;
static char addrbuf[INET6_ADDRSTRLEN];
switch (sa->sa_family) {
case AF_INET:
addr = &((struct sockaddr_in *)sa)->sin_addr;
break;
#ifdef INET6
case AF_INET6:
addr = &((struct sockaddr_in6 *)sa)->sin6_addr;
break;
#endif
default:
return NULL;
}
inet_ntop(sa->sa_family, addr, addrbuf, sizeof(addrbuf));
return addrbuf;
}
#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
static int
setpolicy(net, res, policy)
int net;
struct addrinfo *res;
char *policy;
{
char *buf;
int level;
int optname;
if (policy == NULL)
return 0;
buf = ipsec_set_policy(policy, strlen(policy));
if (buf == NULL) {
printf("%s\n", ipsec_strerror());
return -1;
}
level = res->ai_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
optname = res->ai_family == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY;
if (setsockopt(net, level, optname, buf, ipsec_get_policylen(buf)) < 0){
perror("setsockopt");
return -1;
}
free(buf);
}
#endif
int int
tn(argc, argv) tn(argc, argv)
int argc; int argc;
char *argv[]; char *argv[];
{ {
register struct hostent *host = 0; struct sockaddr_storage ss, src_ss;
struct sockaddr_in sin, src_sin;
struct servent *sp = 0;
unsigned long temp;
extern char *inet_ntoa();
#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
char *srp = 0, *strrchr(); char *srp = 0, *strrchr();
unsigned long sourceroute(), srlen; int proto, opt;
#endif int sourceroute(), srlen;
int srcroute = 0, result;
char *cmd, *hostp = 0, *portp = 0, *user = 0; char *cmd, *hostp = 0, *portp = 0, *user = 0;
char *src_addr = NULL; char *src_addr = NULL;
struct addrinfo hints, *res;
int error = 0;
/* clear the socket address prior to use */ /* clear the socket address prior to use */
memset((char *)&sin, 0, sizeof(sin)); memset((char *)&ss, 0, sizeof(ss));
if (connected) { if (connected) {
printf("?Already connected to %s\n", hostname); printf("?Already connected to %s\n", hostname);
@ -2350,126 +2402,106 @@ tn(argc, argv)
goto usage; goto usage;
if (src_addr != NULL) { if (src_addr != NULL) {
bzero((char *)&src_sin, sizeof(src_sin)); memset(&hints, 0, sizeof(hints));
src_sin.sin_family = AF_INET; hints.ai_flags = AI_NUMERICHOST;
if (!inet_aton(src_addr, &src_sin.sin_addr)) { hints.ai_family = family;
host = gethostbyname2(src_addr, AF_INET); hints.ai_socktype = SOCK_STREAM;
if (host == NULL) { error = getaddrinfo(src_addr, 0, &hints, &res);
herror(src_addr); if (error == EAI_NONAME) {
return 0; hints.ai_flags = 0;
} error = getaddrinfo(src_addr, 0, &hints, &res);
if (host->h_length != sizeof(src_sin.sin_addr)) {
fprintf(stderr, "telnet: gethostbyname2: invalid address\n");
return 0;
}
memcpy((void *)&src_sin.sin_addr, (void *)host->h_addr_list[0],
sizeof(src_sin.sin_addr));
} }
if (error != 0) {
fprintf(stderr, "%s: %s\n", src_addr, gai_strerror(error));
if (error == EAI_SYSTEM)
fprintf(stderr, "%s: %s\n", src_addr, strerror(errno));
return 0;
}
memcpy((void *)&src_ss, (void *)res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
} }
#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
if (hostp[0] == '@' || hostp[0] == '!') { if (hostp[0] == '@' || hostp[0] == '!') {
if ((hostname = strrchr(hostp, ':')) == NULL) if (
#ifdef INET6
family == AF_INET6 ||
#endif
(hostname = strrchr(hostp, ':')) == NULL)
hostname = strrchr(hostp, '@'); hostname = strrchr(hostp, '@');
hostname++; hostname++;
srp = 0; srcroute = 1;
temp = sourceroute(hostp, &srp, &srlen); } else
if (temp == 0) { hostname = hostp;
herror(srp); if (!portp) {
telnetport = 1;
portp = "telnet";
} else if (*portp == '-') {
portp++;
telnetport = 1;
} else
telnetport = 0;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_NUMERICHOST;
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(hostname, portp, &hints, &res);
if (error == 0) {
int gni_err = 1;
if (doaddrlookup)
gni_err = getnameinfo(res->ai_addr, res->ai_addr->sa_len,
_hostname, sizeof(_hostname) - 1, NULL, 0,
0);
if (gni_err != 0)
(void) strncpy(_hostname, hostp, sizeof(_hostname) - 1);
_hostname[sizeof(_hostname)-1] = '\0';
hostname = _hostname;
} else if (error == EAI_NONAME) {
hints.ai_flags = AI_CANONNAME;
error = getaddrinfo(hostname, portp, &hints, &res);
if (error != 0) {
fprintf(stderr, "%s: %s\n", hostname, gai_strerror(error));
if (error == EAI_SYSTEM)
fprintf(stderr, "%s: %s\n", hostname, strerror(errno));
setuid(getuid()); setuid(getuid());
return 0; return 0;
} else if (temp == -1) { }
memcpy((void *)&ss, (void *)res->ai_addr, res->ai_addrlen);
if (srcroute != 0)
(void) strncpy(_hostname, hostname, sizeof(_hostname) - 1);
else if (res->ai_canonname != NULL)
strcpy(_hostname, res->ai_canonname);
else
(void) strncpy(_hostname, hostp, sizeof(_hostname) - 1);
_hostname[sizeof(_hostname)-1] = '\0';
hostname = _hostname;
}
if (srcroute != 0) {
srp = 0;
result = sourceroute(res, hostp, &srp, &srlen, &proto, &opt);
if (result == 0) {
setuid(getuid());
freeaddrinfo(res);
return 0;
} else if (result == -1) {
printf("Bad source route option: %s\n", hostp); printf("Bad source route option: %s\n", hostp);
setuid(getuid()); setuid(getuid());
freeaddrinfo(res);
return 0; return 0;
} else {
sin.sin_addr.s_addr = temp;
sin.sin_family = AF_INET;
} }
} else {
#endif
temp = inet_addr(hostp);
if (temp != INADDR_NONE) {
sin.sin_addr.s_addr = temp;
sin.sin_family = AF_INET;
if (doaddrlookup)
host = gethostbyaddr((char *)&temp, sizeof(temp), AF_INET);
if (host)
(void) strncpy(_hostname, host->h_name, sizeof(_hostname));
else
(void) strncpy(_hostname, hostp, sizeof(_hostname));
_hostname[sizeof(_hostname)-1] = '\0';
hostname = _hostname;
} else {
host = gethostbyname(hostp);
if (host) {
sin.sin_family = host->h_addrtype;
#if defined(h_addr) /* In 4.3, this is a #define */
memmove((caddr_t)&sin.sin_addr,
host->h_addr_list[0], host->h_length);
#else /* defined(h_addr) */
memmove((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
#endif /* defined(h_addr) */
strncpy(_hostname, host->h_name, sizeof(_hostname));
_hostname[sizeof(_hostname)-1] = '\0';
hostname = _hostname;
} else {
herror(hostp);
setuid(getuid());
return 0;
}
}
#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
} }
#endif printf("Trying %s...\n", sockaddr_ntop(res->ai_addr));
if (portp) {
if (*portp == '-') {
portp++;
telnetport = 1;
} else
telnetport = 0;
sin.sin_port = atoi(portp);
if (sin.sin_port == 0) {
sp = getservbyname(portp, "tcp");
if (sp)
sin.sin_port = sp->s_port;
else {
printf("%s: bad port number\n", portp);
setuid(getuid());
return 0;
}
} else {
#if !defined(htons)
u_short htons P((unsigned short));
#endif /* !defined(htons) */
sin.sin_port = htons(sin.sin_port);
}
} else {
if (sp == 0) {
sp = getservbyname("telnet", "tcp");
if (sp == 0) {
fprintf(stderr, "telnet: tcp/telnet: unknown service\n");
setuid(getuid());
return 0;
}
sin.sin_port = sp->s_port;
}
telnetport = 1;
}
printf("Trying %s...\n", inet_ntoa(sin.sin_addr));
do { do {
net = socket(AF_INET, SOCK_STREAM, 0); net = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
setuid(getuid()); setuid(getuid());
if (net < 0) { if (net < 0) {
perror("telnet: socket"); perror("telnet: socket");
return 0; return 0;
} }
#if defined(IP_OPTIONS) && defined(IPPROTO_IP) if (srp && setsockopt(net, proto, opt, (char *)srp, srlen) < 0)
if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0) perror("setsockopt (source route)");
perror("setsockopt (IP_OPTIONS)");
#endif
#if defined(IPPROTO_IP) && defined(IP_TOS) #if defined(IPPROTO_IP) && defined(IP_TOS)
{ if (res->ai_family == PF_INET) {
# if defined(HAS_GETTOS) # if defined(HAS_GETTOS)
struct tosent *tp; struct tosent *tp;
if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
@ -2490,28 +2522,31 @@ tn(argc, argv)
} }
if (src_addr != NULL) { if (src_addr != NULL) {
if (bind(net, (struct sockaddr *)&src_sin, sizeof(src_sin)) == -1) { if (bind(net, (struct sockaddr *)&src_ss,
((struct sockaddr *)&src_ss)->sa_len) == -1) {
perror("bind"); perror("bind");
return 0; return 0;
} }
} }
#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
if (setpolicy(net, res, ipsec_policy_in) < 0)
return 0;
if (setpolicy(net, res, ipsec_policy_out) < 0)
return 0;
#endif
if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) { if (connect(net, res->ai_addr, res->ai_addrlen) < 0) {
#if defined(h_addr) /* In 4.3, this is a #define */ if (res->ai_next) {
if (host && host->h_addr_list[1]) {
int oerrno = errno; int oerrno = errno;
fprintf(stderr, "telnet: connect to address %s: ", fprintf(stderr, "telnet: connect to address %s: ",
inet_ntoa(sin.sin_addr)); sockaddr_ntop(res->ai_addr));
errno = oerrno; errno = oerrno;
perror((char *)0); perror((char *)0);
host->h_addr_list++; res = res->ai_next;
memmove((caddr_t)&sin.sin_addr,
host->h_addr_list[0], host->h_length);
(void) NetClose(net); (void) NetClose(net);
continue; continue;
} }
#endif /* defined(h_addr) */
perror("telnet: Unable to connect to remote host"); perror("telnet: Unable to connect to remote host");
return 0; return 0;
} }
@ -2520,6 +2555,7 @@ tn(argc, argv)
auth_encrypt_connect(connected); auth_encrypt_connect(connected);
#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ #endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
} while (connected == 0); } while (connected == 0);
freeaddrinfo(res);
cmdrc(hostp, hostname); cmdrc(hostp, hostname);
if (autologin && user == NULL) { if (autologin && user == NULL) {
struct passwd *pw; struct passwd *pw;
@ -2861,8 +2897,6 @@ cmdrc(m1, m2)
fclose(rcfile); fclose(rcfile);
} }
#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
/* /*
* Source route is handed in as * Source route is handed in as
* [!]@hop1@hop2...[@|:]dst * [!]@hop1@hop2...[@|:]dst
@ -2876,6 +2910,10 @@ cmdrc(m1, m2)
* be the address to connect() to. * be the address to connect() to.
* *
* Arguments: * Arguments:
*
* res: ponter to addrinfo structure which contains sockaddr to
* the host to connect to.
*
* arg: pointer to route list to decipher * arg: pointer to route list to decipher
* *
* cpp: If *cpp is not equal to NULL, this is a * cpp: If *cpp is not equal to NULL, this is a
@ -2885,9 +2923,18 @@ cmdrc(m1, m2)
* lenp: pointer to an integer that contains the * lenp: pointer to an integer that contains the
* length of *cpp if *cpp != NULL. * length of *cpp if *cpp != NULL.
* *
* protop: pointer to an integer that should be filled in with
* appropriate protocol for setsockopt, as socket
* protocol family.
*
* optp: pointer to an integer that should be filled in with
* appropriate option for setsockopt, as socket protocol
* family.
*
* Return values: * Return values:
* *
* Returns the address of the host to connect to. If the * If the return value is 1, then all operations are
* successful. If the
* return value is -1, there was a syntax error in the * return value is -1, there was a syntax error in the
* option, either unknown characters, or too many hosts. * option, either unknown characters, or too many hosts.
* If the return value is 0, one of the hostnames in the * If the return value is 0, one of the hostnames in the
@ -2901,21 +2948,32 @@ cmdrc(m1, m2)
* *lenp: This will be filled in with how long the option * *lenp: This will be filled in with how long the option
* pointed to by *cpp is. * pointed to by *cpp is.
* *
* *protop: This will be filled in with appropriate protocol for
* setsockopt, as socket protocol family.
*
* *optp: This will be filled in with appropriate option for
* setsockopt, as socket protocol family.
*/ */
unsigned long int
sourceroute(arg, cpp, lenp) sourceroute(ai, arg, cpp, lenp, protop, optp)
struct addrinfo *ai;
char *arg; char *arg;
char **cpp; char **cpp;
int *lenp; int *lenp;
int *protop;
int *optp;
{ {
static char lsr[44]; static char buf[1024]; /*XXX*/
struct cmsghdr *cmsg;
#ifdef sysV88 #ifdef sysV88
static IOPTN ipopt; static IOPTN ipopt;
#endif #endif
char *cp, *cp2, *lsrp, *lsrep; char *cp, *cp2, *lsrp, *ep;
register int tmp; register int tmp;
struct in_addr sin_addr; struct sockaddr_in *sin;
register struct hostent *host = 0; struct sockaddr_in6 *sin6;
struct addrinfo hints, *res;
int error;
register char c; register char c;
/* /*
@ -2924,22 +2982,46 @@ sourceroute(arg, cpp, lenp)
*/ */
if (cpp == NULL || lenp == NULL) if (cpp == NULL || lenp == NULL)
return((unsigned long)-1); return((unsigned long)-1);
if (*cpp != NULL && *lenp < 7) if (*cpp != NULL) {
return((unsigned long)-1); switch (res->ai_family) {
case AF_INET:
if (*lenp < 7)
return((unsigned long)-1);
break;
#ifdef INET6
case AF_INET6:
if (*lenp < (sizeof(struct cmsghdr) +
sizeof(struct ip6_rthdr) +
sizeof(struct in6_addr)))
return((unsigned long)-1);
break;
#endif
}
}
/* /*
* Decide whether we have a buffer passed to us, * Decide whether we have a buffer passed to us,
* or if we need to use our own static buffer. * or if we need to use our own static buffer.
*/ */
if (*cpp) { if (*cpp) {
lsrp = *cpp; lsrp = *cpp;
lsrep = lsrp + *lenp; ep = lsrp + *lenp;
} else { } else {
*cpp = lsrp = lsr; *cpp = lsrp = buf;
lsrep = lsrp + 44; ep = lsrp + 1024;
} }
cp = arg; cp = arg;
#ifdef INET6
if (ai->ai_family == AF_INET6) {
cmsg = inet6_rthdr_init(*cpp, IPV6_RTHDR_TYPE_0);
if (*cp != '@')
return -1;
*protop = IPPROTO_IPV6;
*optp = IPV6_PKTOPTIONS;
} else
#endif
{
/* /*
* Next, decide whether we have a loose source * Next, decide whether we have a loose source
* route or a strict source route, and fill in * route or a strict source route, and fill in
@ -2966,13 +3048,20 @@ sourceroute(arg, cpp, lenp)
lsrp++; /* skip over length, we'll fill it in later */ lsrp++; /* skip over length, we'll fill it in later */
*lsrp++ = 4; *lsrp++ = 4;
#endif #endif
*protop = IPPROTO_IP;
*optp = IP_OPTIONS;
}
cp++; cp++;
memset(&hints, 0, sizeof(hints));
sin_addr.s_addr = 0; hints.ai_family = ai->ai_family;
hints.ai_socktype = SOCK_STREAM;
for (c = 0;;) { for (c = 0;;) {
if (c == ':') if (
#ifdef INET6
ai->ai_family != AF_INET6 &&
#endif
c == ':')
cp2 = 0; cp2 = 0;
else for (cp2 = cp; (c = *cp2); cp2++) { else for (cp2 = cp; (c = *cp2); cp2++) {
if (c == ',') { if (c == ',') {
@ -2981,7 +3070,11 @@ sourceroute(arg, cpp, lenp)
cp2++; cp2++;
} else if (c == '@') { } else if (c == '@') {
*cp2++ = '\0'; *cp2++ = '\0';
} else if (c == ':') { } else if (
#ifdef INET6
ai->ai_family != AF_INET6 &&
#endif
c == ':') {
*cp2++ = '\0'; *cp2++ = '\0';
} else } else
continue; continue;
@ -2990,21 +3083,32 @@ sourceroute(arg, cpp, lenp)
if (!c) if (!c)
cp2 = 0; cp2 = 0;
if ((tmp = inet_addr(cp)) != -1) { hints.ai_flags = AI_NUMERICHOST;
sin_addr.s_addr = tmp; error = getaddrinfo(cp, NULL, &hints, &res);
} else if ((host = gethostbyname(cp))) { if (error == EAI_NONAME) {
#if defined(h_addr) hints.ai_flags = 0;
memmove((caddr_t)&sin_addr, error = getaddrinfo(cp, NULL, &hints, &res);
host->h_addr_list[0], host->h_length); }
#else if (error != 0) {
memmove((caddr_t)&sin_addr, host->h_addr, host->h_length); fprintf(stderr, "%s: %s\n", cp, gai_strerror(error));
#endif if (error == EAI_SYSTEM)
} else { fprintf(stderr, "%s: %s\n", cp,
strerror(errno));
*cpp = cp; *cpp = cp;
return(0); return(0);
} }
memmove(lsrp, (char *)&sin_addr, 4); #ifdef INET6
if (res->ai_family == AF_INET6) {
sin6 = (struct sockaddr_in6 *)res->ai_addr;
inet6_rthdr_add(cmsg, &sin6->sin6_addr,
IPV6_RTHDR_LOOSE);
} else
#endif
{
sin = (struct sockaddr_in *)res->ai_addr;
memcpy(lsrp, (char *)&sin->sin_addr, 4);
lsrp += 4; lsrp += 4;
}
if (cp2) if (cp2)
cp = cp2; cp = cp2;
else else
@ -3012,9 +3116,27 @@ sourceroute(arg, cpp, lenp)
/* /*
* Check to make sure there is space for next address * Check to make sure there is space for next address
*/ */
if (lsrp + 4 > lsrep) #ifdef INET6
if (res->ai_family == AF_INET6) {
if (((char *)cmsg +
sizeof(struct cmsghdr) +
sizeof(struct ip6_rthdr) +
((inet6_rthdr_segments(cmsg) + 1) *
sizeof(struct in6_addr))) > ep)
return((unsigned long)-1); return((unsigned long)-1);
} else
#endif
if (lsrp + 4 > ep)
return((unsigned long)-1);
freeaddrinfo(res);
} }
#ifdef INET6
if (res->ai_family == AF_INET6) {
inet6_rthdr_lasthop(cmsg, IPV6_RTHDR_LOOSE);
*lenp = cmsg->cmsg_len;
} else
#endif
{
#ifndef sysV88 #ifndef sysV88
if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) { if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) {
*cpp = 0; *cpp = 0;
@ -3033,6 +3155,10 @@ sourceroute(arg, cpp, lenp)
*lenp = sizeof(ipopt); *lenp = sizeof(ipopt);
*cpp = (char *) &ipopt; *cpp = (char *) &ipopt;
#endif #endif
return(sin_addr.s_addr); }
freeaddrinfo(res);
return 1;
} }
#endif

View File

@ -31,6 +31,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)externs.h 8.3 (Berkeley) 5/30/95 * @(#)externs.h 8.3 (Berkeley) 5/30/95
* $FreeBSD$
*/ */
#ifndef BSD #ifndef BSD
@ -87,6 +88,14 @@ typedef unsigned char cc_t;
#include <strings.h> #include <strings.h>
#endif #endif
#if defined(IPSEC)
#include <netinet6/ipsec.h>
#if defined(IPSEC_POLICY_IPSEC)
extern char *ipsec_policy_in;
extern char *ipsec_policy_out;
#endif
#endif
#ifndef _POSIX_VDISABLE #ifndef _POSIX_VDISABLE
# ifdef sun # ifdef sun
# include <sys/param.h> /* pick up VDISABLE definition, mayby */ # include <sys/param.h> /* pick up VDISABLE definition, mayby */
@ -116,6 +125,7 @@ extern int
autologin, /* Autologin enabled */ autologin, /* Autologin enabled */
skiprc, /* Don't process the ~/.telnetrc file */ skiprc, /* Don't process the ~/.telnetrc file */
eight, /* use eight bit mode (binary in and/or out */ eight, /* use eight bit mode (binary in and/or out */
family, /* address family of peer */
flushout, /* flush output */ flushout, /* flush output */
connected, /* Are we connected to the other side? */ connected, /* Are we connected to the other side? */
globalmode, /* Mode tty should be in */ globalmode, /* Mode tty should be in */

View File

@ -29,6 +29,8 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*
* $FreeBSD$
*/ */
#ifndef lint #ifndef lint
@ -42,6 +44,7 @@ static const char sccsid[] = "@(#)main.c 8.3 (Berkeley) 5/30/95";
#endif /* not lint */ #endif /* not lint */
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h> #include <stdlib.h>
#include "ring.h" #include "ring.h"
@ -70,6 +73,13 @@ void init_telnet(void);
void init_sys(void); void init_sys(void);
void init_3270(void); void init_3270(void);
#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
char *ipsec_policy_in = NULL;
char *ipsec_policy_out = NULL;
#endif
int family = AF_UNSPEC;
/* /*
* Initialize variables. * Initialize variables.
*/ */
@ -95,10 +105,10 @@ usage()
fprintf(stderr, "Usage: %s %s%s%s%s\n", fprintf(stderr, "Usage: %s %s%s%s%s\n",
prompt, prompt,
#ifdef AUTHENTICATION #ifdef AUTHENTICATION
"[-8] [-E] [-K] [-L] [-N] [-S tos] [-X atype] [-a] [-c] [-d]", "[-4] [-6] [-8] [-E] [-K] [-L] [-N] [-S tos] [-X atype] [-a] [-c] [-d]",
"\n\t[-e char] [-k realm] [-l user] [-f/-F] [-n tracefile] ", "\n\t[-e char] [-k realm] [-l user] [-f/-F] [-n tracefile] ",
#else #else
"[-8] [-E] [-L] [-N] [-S tos] [-a] [-c] [-d] [-e char] [-l user]", "[-4] [-6] [-8] [-E] [-L] [-N] [-S tos] [-a] [-c] [-d] [-e char] [-l user]",
"\n\t[-n tracefile] ", "\n\t[-n tracefile] ",
#endif #endif
#if defined(TN3270) && defined(unix) #if defined(TN3270) && defined(unix)
@ -112,6 +122,9 @@ usage()
#else #else
"[-r] [-s src_addr] ", "[-r] [-s src_addr] ",
#endif #endif
#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
"[-P policy]"
#endif
#ifdef ENCRYPTION #ifdef ENCRYPTION
"[-x] [host-name [port]]" "[-x] [host-name [port]]"
#else /* ENCRYPTION */ #else /* ENCRYPTION */
@ -156,8 +169,24 @@ main(argc, argv)
rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE; rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE;
autologin = -1; autologin = -1;
while ((ch = getopt(argc, argv, "8EKLNS:X:acde:fFk:l:n:rs:t:x")) != EOF) { #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
#define IPSECOPT "P:"
#else
#define IPSECOPT
#endif
while ((ch = getopt(argc, argv,
"468EKLNS:X:acde:fFk:l:n:rs:t:x" IPSECOPT)) != -1)
#undef IPSECOPT
{
switch(ch) { switch(ch) {
case '4':
family = AF_INET;
break;
#ifdef INET6
case '6':
family = AF_INET6;
break;
#endif
case '8': case '8':
eight = 3; /* binary output and input */ eight = 3; /* binary output and input */
break; break;
@ -299,6 +328,16 @@ main(argc, argv)
prompt); prompt);
#endif /* ENCRYPTION */ #endif /* ENCRYPTION */
break; break;
#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
case 'P':
if (!strncmp("in", optarg, 2))
ipsec_policy_in = strdup(optarg);
else if (!strncmp("out", optarg, 3))
ipsec_policy_out = strdup(optarg);
else
usage();
break;
#endif
case '?': case '?':
default: default:
usage(); usage();

View File

@ -30,8 +30,9 @@
.\" SUCH DAMAGE. .\" SUCH DAMAGE.
.\" .\"
.\" @(#)telnet.1 8.6 (Berkeley) 6/1/94 .\" @(#)telnet.1 8.6 (Berkeley) 6/1/94
.\" $FreeBSD$
.\" .\"
.Dd June 1, 1994 .Dd January 27, 2000
.Dt TELNET 1 .Dt TELNET 1
.Os BSD 4.2 .Os BSD 4.2
.Sh NAME .Sh NAME
@ -549,9 +550,10 @@ will attempt to contact a
.Tn TELNET .Tn TELNET
server at the default port. server at the default port.
The host specification may be either a host name (see The host specification may be either a host name (see
.Xr hosts 5 ) .Xr hosts 5 ) ,
or an Internet address specified in the \*(Lqdot notation\*(Rq (see an Internet address specified in the \*(Lqdot notation\*(Rq (see
.Xr inet 3 ) . .Xr inet 3 ) ,
or IPv6 host name or IPv6 coloned-hexadecimal addreess.
The The
.Op Fl l .Op Fl l
option may be used to specify the user name option may be used to specify the user name
@ -1367,6 +1369,8 @@ The
.Nm Telnet .Nm Telnet
command appeared in command appeared in
.Bx 4.2 . .Bx 4.2 .
.Pp
IPv6 support was added by WIDE/KAME project.
.Sh NOTES .Sh NOTES
.Pp .Pp
On some remote systems, echo has to be turned off manually when in On some remote systems, echo has to be turned off manually when in

View File

@ -30,8 +30,9 @@
.\" SUCH DAMAGE. .\" SUCH DAMAGE.
.\" .\"
.\" @(#)telnetd.8 8.4 (Berkeley) 6/1/94 .\" @(#)telnetd.8 8.4 (Berkeley) 6/1/94
.\" $FreeBSD$
.\" .\"
.Dd June 1, 1994 .Dd January 27, 2000
.Dt TELNETD 8 .Dt TELNETD 8
.Os BSD 4.2 .Os BSD 4.2
.Sh NAME .Sh NAME
@ -610,3 +611,5 @@ never sends
.Tn TELNET .Tn TELNET
.Dv IAC GA .Dv IAC GA
(go ahead) commands. (go ahead) commands.
.Sh HISTORY
IPv6 support was added by WIDE/KAME project.

View File

@ -70,6 +70,12 @@ static const char rcsid[] =
#include <sys/secparm.h> #include <sys/secparm.h>
#include <sys/usrv.h> #include <sys/usrv.h>
# endif /* SO_SEC_MULTI */ # endif /* SO_SEC_MULTI */
/* wrapper for KAME-special getnameinfo() */
#ifndef NI_WITHSCOPEID
#define NI_WITHSCOPEID 0
#endif
int secflag; int secflag;
char tty_dev[16]; char tty_dev[16];
struct secdev dv; struct secdev dv;
@ -128,7 +134,7 @@ char ptyibuf2[BUFSIZ];
# include <termcap.h> # include <termcap.h>
int readstream(int p, char *ibuf, int bufsize); int readstream(int p, char *ibuf, int bufsize);
void doit(struct sockaddr_in *who); void doit(struct sockaddr *who);
int terminaltypeok(char *s); int terminaltypeok(char *s);
void startslave(char *host, int autologin, char *autoname); void startslave(char *host, int autologin, char *autoname);
@ -145,7 +151,7 @@ int debug = 0;
int keepalive = 1; int keepalive = 1;
char *altlogin; char *altlogin;
void doit __P((struct sockaddr_in *)); void doit __P((struct sockaddr *));
int terminaltypeok __P((char *)); int terminaltypeok __P((char *));
void startslave __P((char *, int, char *)); void startslave __P((char *, int, char *));
extern void usage P((void)); extern void usage P((void));
@ -157,6 +163,7 @@ extern void usage P((void));
*/ */
char valid_opts[] = { char valid_opts[] = {
'd', ':', 'h', 'k', 'n', 'p', ':', 'S', ':', 'u', ':', 'U', 'd', ':', 'h', 'k', 'n', 'p', ':', 'S', ':', 'u', ':', 'U',
'4', '6',
#ifdef AUTHENTICATION #ifdef AUTHENTICATION
'a', ':', 'X', ':', 'a', ':', 'X', ':',
#endif #endif
@ -184,11 +191,13 @@ char valid_opts[] = {
'\0' '\0'
}; };
int int family = AF_INET;
int
main(argc, argv) main(argc, argv)
char *argv[]; char *argv[];
{ {
struct sockaddr_in from; struct sockaddr_storage from;
int on = 1, fromlen; int on = 1, fromlen;
register int ch; register int ch;
#if defined(IPPROTO_IP) && defined(IP_TOS) #if defined(IPPROTO_IP) && defined(IP_TOS)
@ -406,6 +415,16 @@ main(argc, argv)
break; break;
#endif /* AUTHENTICATION */ #endif /* AUTHENTICATION */
case '4':
family = AF_INET;
break;
#ifdef INET6
case '6':
family = AF_INET6;
break;
#endif
default: default:
warnx("%c: unknown option", ch); warnx("%c: unknown option", ch);
/* FALLTHROUGH */ /* FALLTHROUGH */
@ -419,43 +438,41 @@ main(argc, argv)
argv += optind; argv += optind;
if (debug) { if (debug) {
int s, ns, foo; int s, ns, foo, error;
struct servent *sp; char *service = "telnet";
static struct sockaddr_in sin = { AF_INET }; struct addrinfo hints, *res;
if (argc > 1) { if (argc > 1) {
usage(); usage();
/* NOT REACHED */ /* NOT REACHED */
} else if (argc == 1) { } else if (argc == 1)
if ((sp = getservbyname(*argv, "tcp"))) { service = *argv;
sin.sin_port = sp->s_port;
} else { memset(&hints, 0, sizeof(hints));
sin.sin_port = atoi(*argv); hints.ai_flags = AI_PASSIVE;
if ((int)sin.sin_port <= 0) { hints.ai_family = family;
warnx("%s: bad port #", *argv); hints.ai_socktype = SOCK_STREAM;
usage(); hints.ai_protocol = 0;
/* NOT REACHED */ error = getaddrinfo(NULL, service, &hints, &res);
}
sin.sin_port = htons((u_short)sin.sin_port); if (error) {
} errx(1, "tcp/%s: %s\n", service, gai_strerror(error));
} else { if (error == EAI_SYSTEM)
sp = getservbyname("telnet", "tcp"); errx(1, "tcp/%s: %s\n", service, strerror(errno));
if (sp == 0) usage();
errx(1, "tcp/telnet: unknown service");
sin.sin_port = sp->s_port;
} }
s = socket(AF_INET, SOCK_STREAM, 0); s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s < 0) if (s < 0)
err(1, "socket"); err(1, "socket");
(void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
(char *)&on, sizeof(on)); (char *)&on, sizeof(on));
if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) if (bind(s, res->ai_addr, res->ai_addrlen) < 0)
err(1, "bind"); err(1, "bind");
if (listen(s, 1) < 0) if (listen(s, 1) < 0)
err(1, "listen"); err(1, "listen");
foo = sizeof sin; foo = res->ai_addrlen;
ns = accept(s, (struct sockaddr *)&sin, &foo); ns = accept(s, res->ai_addr, &foo);
if (ns < 0) if (ns < 0)
err(1, "accept"); err(1, "accept");
(void) dup2(ns, 0); (void) dup2(ns, 0);
@ -537,7 +554,7 @@ main(argc, argv)
} }
#if defined(IPPROTO_IP) && defined(IP_TOS) #if defined(IPPROTO_IP) && defined(IP_TOS)
{ if (from.ss_family == AF_INET) {
# if defined(HAS_GETTOS) # if defined(HAS_GETTOS)
struct tosent *tp; struct tosent *tp;
if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
@ -553,7 +570,7 @@ main(argc, argv)
} }
#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
net = 0; net = 0;
doit(&from); doit((struct sockaddr *)&from);
/* NOTREACHED */ /* NOTREACHED */
return(0); return(0);
} /* end of main */ } /* end of main */
@ -821,8 +838,9 @@ char user_name[256];
*/ */
void void
doit(who) doit(who)
struct sockaddr_in *who; struct sockaddr *who;
{ {
int err;
int ptynum; int ptynum;
/* /*
@ -865,16 +883,18 @@ doit(who)
#endif /* _SC_CRAY_SECURE_SYS */ #endif /* _SC_CRAY_SECURE_SYS */
/* get name of connected client */ /* get name of connected client */
if (realhostname(remote_hostname, sizeof(remote_hostname) - 1, if (realhostname_sa(remote_hostname, sizeof(remote_hostname) - 1,
&who->sin_addr) == HOSTNAME_INVALIDADDR && registerd_host_only) who, who->sa_len) == HOSTNAME_INVALIDADDR && registerd_host_only)
fatal(net, "Couldn't resolve your address into a host name.\r\n\ fatal(net, "Couldn't resolve your address into a host name.\r\n\
Please contact your net administrator"); Please contact your net administrator");
remote_hostname[sizeof(remote_hostname) - 1] = '\0'; remote_hostname[sizeof(remote_hostname) - 1] = '\0';
trimdomain(remote_hostname, UT_HOSTSIZE); trimdomain(remote_hostname, UT_HOSTSIZE);
if (!isdigit(remote_hostname[0]) && strlen(remote_hostname) > utmp_len) if (!isdigit(remote_hostname[0]) && strlen(remote_hostname) > utmp_len)
strncpy(remote_hostname, inet_ntoa(who->sin_addr), err = getnameinfo(who, who->sa_len, remote_hostname,
sizeof(remote_hostname) - 1); sizeof(remote_hostname), NULL, 0,
NI_NUMERICHOST|NI_WITHSCOPEID);
/* XXX: do 'err' check */
(void) gethostname(host_name, sizeof(host_name) - 1); (void) gethostname(host_name, sizeof(host_name) - 1);
host_name[sizeof(host_name) - 1] = '\0'; host_name[sizeof(host_name) - 1] = '\0';