From 9bee021415ee871abe55d8ae1bfa52e659128407 Mon Sep 17 00:00:00 2001 From: itojun Date: Fri, 2 Jul 1999 15:09:10 +0000 Subject: [PATCH] IPv6-ready telnet. source route (telnet @localhost@localhost) works for IPv6 as well. --- usr.bin/telnet/Makefile | 10 +- usr.bin/telnet/commands.c | 480 +++++++++++++++++++++----------------- usr.bin/telnet/externs.h | 12 +- usr.bin/telnet/main.c | 26 ++- usr.bin/telnet/telnet.1 | 13 +- 5 files changed, 324 insertions(+), 217 deletions(-) diff --git a/usr.bin/telnet/Makefile b/usr.bin/telnet/Makefile index 5a8365028541..e424482a0bf3 100644 --- a/usr.bin/telnet/Makefile +++ b/usr.bin/telnet/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.16 1999/06/07 00:53:10 thorpej Exp $ +# $NetBSD: Makefile,v 1.17 1999/07/02 15:09:10 itojun Exp $ # # Copyright (c) 1990 The Regents of the University of California. # All rights reserved. @@ -48,10 +48,9 @@ PROG= telnet CPPFLAGS+=-DTERMCAP -DKLUDGELINEMODE -DUSE_TERMIO -Dunix CPPFLAGS+=-DENV_HACK CPPFLAGS+=-I${.CURDIR}/../../lib -LDADD+= -ltermcap -ltelnet +LDADD+= -ltermcap -ltelnet DPADD= ${LIBTERMCAP} ${LIBTELNET} - SRCS= authenc.c commands.c main.c network.c ring.c sys_bsd.c telnet.c \ terminal.c tn3270.c utilities.c @@ -70,5 +69,10 @@ MAN= telnet.1 .endif # EXPORTABLE_SYSTEM +CPPFLAGS+=-DIPSEC +LDADD+= -lipsec +DPADD+= ${LIBIPSEC} +CPPFLAGS+=-DINET6 + nocrypt: @echo "Encryption code already removed." diff --git a/usr.bin/telnet/commands.c b/usr.bin/telnet/commands.c index 90387e7b4c23..2331cb2b90f4 100644 --- a/usr.bin/telnet/commands.c +++ b/usr.bin/telnet/commands.c @@ -1,4 +1,33 @@ -/* $NetBSD: commands.c,v 1.25 1998/11/06 19:54:18 christos Exp $ */ +/* $NetBSD: commands.c,v 1.26 1999/07/02 15:09:10 itojun Exp $ */ + +/* + * Copyright (C) 1997 and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * 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 + * SUCH DAMAGE. + */ /* * Copyright (c) 1988, 1990, 1993 @@ -38,7 +67,7 @@ #if 0 static char sccsid[] = "@(#)commands.c 8.4 (Berkeley) 5/30/95"; #else -__RCSID("$NetBSD: commands.c,v 1.25 1998/11/06 19:54:18 christos Exp $"); +__RCSID("$NetBSD: commands.c,v 1.26 1999/07/02 15:09:10 itojun Exp $"); #endif #endif /* not lint */ @@ -160,6 +189,7 @@ static int auth_help P((char *)); static void filestuff P((int)); #endif static int status P((int, char *[])); +static const char *sockaddr_ntop __P((struct sockaddr *)); typedef int (*intrtn_t) P((int, char **)); static int call P((intrtn_t, ...)); static Command *getcmd P((char *)); @@ -2130,18 +2160,37 @@ ayt_status() } #endif +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; + case AF_INET6: + addr = &((struct sockaddr_in6 *)sa)->sin6_addr; + break; + default: + return NULL; + } + return (char *)inet_ntop(sa->sa_family, addr, addrbuf, sizeof(addrbuf)); +} + int tn(argc, argv) int argc; char *argv[]; { - register struct hostent *host = 0; - struct sockaddr_in sin; - struct servent *sp = 0; - unsigned long temp; + struct addrinfo hints, *res; + int error; #if defined(IP_OPTIONS) && defined(IPPROTO_IP) char *srp = 0; unsigned long srlen; + int proto, opt; #endif char *cmd, *hostp = 0, *portp = 0; const char *user = 0; @@ -2149,9 +2198,6 @@ tn(argc, argv) (void) &user; #endif - /* clear the socket address prior to use */ - memset((char *)&sin, 0, sizeof(sin)); - if (connected) { printf("?Already connected to %s\n", hostname); setuid(getuid()); @@ -2201,142 +2247,120 @@ tn(argc, argv) if (hostp == 0) goto usage; -#if defined(IP_OPTIONS) && defined(IPPROTO_IP) + (void) strcpy(_hostname, hostp); if (hostp[0] == '@' || hostp[0] == '!') { - if ((hostname = strrchr(hostp, ':')) == NULL) - hostname = strrchr(hostp, '@'); - hostname++; - srp = 0; - temp = sourceroute(hostp, &srp, &srlen); - if (temp == 0) { - herror(srp); + char *p; + hostname = NULL; + for (p = hostp + 1; *p; p++) { + if (*p == ',' || *p == '@') + hostname = p; + } + if (hostname == NULL) { + fprintf(stderr, "%s: bad source route specification\n", hostp); setuid(getuid()); return 0; - } else if (temp == -1) { - printf("Bad source route option: %s\n", hostp); - setuid(getuid()); - 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; - host = gethostbyaddr((char *)&temp, sizeof(temp), AF_INET); - if (host) - (void) strcpy(_hostname, host->h_name); - else - (void) strcpy(_hostname, hostp); - 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) + *hostname++ = '\0'; + } else + hostname = hostp; + + if (!portp) { + telnetport = 1; + portp = "telnet"; } -#endif - 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); - } + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_NUMERICHOST; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + error = getaddrinfo(hostname, portp, &hints, &res); + if (!error) { + /*numeric*/ + freeaddrinfo(res); + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + error = getaddrinfo(hostname, portp, &hints, &res); } 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; + /*non-numeric*/ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + error = getaddrinfo(hostname, portp, &hints, &res); } - printf("Trying %s...\n", inet_ntoa(sin.sin_addr)); + if (error) { + fprintf(stderr, "%s: %s\n", hostname, gai_strerror(error)); + setuid(getuid()); + return 0; + } + + if (res->ai_canonname) + (void) strcpy(_hostname, res->ai_canonname); + hostname = _hostname; + do { - net = socket(AF_INET, SOCK_STREAM, 0); + printf("Trying %s...\n", sockaddr_ntop(res->ai_addr)); + net = socket(res->ai_family, res->ai_socktype, res->ai_protocol); setuid(getuid()); if (net < 0) { perror("telnet: socket"); return 0; } -#if defined(IP_OPTIONS) && defined(IPPROTO_IP) - if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0) - perror("setsockopt (IP_OPTIONS)"); -#endif -#if defined(IPPROTO_IP) && defined(IP_TOS) - { -# if defined(HAS_GETTOS) - struct tosent *tp; - if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) - tos = tp->t_tos; -# endif - if (tos < 0) - tos = IPTOS_LOWDELAY; /* Low Delay bit */ - if (tos - && (setsockopt(net, IPPROTO_IP, IP_TOS, - (char *)&tos, sizeof(int)) < 0) - && (errno != ENOPROTOOPT)) - perror("telnet: setsockopt (IP_TOS) (ignored)"); - } -#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { perror("setsockopt (SO_DEBUG)"); } + if (hostp[0] == '@' || hostp[0] == '!') { + if ((srlen = sourceroute(res, hostp, &srp, &proto, &opt)) < 0) + continue; + if (srp && setsockopt(net, proto, opt, srp, srlen) < 0) + perror("setsockopt (source route)"); + } +#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) + if (ipsec_policy) { + int len; + char *buf; + int level; + int optname; - if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) { -#if defined(h_addr) /* In 4.3, this is a #define */ - if (host && host->h_addr_list[1]) { + if ((len = ipsec_get_policylen(ipsec_policy)) < 0) { + printf("%s\n", ipsec_strerror()); + return 0; + } + if ((buf = (char *)malloc(len)) == NULL) { + perror("malloc"); + return 0; + } + if ((len = ipsec_set_policy(buf, len, ipsec_policy)) < 0) { + printf("%s\n", ipsec_strerror()); + return 0; + } + 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, len) < 0){ + perror("setsockopt"); + return 0; + } + free(buf); + } +#endif + + if (connect(net, res->ai_addr, res->ai_addrlen) < 0) { + if (res->ai_next) { int oerrno = errno; fprintf(stderr, "telnet: connect to address %s: ", - inet_ntoa(sin.sin_addr)); + sockaddr_ntop(res->ai_addr)); errno = oerrno; perror((char *)0); - host->h_addr_list++; - memmove((caddr_t)&sin.sin_addr, - host->h_addr_list[0], host->h_length); + res = res->ai_next; (void) NetClose(net); continue; } -#endif /* defined(h_addr) */ perror("telnet: Unable to connect to remote host"); return 0; } @@ -2683,11 +2707,9 @@ cmdrc(m1, m2) fclose(rcfile); } -#if defined(IP_OPTIONS) && defined(IPPROTO_IP) - /* * Source route is handed in as - * [!]@hop1@hop2...[@|:]dst + * [!]@hop1@hop2...@dst * If the leading ! is present, it is a * strict source route, otherwise it is * assmed to be a loose source route. @@ -2724,74 +2746,88 @@ cmdrc(m1, m2) * pointed to by *cpp is. * */ - unsigned long -sourceroute(arg, cpp, lenp) +int +sourceroute(ai, arg, cpp, protop, optp) + struct addrinfo *ai; char *arg; - char **cpp; - unsigned long *lenp; + char **cpp; + int *protop; + int *optp; { - static char lsr[44]; #ifdef sysV88 static IOPTN ipopt; #endif char *cp, *cp2, *lsrp, *lsrep; - register int tmp; - struct in_addr sin_addr; - register struct hostent *host = 0; + struct addrinfo hints, *res; + int len, error; + struct sockaddr_in *sin; register char c; + static char lsr[44]; +#ifdef INET6 + struct cmsghdr *cmsg; + struct sockaddr_in6 *sin6; + static char rhbuf[1024]; +#endif /* - * Verify the arguments, and make sure we have - * at least 7 bytes for the option. + * Verify the arguments. */ - if (cpp == NULL || lenp == NULL) - return((unsigned long)-1); - if (*cpp != NULL && *lenp < 7) - return((unsigned long)-1); - /* - * Decide whether we have a buffer passed to us, - * or if we need to use our own static buffer. - */ - if (*cpp) { - lsrp = *cpp; - lsrep = lsrp + *lenp; - } else { - *cpp = lsrp = lsr; - lsrep = lsrp + 44; - } + if (cpp == NULL) + return -1; cp = arg; - /* - * Next, decide whether we have a loose source - * route or a strict source route, and fill in - * the begining of the option. - */ + *cpp = NULL; + switch (ai->ai_family) { + case AF_INET: + lsrp = lsr; + lsrep = lsrp + sizeof(lsr); + + /* + * Next, decide whether we have a loose source + * route or a strict source route, and fill in + * the begining of the option. + */ #ifndef sysV88 - if (*cp == '!') { - cp++; - *lsrp++ = IPOPT_SSRR; - } else - *lsrp++ = IPOPT_LSRR; + if (*cp == '!') { + cp++; + *lsrp++ = IPOPT_SSRR; + } else + *lsrp++ = IPOPT_LSRR; #else - if (*cp == '!') { - cp++; - ipopt.io_type = IPOPT_SSRR; - } else - ipopt.io_type = IPOPT_LSRR; + if (*cp == '!') { + cp++; + ipopt.io_type = IPOPT_SSRR; + } else + ipopt.io_type = IPOPT_LSRR; #endif - - if (*cp != '@') - return((unsigned long)-1); - + if (*cp != '@') + return -1; #ifndef sysV88 - lsrp++; /* skip over length, we'll fill it in later */ - *lsrp++ = 4; + lsrp++; /* skip over length, we'll fill it in later */ + *lsrp++ = 4; #endif + cp++; + *protop = IPPROTO_IP; + *optp = IP_OPTIONS; + break; +#ifdef INET6 + case AF_INET6: + cmsg = inet6_rthdr_init(rhbuf, IPV6_RTHDR_TYPE_0); + if (*cp != '@') + return -1; + cp++; + *protop = IPPROTO_IPV6; + *optp = IPV6_PKTOPTIONS; + break; +#endif + default: + return -1; + } - cp++; - - sin_addr.s_addr = 0; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = ai->ai_family; + hints.ai_socktype = SOCK_STREAM; for (c = 0;;) { if (c == ':') @@ -2803,58 +2839,86 @@ sourceroute(arg, cpp, lenp) cp2++; } else if (c == '@') { *cp2++ = '\0'; - } else if (c == ':') { + } +#if 0 /*colon conflicts with IPv6 address*/ + else if (c == ':') { *cp2++ = '\0'; - } else + } +#endif + else continue; break; } if (!c) cp2 = 0; - if ((tmp = inet_addr(cp)) != INADDR_NONE) { - sin_addr.s_addr = tmp; - } else if ((host = gethostbyname(cp)) != NULL) { -#if defined(h_addr) - memmove((caddr_t)&sin_addr, - host->h_addr_list[0], host->h_length); -#else - memmove((caddr_t)&sin_addr, host->h_addr, host->h_length); -#endif - } else { - *cpp = cp; - return(0); + error = getaddrinfo(cp, NULL, &hints, &res); + if (error) { + fprintf(stderr, "%s: %s\n", cp, gai_strerror(error)); + return -1; } - memmove(lsrp, (char *)&sin_addr, 4); - lsrp += 4; + if (ai->ai_family != res->ai_family) { + freeaddrinfo(res); + return -1; + } + if (ai->ai_family == AF_INET) { + /* + * Check to make sure there is space for address + */ + if (lsrp + 4 > lsrep) { + freeaddrinfo(res); + return -1; + } + sin = (struct sockaddr_in *)res->ai_addr; + memcpy(lsrp, &sin->sin_addr, sizeof(struct in_addr)); + lsrp += sizeof(struct in_addr); + } +#ifdef INET6 + else if (ai->ai_family == AF_INET6) { + sin6 = (struct sockaddr_in6 *)res->ai_addr; + inet6_rthdr_add(cmsg, &sin6->sin6_addr, + IPV6_RTHDR_LOOSE); + } +#endif + else { + freeaddrinfo(res); + return -1; + } + freeaddrinfo(res); if (cp2) cp = cp2; else break; - /* - * Check to make sure there is space for next address - */ + } + if (ai->ai_family == AF_INET) { + /* record the last hop */ if (lsrp + 4 > lsrep) - return((unsigned long)-1); - } + return -1; + sin = (struct sockaddr_in *)ai->ai_addr; + memcpy(lsrp, &sin->sin_addr, sizeof(struct in_addr)); + lsrp += sizeof(struct in_addr); #ifndef sysV88 - if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) { - *cpp = 0; - *lenp = 0; - return((unsigned long)-1); - } - *lsrp++ = IPOPT_NOP; /* 32 bit word align it */ - *lenp = lsrp - *cpp; + lsr[IPOPT_OLEN] = lsrp - lsr; + if (lsr[IPOPT_OLEN] <= 7 || lsr[IPOPT_OLEN] > 40) + return -1; + *lsrp++ = IPOPT_NOP; /*32bit word align*/ + len = lsrp - lsr; + *cpp = lsr; #else - ipopt.io_len = lsrp - *cpp; - if (ipopt.io_len <= 5) { /* Is 3 better ? */ - *cpp = 0; - *lenp = 0; - return((unsigned long)-1); + ipopt.io_len = lsrp - lsr; + if (ipopt.io_len <= 5) /*is 3 better?*/ + return -1; + *cpp = (char 8)&ipopt; +#endif + } +#ifdef INET6 + else if (ai->ai_family == AF_INET6) { + inet6_rthdr_lasthop(cmsg, IPV6_RTHDR_LOOSE); + len = cmsg->cmsg_len; + *cpp = rhbuf; } - *lenp = sizeof(ipopt); - *cpp = (char *) &ipopt; #endif - return(sin_addr.s_addr); + else + return -1; + return len; } -#endif diff --git a/usr.bin/telnet/externs.h b/usr.bin/telnet/externs.h index c17250cf1333..fb8889154c96 100644 --- a/usr.bin/telnet/externs.h +++ b/usr.bin/telnet/externs.h @@ -1,4 +1,4 @@ -/* $NetBSD: externs.h,v 1.13 1998/12/20 14:48:33 christos Exp $ */ +/* $NetBSD: externs.h,v 1.14 1999/07/02 15:09:10 itojun Exp $ */ /* * Copyright (c) 1988, 1990, 1993 @@ -94,6 +94,13 @@ typedef unsigned char cc_t; #include #endif +#if defined(IPSEC) +#include +#if defined(IPSEC_POLICY_IPSEC) +extern char *ipsec_policy; +#endif +#endif + #ifndef _POSIX_VDISABLE # ifdef sun # include /* pick up VDISABLE definition, mayby */ @@ -275,7 +282,8 @@ int ayt_status P((void)); int tn P((int, char *[])); void command P((int, char *, int)); void cmdrc P((const char *, const char *)); -unsigned long sourceroute P((char *, char **, unsigned long *)); +struct addrinfo; +int sourceroute P((struct addrinfo *, char *, char **, int *, int*)); /* main.c */ void tninit P((void)); diff --git a/usr.bin/telnet/main.c b/usr.bin/telnet/main.c index 3ae2dbe042b6..c7fa114ff38a 100644 --- a/usr.bin/telnet/main.c +++ b/usr.bin/telnet/main.c @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.8 1998/02/28 12:16:56 enami Exp $ */ +/* $NetBSD: main.c,v 1.9 1999/07/02 15:09:10 itojun Exp $ */ /* * Copyright (c) 1988, 1990, 1993 @@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1988, 1990, 1993\n\ #if 0 static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 5/30/95"; #else -__RCSID("$NetBSD: main.c,v 1.8 1998/02/28 12:16:56 enami Exp $"); +__RCSID("$NetBSD: main.c,v 1.9 1999/07/02 15:09:10 itojun Exp $"); #endif #endif /* not lint */ @@ -64,6 +64,10 @@ __RCSID("$NetBSD: main.c,v 1.8 1998/02/28 12:16:56 enami Exp $"); #define FORWARD #endif +#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) +char *ipsec_policy = NULL; +#endif + int main P((int, char *[])); /* @@ -106,7 +110,11 @@ usage() #else "[-r] ", #endif +#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) + "[-P policy] [host-name [port]]" +#else "[host-name [port]]" +#endif ); exit(1); } @@ -146,7 +154,14 @@ main(argc, argv) rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE; autologin = -1; - while ((ch = getopt(argc, argv, "8EKLS:X:acde:fFk:l:n:rt:x")) != -1) { +#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) +#define IPSECOPT "P:" +#else +#define IPSECOPT +#endif + while ((ch = getopt(argc, argv, "8EKLS:X:acde:fFk:l:n:rt:x" + IPSECOPT)) != -1) { +#undef IPSECOPT switch(ch) { case '8': eight = 3; /* binary output and input */ @@ -278,6 +293,11 @@ main(argc, argv) "%s: Warning: -x ignored, no ENCRYPT support.\n", prompt); break; +#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) + case 'P': + ipsec_policy = strdup(optarg); + break; +#endif case '?': default: usage(); diff --git a/usr.bin/telnet/telnet.1 b/usr.bin/telnet/telnet.1 index d6081f9117c0..34a55fa52306 100644 --- a/usr.bin/telnet/telnet.1 +++ b/usr.bin/telnet/telnet.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: telnet.1,v 1.11 1999/03/22 18:16:44 garbled Exp $ +.\" $NetBSD: telnet.1,v 1.12 1999/07/02 15:09:11 itojun Exp $ .\" .\" Copyright (c) 1983, 1990, 1993 .\" The Regents of the University of California. All rights reserved. @@ -70,6 +70,9 @@ protocol .Bk -words .Op Fl n Ar tracefile .Ek +.Bk -words +.Op Fl P Ar policy +.Ek .Op Fl r .Op Fl x .Oo @@ -190,6 +193,13 @@ for recording trace information. See the .Ic set tracefile command below. +.It Fl P Ar policy +Use IPsec policy specification string +.Ar policy , +for the connections. +See +.Xr ipsec_set_policy 3 +for details. .It Fl r Specifies a user interface similar to .Xr rlogin 1 . @@ -1375,6 +1385,7 @@ The .Nm Telnet command appeared in .Bx 4.2 . +IPsec support was added by WIDE/KAME project, in 1999. .Sh NOTES .Pp On some remote systems, echo has to be turned off manually when in