1*4882a593SmuzhiyunFrom f09a6460a62aacb87bb8683d16aa3ce55848bf7e Mon Sep 17 00:00:00 2001 2*4882a593SmuzhiyunFrom: Li xin <lixin.fnst@cn.fujitsu.com> 3*4882a593SmuzhiyunDate: Fri, 28 Nov 2014 07:06:24 +0900 4*4882a593SmuzhiyunSubject: [PATCH 1/2] To aviod buffer overflow in telnet 5*4882a593Smuzhiyun 6*4882a593SmuzhiyunThis patch is from Fedora. 7*4882a593Smuzhiyun 8*4882a593SmuzhiyunUpstream-Status: pending 9*4882a593Smuzhiyun 10*4882a593SmuzhiyunSigned-off-by: Li Xin <lixin.fnst@cn.fujitsu.com> 11*4882a593Smuzhiyun--- 12*4882a593Smuzhiyun telnet/Makefile | 4 +- 13*4882a593Smuzhiyun telnet/commands.cc | 270 +++++++++++++++++++++++++++++++++++----------------- 14*4882a593Smuzhiyun telnet/defines.h | 2 + 15*4882a593Smuzhiyun telnet/externs.h | 7 +- 16*4882a593Smuzhiyun telnet/main.cc | 65 ++++++++++--- 17*4882a593Smuzhiyun telnet/netlink.cc | 78 +++++++++------ 18*4882a593Smuzhiyun telnet/netlink.h | 7 +- 19*4882a593Smuzhiyun telnet/network.cc | 1 + 20*4882a593Smuzhiyun telnet/proto.h | 2 +- 21*4882a593Smuzhiyun telnet/ring.cc | 2 +- 22*4882a593Smuzhiyun telnet/ring.h | 2 +- 23*4882a593Smuzhiyun telnet/sys_bsd.cc | 11 +++ 24*4882a593Smuzhiyun telnet/telnet.1 | 37 +++++-- 25*4882a593Smuzhiyun telnet/telnet.cc | 45 +++++---- 26*4882a593Smuzhiyun telnet/terminal.cc | 17 +++- 27*4882a593Smuzhiyun telnet/utilities.cc | 2 + 28*4882a593Smuzhiyun 16 files changed, 380 insertions(+), 172 deletions(-) 29*4882a593Smuzhiyun 30*4882a593Smuzhiyundiff --git a/telnet/Makefile b/telnet/Makefile 31*4882a593Smuzhiyunindex cef866f..39249e1 100644 32*4882a593Smuzhiyun--- a/telnet/Makefile 33*4882a593Smuzhiyun+++ b/telnet/Makefile 34*4882a593Smuzhiyun@@ -7,7 +7,7 @@ include ../MRULES 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun # -DAUTHENTICATE 37*4882a593Smuzhiyun CXXFLAGS += -DUSE_TERMIO -DKLUDGELINEMODE 38*4882a593Smuzhiyun-LIBS += $(LIBTERMCAP) 39*4882a593Smuzhiyun+LIBS = $(LIBTERMCAP) 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun SRCS = commands.cc main.cc network.cc ring.cc sys_bsd.cc telnet.cc \ 42*4882a593Smuzhiyun terminal.cc tn3270.cc utilities.cc genget.cc environ.cc netlink.cc 43*4882a593Smuzhiyun@@ -22,7 +22,7 @@ depend: 44*4882a593Smuzhiyun $(CXX) $(CXXFLAGS) -MM $(SRCS) >depend.mk 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun install: telnet 47*4882a593Smuzhiyun- install -s -m$(BINMODE) telnet $(INSTALLROOT)$(BINDIR) 48*4882a593Smuzhiyun+ install -m$(BINMODE) telnet $(INSTALLROOT)$(BINDIR) 49*4882a593Smuzhiyun install -m$(MANMODE) telnet.1 $(INSTALLROOT)$(MANDIR)/man1 50*4882a593Smuzhiyun 51*4882a593Smuzhiyun clean: 52*4882a593Smuzhiyundiff --git a/telnet/commands.cc b/telnet/commands.cc 53*4882a593Smuzhiyunindex d92bccd..02c593e 100644 54*4882a593Smuzhiyun--- a/telnet/commands.cc 55*4882a593Smuzhiyun+++ b/telnet/commands.cc 56*4882a593Smuzhiyun@@ -86,10 +86,6 @@ char cmd_rcsid[] = 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun #define HELPINDENT ((int) sizeof ("connect")) 59*4882a593Smuzhiyun 60*4882a593Smuzhiyun-#ifndef MAXHOSTNAMELEN 61*4882a593Smuzhiyun-#define MAXHOSTNAMELEN 64 62*4882a593Smuzhiyun-#endif MAXHOSTNAMELEN 63*4882a593Smuzhiyun- 64*4882a593Smuzhiyun #if defined(HAS_IPPROTO_IP) && defined(IP_TOS) 65*4882a593Smuzhiyun int tos = -1; 66*4882a593Smuzhiyun #endif /* defined(HAS_IPPROTO_IP) && defined(IP_TOS) */ 67*4882a593Smuzhiyun@@ -98,7 +94,7 @@ static unsigned long sourceroute(char *arg, char **cpp, int *lenp); 68*4882a593Smuzhiyun 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun char *hostname; 71*4882a593Smuzhiyun-static char _hostname[MAXHOSTNAMELEN]; 72*4882a593Smuzhiyun+static char *_hostname; 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun //typedef int (*intrtn_t)(int argc, const char *argv[]); 75*4882a593Smuzhiyun 76*4882a593Smuzhiyun@@ -161,7 +157,7 @@ class command_entry { 77*4882a593Smuzhiyun assert(argc>=1); 78*4882a593Smuzhiyun if (nargs>=0 && argc!=nargs+1) { 79*4882a593Smuzhiyun fprintf(stderr, "Wrong number of arguments for command.\n"); 80*4882a593Smuzhiyun- fprintf(stderr, "Try %s ? for help\n", argv[0]); 81*4882a593Smuzhiyun+ fprintf(stderr, "Try ? %s for help\n", argv[0]); 82*4882a593Smuzhiyun return 0; /* is this right? */ 83*4882a593Smuzhiyun } 84*4882a593Smuzhiyun if (nargs==-2) { 85*4882a593Smuzhiyun@@ -480,6 +476,7 @@ static int send_wontcmd(const char *name, const char *) { 86*4882a593Smuzhiyun int send_tncmd(int (*func)(int, int), const char *cmd, const char *name) { 87*4882a593Smuzhiyun char **cpp; 88*4882a593Smuzhiyun extern char *telopts[]; 89*4882a593Smuzhiyun+ long opt; 90*4882a593Smuzhiyun 91*4882a593Smuzhiyun if (isprefix(name, "help") || isprefix(name, "?")) { 92*4882a593Smuzhiyun register int col, len; 93*4882a593Smuzhiyun@@ -506,16 +503,23 @@ int send_tncmd(int (*func)(int, int), const char *cmd, const char *name) { 94*4882a593Smuzhiyun name, cmd); 95*4882a593Smuzhiyun return 0; 96*4882a593Smuzhiyun } 97*4882a593Smuzhiyun+ 98*4882a593Smuzhiyun+ opt = cpp - telopts; 99*4882a593Smuzhiyun if (cpp == 0) { 100*4882a593Smuzhiyun- fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n", 101*4882a593Smuzhiyun+ char *end; 102*4882a593Smuzhiyun+ 103*4882a593Smuzhiyun+ opt = strtol(name, &end, 10); 104*4882a593Smuzhiyun+ if (*end || opt < 0 || opt > 255) { 105*4882a593Smuzhiyun+ fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n", 106*4882a593Smuzhiyun name, cmd); 107*4882a593Smuzhiyun- return 0; 108*4882a593Smuzhiyun+ return 0; 109*4882a593Smuzhiyun+ } 110*4882a593Smuzhiyun } 111*4882a593Smuzhiyun if (!connected) { 112*4882a593Smuzhiyun printf("?Need to be connected first.\n"); 113*4882a593Smuzhiyun return 0; 114*4882a593Smuzhiyun } 115*4882a593Smuzhiyun- (*func)(cpp - telopts, 1); 116*4882a593Smuzhiyun+ (*func)(opt, 1); 117*4882a593Smuzhiyun return 1; 118*4882a593Smuzhiyun } 119*4882a593Smuzhiyun 120*4882a593Smuzhiyun@@ -689,9 +693,9 @@ static struct togglelist Togglelist[] = { 121*4882a593Smuzhiyun "print encryption debugging information" }, 122*4882a593Smuzhiyun #endif 123*4882a593Smuzhiyun 124*4882a593Smuzhiyun- { "skiprc", "don't read ~/.telnetrc file", 125*4882a593Smuzhiyun+ { "skiprc", "don't read the telnetrc files", 126*4882a593Smuzhiyun NULL, &skiprc, 127*4882a593Smuzhiyun- "read ~/.telnetrc file" }, 128*4882a593Smuzhiyun+ "read the telnetrc files" }, 129*4882a593Smuzhiyun { "binary", 130*4882a593Smuzhiyun "sending and receiving of binary data", 131*4882a593Smuzhiyun togbinary, NULL, 132*4882a593Smuzhiyun@@ -1615,15 +1619,20 @@ void ayt_status(int) { 133*4882a593Smuzhiyun #endif 134*4882a593Smuzhiyun 135*4882a593Smuzhiyun int tn(int argc, const char *argv[]) { 136*4882a593Smuzhiyun- register struct hostent *host = 0; 137*4882a593Smuzhiyun struct sockaddr_in sn; 138*4882a593Smuzhiyun- struct servent *sp = 0; 139*4882a593Smuzhiyun char *srp = NULL; 140*4882a593Smuzhiyun int srlen; 141*4882a593Smuzhiyun- 142*4882a593Smuzhiyun- const char *cmd, *volatile user = 0; 143*4882a593Smuzhiyun+ int family = 0; 144*4882a593Smuzhiyun+ const char *cmd, *volatile user = 0, *srchostp = 0; 145*4882a593Smuzhiyun const char *portp = NULL; 146*4882a593Smuzhiyun char *hostp = NULL; 147*4882a593Smuzhiyun+ char *resolv_hostp; 148*4882a593Smuzhiyun+ struct addrinfo hints; 149*4882a593Smuzhiyun+ struct addrinfo *hostaddr = 0; 150*4882a593Smuzhiyun+ int res; 151*4882a593Smuzhiyun+ char name[NI_MAXHOST]; 152*4882a593Smuzhiyun+ char service[NI_MAXSERV]; 153*4882a593Smuzhiyun+ struct addrinfo *tmpaddr; 154*4882a593Smuzhiyun 155*4882a593Smuzhiyun /* clear the socket address prior to use */ 156*4882a593Smuzhiyun memset(&sn, 0, sizeof(sn)); 157*4882a593Smuzhiyun@@ -1632,6 +1641,10 @@ int tn(int argc, const char *argv[]) { 158*4882a593Smuzhiyun printf("?Already connected to %s\n", hostname); 159*4882a593Smuzhiyun return 0; 160*4882a593Smuzhiyun } 161*4882a593Smuzhiyun+ if (_hostname) { 162*4882a593Smuzhiyun+ delete[] _hostname; 163*4882a593Smuzhiyun+ _hostname = 0; 164*4882a593Smuzhiyun+ } 165*4882a593Smuzhiyun if (argc < 2) { 166*4882a593Smuzhiyun (void) strcpy(line, "open "); 167*4882a593Smuzhiyun printf("(to) "); 168*4882a593Smuzhiyun@@ -1657,11 +1670,33 @@ int tn(int argc, const char *argv[]) { 169*4882a593Smuzhiyun --argc; 170*4882a593Smuzhiyun continue; 171*4882a593Smuzhiyun } 172*4882a593Smuzhiyun+ if (strcmp(*argv, "-b") == 0) { 173*4882a593Smuzhiyun+ --argc; ++argv; 174*4882a593Smuzhiyun+ if (argc == 0) 175*4882a593Smuzhiyun+ goto usage; 176*4882a593Smuzhiyun+ srchostp = *argv++; 177*4882a593Smuzhiyun+ --argc; 178*4882a593Smuzhiyun+ continue; 179*4882a593Smuzhiyun+ } 180*4882a593Smuzhiyun if (strcmp(*argv, "-a") == 0) { 181*4882a593Smuzhiyun --argc; ++argv; 182*4882a593Smuzhiyun autologin = 1; 183*4882a593Smuzhiyun continue; 184*4882a593Smuzhiyun } 185*4882a593Smuzhiyun+ if (strcmp(*argv, "-6") == 0) { 186*4882a593Smuzhiyun+ --argc; ++argv; 187*4882a593Smuzhiyun+#ifdef AF_INET6 188*4882a593Smuzhiyun+ family = AF_INET6; 189*4882a593Smuzhiyun+#else 190*4882a593Smuzhiyun+ puts("IPv6 unsupported"); 191*4882a593Smuzhiyun+#endif 192*4882a593Smuzhiyun+ continue; 193*4882a593Smuzhiyun+ } 194*4882a593Smuzhiyun+ if (strcmp(*argv, "-4") == 0) { 195*4882a593Smuzhiyun+ --argc; ++argv; 196*4882a593Smuzhiyun+ family = AF_INET; 197*4882a593Smuzhiyun+ continue; 198*4882a593Smuzhiyun+ } 199*4882a593Smuzhiyun if (hostp == 0) { 200*4882a593Smuzhiyun /* this leaks memory - FIXME */ 201*4882a593Smuzhiyun hostp = strdup(*argv++); 202*4882a593Smuzhiyun@@ -1680,6 +1715,8 @@ int tn(int argc, const char *argv[]) { 203*4882a593Smuzhiyun if (hostp == 0) 204*4882a593Smuzhiyun goto usage; 205*4882a593Smuzhiyun 206*4882a593Smuzhiyun+ resolv_hostp = hostp; 207*4882a593Smuzhiyun+ 208*4882a593Smuzhiyun #if defined(IP_OPTIONS) && defined(HAS_IPPROTO_IP) 209*4882a593Smuzhiyun if (hostp[0] == '@' || hostp[0] == '!') { 210*4882a593Smuzhiyun if ((hostname = strrchr(hostp, ':')) == NULL) 211*4882a593Smuzhiyun@@ -1696,78 +1733,122 @@ int tn(int argc, const char *argv[]) { 212*4882a593Smuzhiyun } else { 213*4882a593Smuzhiyun sn.sin_addr.s_addr = temp; 214*4882a593Smuzhiyun sn.sin_family = AF_INET; 215*4882a593Smuzhiyun+ /* 216*4882a593Smuzhiyun+ * For source route we just make sure to get the IP given 217*4882a593Smuzhiyun+ * on the command line when looking up the port. 218*4882a593Smuzhiyun+ */ 219*4882a593Smuzhiyun+ resolv_hostp = inet_ntoa(sn.sin_addr); 220*4882a593Smuzhiyun } 221*4882a593Smuzhiyun } 222*4882a593Smuzhiyun- else { 223*4882a593Smuzhiyun-#endif 224*4882a593Smuzhiyun- if (inet_aton(hostp, &sn.sin_addr)) { 225*4882a593Smuzhiyun- sn.sin_family = AF_INET; 226*4882a593Smuzhiyun- strcpy(_hostname, hostp); 227*4882a593Smuzhiyun- hostname = _hostname; 228*4882a593Smuzhiyun- } 229*4882a593Smuzhiyun- else { 230*4882a593Smuzhiyun- host = gethostbyname(hostp); 231*4882a593Smuzhiyun- if (host) { 232*4882a593Smuzhiyun- sn.sin_family = host->h_addrtype; 233*4882a593Smuzhiyun- if (host->h_length > (int)sizeof(sn.sin_addr)) { 234*4882a593Smuzhiyun- host->h_length = sizeof(sn.sin_addr); 235*4882a593Smuzhiyun- } 236*4882a593Smuzhiyun-#if defined(h_addr) /* In 4.3, this is a #define */ 237*4882a593Smuzhiyun- memcpy((caddr_t)&sn.sin_addr, 238*4882a593Smuzhiyun- host->h_addr_list[0], host->h_length); 239*4882a593Smuzhiyun-#else /* defined(h_addr) */ 240*4882a593Smuzhiyun- memcpy((caddr_t)&sn.sin_addr, host->h_addr, host->h_length); 241*4882a593Smuzhiyun-#endif /* defined(h_addr) */ 242*4882a593Smuzhiyun- strncpy(_hostname, host->h_name, sizeof(_hostname)); 243*4882a593Smuzhiyun- _hostname[sizeof(_hostname)-1] = '\0'; 244*4882a593Smuzhiyun- hostname = _hostname; 245*4882a593Smuzhiyun- } else { 246*4882a593Smuzhiyun- herror(hostp); 247*4882a593Smuzhiyun- return 0; 248*4882a593Smuzhiyun- } 249*4882a593Smuzhiyun- } 250*4882a593Smuzhiyun-#if defined(IP_OPTIONS) && defined(HAS_IPPROTO_IP) 251*4882a593Smuzhiyun- } 252*4882a593Smuzhiyun #endif 253*4882a593Smuzhiyun+ 254*4882a593Smuzhiyun+ /* User port or the default name of telnet. */ 255*4882a593Smuzhiyun if (portp) { 256*4882a593Smuzhiyun if (*portp == '-') { 257*4882a593Smuzhiyun portp++; 258*4882a593Smuzhiyun telnetport = 1; 259*4882a593Smuzhiyun- } else 260*4882a593Smuzhiyun+ } else { 261*4882a593Smuzhiyun telnetport = 0; 262*4882a593Smuzhiyun- sn.sin_port = atoi(portp); 263*4882a593Smuzhiyun- if (sn.sin_port == 0) { 264*4882a593Smuzhiyun- sp = getservbyname(portp, "tcp"); 265*4882a593Smuzhiyun- if (sp) 266*4882a593Smuzhiyun- sn.sin_port = sp->s_port; 267*4882a593Smuzhiyun- else { 268*4882a593Smuzhiyun- printf("%s: bad port number\n", portp); 269*4882a593Smuzhiyun- return 0; 270*4882a593Smuzhiyun+ if (*portp >='0' && *portp<='9') { 271*4882a593Smuzhiyun+ char *end; 272*4882a593Smuzhiyun+ long int p; 273*4882a593Smuzhiyun+ 274*4882a593Smuzhiyun+ p=strtol(portp, &end, 10); 275*4882a593Smuzhiyun+ if (ERANGE==errno && (LONG_MIN==p || LONG_MAX==p)) { 276*4882a593Smuzhiyun+ fprintf(stderr, "telnet: port %s overflows\n", portp); 277*4882a593Smuzhiyun+ return 0; 278*4882a593Smuzhiyun+ } else if (p<=0 || p>=65536) { 279*4882a593Smuzhiyun+ fprintf(stderr, "telnet: port %s out of range\n", portp); 280*4882a593Smuzhiyun+ return 0; 281*4882a593Smuzhiyun+ } 282*4882a593Smuzhiyun } 283*4882a593Smuzhiyun- } 284*4882a593Smuzhiyun- else { 285*4882a593Smuzhiyun- sn.sin_port = htons(sn.sin_port); 286*4882a593Smuzhiyun } 287*4882a593Smuzhiyun- } 288*4882a593Smuzhiyun+ } 289*4882a593Smuzhiyun else { 290*4882a593Smuzhiyun- if (sp == 0) { 291*4882a593Smuzhiyun- sp = getservbyname("telnet", "tcp"); 292*4882a593Smuzhiyun- if (sp == 0) { 293*4882a593Smuzhiyun- fprintf(stderr, "telnet: tcp/telnet: unknown service\n"); 294*4882a593Smuzhiyun- return 0; 295*4882a593Smuzhiyun- } 296*4882a593Smuzhiyun- sn.sin_port = sp->s_port; 297*4882a593Smuzhiyun- } 298*4882a593Smuzhiyun+ portp = "telnet"; 299*4882a593Smuzhiyun telnetport = 1; 300*4882a593Smuzhiyun } 301*4882a593Smuzhiyun- printf("Trying %s...\n", inet_ntoa(sn.sin_addr)); 302*4882a593Smuzhiyun+ 303*4882a593Smuzhiyun+ /* We only understand SOCK_STREAM sockets. */ 304*4882a593Smuzhiyun+ memset(&hints, 0, sizeof(hints)); 305*4882a593Smuzhiyun+ hints.ai_socktype = SOCK_STREAM; 306*4882a593Smuzhiyun+ hints.ai_flags = AI_NUMERICHOST; 307*4882a593Smuzhiyun+ hints.ai_family = family; 308*4882a593Smuzhiyun+ 309*4882a593Smuzhiyun+ if (srchostp) { 310*4882a593Smuzhiyun+ res = getaddrinfo(srchostp, "0", &hints, &hostaddr); 311*4882a593Smuzhiyun+ if (res) { 312*4882a593Smuzhiyun+ fprintf(stderr, "telnet: could not resolve %s: %s\n", srchostp, 313*4882a593Smuzhiyun+ gai_strerror(res)); 314*4882a593Smuzhiyun+ return 0; 315*4882a593Smuzhiyun+ } 316*4882a593Smuzhiyun+ hints.ai_family = hostaddr->ai_family; 317*4882a593Smuzhiyun+ res = nlink.bind(hostaddr); 318*4882a593Smuzhiyun+ freeaddrinfo(hostaddr); 319*4882a593Smuzhiyun+ if (res < 0) 320*4882a593Smuzhiyun+ return 0; 321*4882a593Smuzhiyun+ } 322*4882a593Smuzhiyun+ 323*4882a593Smuzhiyun+ /* Resolve both the host and service simultaneously. */ 324*4882a593Smuzhiyun+ res = getaddrinfo(resolv_hostp, portp, &hints, &hostaddr); 325*4882a593Smuzhiyun+ if (res == EAI_NONAME) { 326*4882a593Smuzhiyun+ hints.ai_flags = AI_CANONNAME; 327*4882a593Smuzhiyun+ res = getaddrinfo(resolv_hostp, portp, &hints, &hostaddr); 328*4882a593Smuzhiyun+ } else if (hostaddr) { 329*4882a593Smuzhiyun+ hostaddr->ai_canonname = 0; 330*4882a593Smuzhiyun+ } 331*4882a593Smuzhiyun+ if (res || !hostaddr) { 332*4882a593Smuzhiyun+ fprintf(stderr, "telnet: could not resolve %s/%s: %s\n", resolv_hostp, portp, gai_strerror(res)); 333*4882a593Smuzhiyun+ return 0; 334*4882a593Smuzhiyun+ } 335*4882a593Smuzhiyun+ 336*4882a593Smuzhiyun+ /* Try to connect to every listed round robin IP. */ 337*4882a593Smuzhiyun+ tmpaddr = hostaddr; 338*4882a593Smuzhiyun+ errno = 0; 339*4882a593Smuzhiyun do { 340*4882a593Smuzhiyun- int x = nlink.connect(debug, host, &sn, srp, srlen, tos); 341*4882a593Smuzhiyun- if (!x) return 0; 342*4882a593Smuzhiyun- else if (x==1) continue; 343*4882a593Smuzhiyun+ int x; 344*4882a593Smuzhiyun+ 345*4882a593Smuzhiyun+ if (!tmpaddr) { 346*4882a593Smuzhiyun+ if (errno) 347*4882a593Smuzhiyun+ perror("telnet: Unable to connect to remote host"); 348*4882a593Smuzhiyun+ else 349*4882a593Smuzhiyun+ fputs("telnet: Unable to connect to remote host: " 350*4882a593Smuzhiyun+ "Bad port number\n", stderr); 351*4882a593Smuzhiyun+err: 352*4882a593Smuzhiyun+ freeaddrinfo(hostaddr); 353*4882a593Smuzhiyun+ return 0; 354*4882a593Smuzhiyun+ } 355*4882a593Smuzhiyun+ 356*4882a593Smuzhiyun+ if (tmpaddr->ai_family == AF_UNIX) { 357*4882a593Smuzhiyun+nextaddr: 358*4882a593Smuzhiyun+ tmpaddr = tmpaddr->ai_next; 359*4882a593Smuzhiyun+ continue; 360*4882a593Smuzhiyun+ } 361*4882a593Smuzhiyun+ 362*4882a593Smuzhiyun+ getnameinfo(tmpaddr->ai_addr, tmpaddr->ai_addrlen, 363*4882a593Smuzhiyun+ name, sizeof(name), service, sizeof(service), 364*4882a593Smuzhiyun+ NI_NUMERICHOST | NI_NUMERICSERV); 365*4882a593Smuzhiyun+ 366*4882a593Smuzhiyun+ printf("Trying %s...\n", name); 367*4882a593Smuzhiyun+ x = nlink.connect(debug, tmpaddr, srp, srlen, tos); 368*4882a593Smuzhiyun+ if (!x) 369*4882a593Smuzhiyun+ goto err; 370*4882a593Smuzhiyun+ else if (x==1) 371*4882a593Smuzhiyun+ goto nextaddr; 372*4882a593Smuzhiyun+ 373*4882a593Smuzhiyun connected++; 374*4882a593Smuzhiyun } while (connected == 0); 375*4882a593Smuzhiyun- cmdrc(hostp, hostname); 376*4882a593Smuzhiyun+ if (tmpaddr->ai_canonname == 0) { 377*4882a593Smuzhiyun+ hostname = new char[strlen(hostp)+1]; 378*4882a593Smuzhiyun+ strcpy(hostname, hostp); 379*4882a593Smuzhiyun+ } 380*4882a593Smuzhiyun+ else { 381*4882a593Smuzhiyun+ hostname = new char[strlen(tmpaddr->ai_canonname)+1]; 382*4882a593Smuzhiyun+ strcpy(hostname, tmpaddr->ai_canonname); 383*4882a593Smuzhiyun+ } 384*4882a593Smuzhiyun+ 385*4882a593Smuzhiyun+ cmdrc(hostp, hostname, portp); 386*4882a593Smuzhiyun+ freeaddrinfo(hostaddr); 387*4882a593Smuzhiyun if (autologin && user == NULL) { 388*4882a593Smuzhiyun struct passwd *pw; 389*4882a593Smuzhiyun 390*4882a593Smuzhiyun@@ -2013,30 +2094,21 @@ static int help(command_table *tab, int argc, const char *argv[]) { 391*4882a593Smuzhiyun return 0; 392*4882a593Smuzhiyun } 393*4882a593Smuzhiyun 394*4882a593Smuzhiyun-static char *rcname = 0; 395*4882a593Smuzhiyun-static char rcbuf[128]; 396*4882a593Smuzhiyun- 397*4882a593Smuzhiyun-void cmdrc(const char *m1, const char *m2) { 398*4882a593Smuzhiyun+static void readrc(const char *m1, const char *m2, const char *port, 399*4882a593Smuzhiyun+ const char *rcname) 400*4882a593Smuzhiyun+{ 401*4882a593Smuzhiyun FILE *rcfile; 402*4882a593Smuzhiyun int gotmachine = 0; 403*4882a593Smuzhiyun int l1 = strlen(m1); 404*4882a593Smuzhiyun int l2 = strlen(m2); 405*4882a593Smuzhiyun- char m1save[64]; 406*4882a593Smuzhiyun- 407*4882a593Smuzhiyun- if (skiprc) return; 408*4882a593Smuzhiyun+ int lport = strlen(port); 409*4882a593Smuzhiyun+ char m1save[l1 + 1]; 410*4882a593Smuzhiyun+ char portsave[lport + 1]; 411*4882a593Smuzhiyun 412*4882a593Smuzhiyun strcpy(m1save, m1); 413*4882a593Smuzhiyun m1 = m1save; 414*4882a593Smuzhiyun- 415*4882a593Smuzhiyun- if (rcname == 0) { 416*4882a593Smuzhiyun- rcname = getenv("HOME"); 417*4882a593Smuzhiyun- if (rcname) 418*4882a593Smuzhiyun- strcpy(rcbuf, rcname); 419*4882a593Smuzhiyun- else 420*4882a593Smuzhiyun- rcbuf[0] = '\0'; 421*4882a593Smuzhiyun- strcat(rcbuf, "/.telnetrc"); 422*4882a593Smuzhiyun- rcname = rcbuf; 423*4882a593Smuzhiyun- } 424*4882a593Smuzhiyun+ strcpy(portsave, port); 425*4882a593Smuzhiyun+ port = portsave; 426*4882a593Smuzhiyun 427*4882a593Smuzhiyun rcfile = fopen(rcname, "r"); 428*4882a593Smuzhiyun if (!rcfile) return; 429*4882a593Smuzhiyun@@ -2061,6 +2133,13 @@ void cmdrc(const char *m1, const char *m2) { 430*4882a593Smuzhiyun strncpy(line, &line[7], sizeof(line) - 7); 431*4882a593Smuzhiyun else 432*4882a593Smuzhiyun continue; 433*4882a593Smuzhiyun+ 434*4882a593Smuzhiyun+ if (line[0] == ':') { 435*4882a593Smuzhiyun+ if (!strncasecmp(&line[1], port, lport)) 436*4882a593Smuzhiyun+ continue; 437*4882a593Smuzhiyun+ strncpy(line, &line[lport + 1], sizeof(line) - lport - 1); 438*4882a593Smuzhiyun+ } 439*4882a593Smuzhiyun+ 440*4882a593Smuzhiyun if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n') 441*4882a593Smuzhiyun continue; 442*4882a593Smuzhiyun gotmachine = 1; 443*4882a593Smuzhiyun@@ -2073,6 +2152,21 @@ void cmdrc(const char *m1, const char *m2) { 444*4882a593Smuzhiyun fclose(rcfile); 445*4882a593Smuzhiyun } 446*4882a593Smuzhiyun 447*4882a593Smuzhiyun+void cmdrc(const char *m1, const char *m2, const char *port) { 448*4882a593Smuzhiyun+ char *rcname = NULL; 449*4882a593Smuzhiyun+ 450*4882a593Smuzhiyun+ if (skiprc) return; 451*4882a593Smuzhiyun+ 452*4882a593Smuzhiyun+ readrc(m1, m2, port, "/etc/telnetrc"); 453*4882a593Smuzhiyun+ if (asprintf (&rcname, "%s/.telnetrc", getenv ("HOME")) == -1) 454*4882a593Smuzhiyun+ { 455*4882a593Smuzhiyun+ perror ("asprintf"); 456*4882a593Smuzhiyun+ return; 457*4882a593Smuzhiyun+ } 458*4882a593Smuzhiyun+ readrc(m1, m2, port, rcname); 459*4882a593Smuzhiyun+ free (rcname); 460*4882a593Smuzhiyun+} 461*4882a593Smuzhiyun+ 462*4882a593Smuzhiyun #if defined(IP_OPTIONS) && defined(HAS_IPPROTO_IP) 463*4882a593Smuzhiyun 464*4882a593Smuzhiyun /* 465*4882a593Smuzhiyundiff --git a/telnet/defines.h b/telnet/defines.h 466*4882a593Smuzhiyunindex 2784400..d5edc46 100644 467*4882a593Smuzhiyun--- a/telnet/defines.h 468*4882a593Smuzhiyun+++ b/telnet/defines.h 469*4882a593Smuzhiyun@@ -50,3 +50,5 @@ 470*4882a593Smuzhiyun #define MODE_COMMAND_LINE(m) ((m)==-1) 471*4882a593Smuzhiyun 472*4882a593Smuzhiyun #define CONTROL(x) ((x)&0x1f) /* CTRL(x) is not portable */ 473*4882a593Smuzhiyun+ 474*4882a593Smuzhiyun+#define MODE_OUT8 0x8000 /* binary mode sans -opost */ 475*4882a593Smuzhiyundiff --git a/telnet/externs.h b/telnet/externs.h 476*4882a593Smuzhiyunindex 955df79..0730e8a 100644 477*4882a593Smuzhiyun--- a/telnet/externs.h 478*4882a593Smuzhiyun+++ b/telnet/externs.h 479*4882a593Smuzhiyun@@ -48,9 +48,7 @@ 480*4882a593Smuzhiyun typedef unsigned char cc_t; 481*4882a593Smuzhiyun #endif 482*4882a593Smuzhiyun 483*4882a593Smuzhiyun-#ifdef __linux__ 484*4882a593Smuzhiyun #include <unistd.h> /* get _POSIX_VDISABLE */ 485*4882a593Smuzhiyun-#endif 486*4882a593Smuzhiyun 487*4882a593Smuzhiyun #ifndef _POSIX_VDISABLE 488*4882a593Smuzhiyun #error "Please fix externs.h to define _POSIX_VDISABLE" 489*4882a593Smuzhiyun@@ -60,7 +58,8 @@ typedef unsigned char cc_t; 490*4882a593Smuzhiyun 491*4882a593Smuzhiyun extern int autologin; /* Autologin enabled */ 492*4882a593Smuzhiyun extern int skiprc; /* Don't process the ~/.telnetrc file */ 493*4882a593Smuzhiyun-extern int eight; /* use eight bit mode (binary in and/or out */ 494*4882a593Smuzhiyun+extern int eight; /* use eight bit mode (binary in and/or out) */ 495*4882a593Smuzhiyun+extern int binary; /* use binary option (in and/or out) */ 496*4882a593Smuzhiyun extern int flushout; /* flush output */ 497*4882a593Smuzhiyun extern int connected; /* Are we connected to the other side? */ 498*4882a593Smuzhiyun extern int globalmode; /* Mode tty should be in */ 499*4882a593Smuzhiyun@@ -225,6 +224,8 @@ cc_t *tcval(int); 500*4882a593Smuzhiyun 501*4882a593Smuzhiyun //#if 0 502*4882a593Smuzhiyun extern struct termios new_tc; 503*4882a593Smuzhiyun+extern struct termios old_tc; 504*4882a593Smuzhiyun+ 505*4882a593Smuzhiyun 506*4882a593Smuzhiyun #define termEofChar new_tc.c_cc[VEOF] 507*4882a593Smuzhiyun #define termEraseChar new_tc.c_cc[VERASE] 508*4882a593Smuzhiyundiff --git a/telnet/main.cc b/telnet/main.cc 509*4882a593Smuzhiyunindex b67f2ce..b626e54 100644 510*4882a593Smuzhiyun--- a/telnet/main.cc 511*4882a593Smuzhiyun+++ b/telnet/main.cc 512*4882a593Smuzhiyun@@ -45,7 +45,10 @@ char main_rcsid[] = 513*4882a593Smuzhiyun 514*4882a593Smuzhiyun #include <sys/types.h> 515*4882a593Smuzhiyun #include <getopt.h> 516*4882a593Smuzhiyun+#include <stdlib.h> 517*4882a593Smuzhiyun #include <string.h> 518*4882a593Smuzhiyun+#include <netdb.h> 519*4882a593Smuzhiyun+#include <errno.h> 520*4882a593Smuzhiyun 521*4882a593Smuzhiyun #include "ring.h" 522*4882a593Smuzhiyun #include "externs.h" 523*4882a593Smuzhiyun@@ -80,12 +83,13 @@ tninit(void) 524*4882a593Smuzhiyun void usage(void) { 525*4882a593Smuzhiyun fprintf(stderr, "Usage: %s %s%s%s%s\n", 526*4882a593Smuzhiyun prompt, 527*4882a593Smuzhiyun- " [-8] [-E] [-L] [-a] [-d] [-e char] [-l user] [-n tracefile]", 528*4882a593Smuzhiyun- "\n\t", 529*4882a593Smuzhiyun+ "[-4] [-6] [-8] [-E] [-L] [-a] [-d] [-e char] [-l user]", 530*4882a593Smuzhiyun+ "\n\t[-n tracefile] [ -b addr ]", 531*4882a593Smuzhiyun #ifdef TN3270 532*4882a593Smuzhiyun+ "\n\t" 533*4882a593Smuzhiyun "[-noasynch] [-noasynctty] [-noasyncnet] [-r] [-t transcom]\n\t", 534*4882a593Smuzhiyun #else 535*4882a593Smuzhiyun- "[-r] ", 536*4882a593Smuzhiyun+ " [-r] ", 537*4882a593Smuzhiyun #endif 538*4882a593Smuzhiyun "[host-name [port]]" 539*4882a593Smuzhiyun ); 540*4882a593Smuzhiyun@@ -102,7 +106,8 @@ main(int argc, char *argv[]) 541*4882a593Smuzhiyun extern char *optarg; 542*4882a593Smuzhiyun extern int optind; 543*4882a593Smuzhiyun int ch; 544*4882a593Smuzhiyun- char *user; 545*4882a593Smuzhiyun+ char *user, *srcaddr; 546*4882a593Smuzhiyun+ int family; 547*4882a593Smuzhiyun 548*4882a593Smuzhiyun tninit(); /* Clear out things */ 549*4882a593Smuzhiyun #if defined(CRAY) && !defined(__STDC__) 550*4882a593Smuzhiyun@@ -110,21 +115,38 @@ main(int argc, char *argv[]) 551*4882a593Smuzhiyun #endif 552*4882a593Smuzhiyun 553*4882a593Smuzhiyun TerminalSaveState(); 554*4882a593Smuzhiyun+ if ((old_tc.c_cflag & (CSIZE|PARENB)) != CS8) 555*4882a593Smuzhiyun+ eight = 0; 556*4882a593Smuzhiyun 557*4882a593Smuzhiyun if ((prompt = strrchr(argv[0], '/'))!=NULL) 558*4882a593Smuzhiyun ++prompt; 559*4882a593Smuzhiyun else 560*4882a593Smuzhiyun prompt = argv[0]; 561*4882a593Smuzhiyun 562*4882a593Smuzhiyun- user = NULL; 563*4882a593Smuzhiyun+ user = srcaddr = NULL; 564*4882a593Smuzhiyun+ family = 0; 565*4882a593Smuzhiyun 566*4882a593Smuzhiyun rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE; 567*4882a593Smuzhiyun autologin = -1; 568*4882a593Smuzhiyun 569*4882a593Smuzhiyun- while ((ch = getopt(argc, argv, "8EKLS:X:ade:k:l:n:rt:x")) != EOF) { 570*4882a593Smuzhiyun+ while ((ch = getopt(argc, argv, 571*4882a593Smuzhiyun+ "4678EKLS:X:ab:de:k:l:n:rt:x")) != EOF) { 572*4882a593Smuzhiyun switch(ch) { 573*4882a593Smuzhiyun+ case '4': 574*4882a593Smuzhiyun+ family = AF_INET; 575*4882a593Smuzhiyun+ break; 576*4882a593Smuzhiyun+ case '6': 577*4882a593Smuzhiyun+#ifdef AF_INET6 578*4882a593Smuzhiyun+ family = AF_INET6; 579*4882a593Smuzhiyun+#else 580*4882a593Smuzhiyun+ fputs("IPv6 unsupported\n", stderr); 581*4882a593Smuzhiyun+#endif 582*4882a593Smuzhiyun+ break; 583*4882a593Smuzhiyun+ case '7': 584*4882a593Smuzhiyun+ eight = 0; /* 7-bit ouput and input */ 585*4882a593Smuzhiyun+ break; 586*4882a593Smuzhiyun case '8': 587*4882a593Smuzhiyun- eight = 3; /* binary output and input */ 588*4882a593Smuzhiyun+ binary = 3; /* binary output and input */ 589*4882a593Smuzhiyun break; 590*4882a593Smuzhiyun case 'E': 591*4882a593Smuzhiyun rlogin = escapechar = _POSIX_VDISABLE; 592*4882a593Smuzhiyun@@ -133,23 +155,26 @@ main(int argc, char *argv[]) 593*4882a593Smuzhiyun //autologin = 0; 594*4882a593Smuzhiyun break; 595*4882a593Smuzhiyun case 'L': 596*4882a593Smuzhiyun- eight |= 2; /* binary output only */ 597*4882a593Smuzhiyun+ binary |= 2; /* binary output only */ 598*4882a593Smuzhiyun break; 599*4882a593Smuzhiyun case 'S': 600*4882a593Smuzhiyun { 601*4882a593Smuzhiyun-#ifdef HAS_GETTOS 602*4882a593Smuzhiyun extern int tos; 603*4882a593Smuzhiyun+ int num; 604*4882a593Smuzhiyun 605*4882a593Smuzhiyun- if ((tos = parsetos(optarg, "tcp")) < 0) 606*4882a593Smuzhiyun+#ifdef HAS_GETTOS 607*4882a593Smuzhiyun+ if ((num = parsetos(optarg, "tcp")) < 0) { 608*4882a593Smuzhiyun+#else 609*4882a593Smuzhiyun+ errno = 0; 610*4882a593Smuzhiyun+ num = strtol(optarg, 0, 0); 611*4882a593Smuzhiyun+ if (errno) { 612*4882a593Smuzhiyun+#endif 613*4882a593Smuzhiyun fprintf(stderr, "%s%s%s%s\n", 614*4882a593Smuzhiyun prompt, ": Bad TOS argument '", 615*4882a593Smuzhiyun optarg, 616*4882a593Smuzhiyun "; will try to use default TOS"); 617*4882a593Smuzhiyun-#else 618*4882a593Smuzhiyun- fprintf(stderr, 619*4882a593Smuzhiyun- "%s: Warning: -S ignored, no parsetos() support.\n", 620*4882a593Smuzhiyun- prompt); 621*4882a593Smuzhiyun-#endif 622*4882a593Smuzhiyun+ } else 623*4882a593Smuzhiyun+ tos = num; 624*4882a593Smuzhiyun } 625*4882a593Smuzhiyun break; 626*4882a593Smuzhiyun case 'X': 627*4882a593Smuzhiyun@@ -210,6 +235,9 @@ main(int argc, char *argv[]) 628*4882a593Smuzhiyun "%s: -x ignored, no encryption support.\n", 629*4882a593Smuzhiyun prompt); 630*4882a593Smuzhiyun break; 631*4882a593Smuzhiyun+ case 'b': 632*4882a593Smuzhiyun+ srcaddr = optarg; 633*4882a593Smuzhiyun+ break; 634*4882a593Smuzhiyun case '?': 635*4882a593Smuzhiyun default: 636*4882a593Smuzhiyun usage(); 637*4882a593Smuzhiyun@@ -233,6 +261,13 @@ main(int argc, char *argv[]) 638*4882a593Smuzhiyun *argp++ = "-l"; 639*4882a593Smuzhiyun *argp++ = user; 640*4882a593Smuzhiyun } 641*4882a593Smuzhiyun+ if (srcaddr) { 642*4882a593Smuzhiyun+ *argp++ = "-b"; 643*4882a593Smuzhiyun+ *argp++ = srcaddr; 644*4882a593Smuzhiyun+ } 645*4882a593Smuzhiyun+ if (family) { 646*4882a593Smuzhiyun+ *argp++ = family == AF_INET ? "-4" : "-6"; 647*4882a593Smuzhiyun+ } 648*4882a593Smuzhiyun *argp++ = argv[0]; /* host */ 649*4882a593Smuzhiyun if (argc > 1) 650*4882a593Smuzhiyun *argp++ = argv[1]; /* port */ 651*4882a593Smuzhiyundiff --git a/telnet/netlink.cc b/telnet/netlink.cc 652*4882a593Smuzhiyunindex f439cff..f839747 100644 653*4882a593Smuzhiyun--- a/telnet/netlink.cc 654*4882a593Smuzhiyun+++ b/telnet/netlink.cc 655*4882a593Smuzhiyun@@ -79,22 +79,61 @@ void netlink::close(int doshutdown) { 656*4882a593Smuzhiyun shutdown(net, 2); 657*4882a593Smuzhiyun } 658*4882a593Smuzhiyun ::close(net); 659*4882a593Smuzhiyun+ net = -1; 660*4882a593Smuzhiyun } 661*4882a593Smuzhiyun 662*4882a593Smuzhiyun-int netlink::connect(int debug, struct hostent *host, 663*4882a593Smuzhiyun- struct sockaddr_in *sn, 664*4882a593Smuzhiyun- char *srcroute, int srlen, int tos) 665*4882a593Smuzhiyun+int netlink::bind(struct addrinfo *addr) 666*4882a593Smuzhiyun { 667*4882a593Smuzhiyun- int on=1; 668*4882a593Smuzhiyun+ int res; 669*4882a593Smuzhiyun+ 670*4882a593Smuzhiyun+ res = socket(addr->ai_family); 671*4882a593Smuzhiyun+ if (res < 2) { 672*4882a593Smuzhiyun+ if (res == 1) 673*4882a593Smuzhiyun+ perror("telnet: socket"); 674*4882a593Smuzhiyun+ return -1; 675*4882a593Smuzhiyun+ } 676*4882a593Smuzhiyun+ 677*4882a593Smuzhiyun+ if (::bind(net, addr->ai_addr, addr->ai_addrlen) < 0) { 678*4882a593Smuzhiyun+ perror("telnet: bind"); 679*4882a593Smuzhiyun+ return -1; 680*4882a593Smuzhiyun+ } 681*4882a593Smuzhiyun+ 682*4882a593Smuzhiyun+ return 0; 683*4882a593Smuzhiyun+} 684*4882a593Smuzhiyun+ 685*4882a593Smuzhiyun+int netlink::socket(int family) 686*4882a593Smuzhiyun+{ 687*4882a593Smuzhiyun+ if (this->family != family) 688*4882a593Smuzhiyun+ close(0); 689*4882a593Smuzhiyun 690*4882a593Smuzhiyun- net = socket(AF_INET, SOCK_STREAM, 0); 691*4882a593Smuzhiyun if (net < 0) { 692*4882a593Smuzhiyun- perror("telnet: socket"); 693*4882a593Smuzhiyun- return 0; 694*4882a593Smuzhiyun+ this->family = family; 695*4882a593Smuzhiyun+ net = ::socket(family, SOCK_STREAM, 0); 696*4882a593Smuzhiyun+ if (net < 0) { 697*4882a593Smuzhiyun+ if (errno == EAFNOSUPPORT) 698*4882a593Smuzhiyun+ return 1; 699*4882a593Smuzhiyun+ perror("telnet: socket"); 700*4882a593Smuzhiyun+ return 0; 701*4882a593Smuzhiyun+ } 702*4882a593Smuzhiyun } 703*4882a593Smuzhiyun 704*4882a593Smuzhiyun+ return 2; 705*4882a593Smuzhiyun+} 706*4882a593Smuzhiyun+ 707*4882a593Smuzhiyun+int netlink::connect(int debug, struct addrinfo *addr, 708*4882a593Smuzhiyun+ char *srcroute, int srlen, int tos) 709*4882a593Smuzhiyun+{ 710*4882a593Smuzhiyun+ int on=1; 711*4882a593Smuzhiyun+ int res; 712*4882a593Smuzhiyun+ 713*4882a593Smuzhiyun+ res = socket(addr->ai_family); 714*4882a593Smuzhiyun+ if (res < 2) 715*4882a593Smuzhiyun+ return res; 716*4882a593Smuzhiyun+ 717*4882a593Smuzhiyun #if defined(IP_OPTIONS) && defined(HAS_IPPROTO_IP) 718*4882a593Smuzhiyun if (srcroute) { 719*4882a593Smuzhiyun+ if (addr->ai_family != AF_INET) 720*4882a593Smuzhiyun+ fputs("Source route is only supported for IPv4\n", stderr); 721*4882a593Smuzhiyun if (setsockopt(net, IPPROTO_IP, IP_OPTIONS, srcroute, srlen) < 0) 722*4882a593Smuzhiyun perror("setsockopt (IP_OPTIONS)"); 723*4882a593Smuzhiyun } 724*4882a593Smuzhiyun@@ -108,7 +147,7 @@ int netlink::connect(int debug, struct hostent *host, 725*4882a593Smuzhiyun #endif 726*4882a593Smuzhiyun if (tos < 0) tos = 020; /* Low Delay bit */ 727*4882a593Smuzhiyun if (tos && (setsockopt(net, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0) 728*4882a593Smuzhiyun- && (errno != ENOPROTOOPT)) 729*4882a593Smuzhiyun+ && (errno != ENOPROTOOPT) && (errno != EOPNOTSUPP)) 730*4882a593Smuzhiyun perror("telnet: setsockopt (IP_TOS) (ignored)"); 731*4882a593Smuzhiyun #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ 732*4882a593Smuzhiyun 733*4882a593Smuzhiyun@@ -116,27 +155,8 @@ int netlink::connect(int debug, struct hostent *host, 734*4882a593Smuzhiyun perror("setsockopt (SO_DEBUG)"); 735*4882a593Smuzhiyun } 736*4882a593Smuzhiyun 737*4882a593Smuzhiyun- if (::connect(net, (struct sockaddr *)sn, sizeof(*sn)) < 0) { 738*4882a593Smuzhiyun-#if defined(h_addr) /* In 4.3, this is a #define */ 739*4882a593Smuzhiyun- if (host && host->h_addr_list[1]) { 740*4882a593Smuzhiyun- int oerrno = errno; 741*4882a593Smuzhiyun- 742*4882a593Smuzhiyun- fprintf(stderr, "telnet: connect to address %s: ", 743*4882a593Smuzhiyun- inet_ntoa(sn->sin_addr)); 744*4882a593Smuzhiyun- errno = oerrno; 745*4882a593Smuzhiyun- perror(NULL); 746*4882a593Smuzhiyun- host->h_addr_list++; 747*4882a593Smuzhiyun- if (host->h_length > (int)sizeof(sn->sin_addr)) { 748*4882a593Smuzhiyun- host->h_length = sizeof(sn->sin_addr); 749*4882a593Smuzhiyun- } 750*4882a593Smuzhiyun- memcpy(&sn->sin_addr, host->h_addr_list[0], host->h_length); 751*4882a593Smuzhiyun- close(net); 752*4882a593Smuzhiyun- return 1; 753*4882a593Smuzhiyun- } 754*4882a593Smuzhiyun-#endif /* defined(h_addr) */ 755*4882a593Smuzhiyun- 756*4882a593Smuzhiyun- perror("telnet: Unable to connect to remote host"); 757*4882a593Smuzhiyun- return 0; 758*4882a593Smuzhiyun+ if (::connect(net, addr->ai_addr, addr->ai_addrlen) < 0) { 759*4882a593Smuzhiyun+ return 1; 760*4882a593Smuzhiyun } 761*4882a593Smuzhiyun return 2; 762*4882a593Smuzhiyun } 763*4882a593Smuzhiyundiff --git a/telnet/netlink.h b/telnet/netlink.h 764*4882a593Smuzhiyunindex 9852b30..0ac8a08 100644 765*4882a593Smuzhiyun--- a/telnet/netlink.h 766*4882a593Smuzhiyun+++ b/telnet/netlink.h 767*4882a593Smuzhiyun@@ -1,13 +1,16 @@ 768*4882a593Smuzhiyun 769*4882a593Smuzhiyun class netlink { 770*4882a593Smuzhiyun+ private: 771*4882a593Smuzhiyun+ int family; 772*4882a593Smuzhiyun protected: 773*4882a593Smuzhiyun int net; 774*4882a593Smuzhiyun public: 775*4882a593Smuzhiyun netlink(); 776*4882a593Smuzhiyun ~netlink(); 777*4882a593Smuzhiyun 778*4882a593Smuzhiyun- int connect(int debug, struct hostent *host, 779*4882a593Smuzhiyun- struct sockaddr_in *sin, 780*4882a593Smuzhiyun+ int bind(struct addrinfo *hostaddr); 781*4882a593Smuzhiyun+ int socket(int family); 782*4882a593Smuzhiyun+ int connect(int debug, struct addrinfo *hostaddr, 783*4882a593Smuzhiyun char *srcroute, int srlen, 784*4882a593Smuzhiyun int tos); 785*4882a593Smuzhiyun void close(int doshutdown); 786*4882a593Smuzhiyundiff --git a/telnet/network.cc b/telnet/network.cc 787*4882a593Smuzhiyunindex 6a2c374..0dcf3e2 100644 788*4882a593Smuzhiyun--- a/telnet/network.cc 789*4882a593Smuzhiyun+++ b/telnet/network.cc 790*4882a593Smuzhiyun@@ -40,6 +40,7 @@ char net_rcsid[] = 791*4882a593Smuzhiyun #include <sys/types.h> 792*4882a593Smuzhiyun #include <sys/socket.h> 793*4882a593Smuzhiyun #include <sys/time.h> 794*4882a593Smuzhiyun+#include <stdlib.h> 795*4882a593Smuzhiyun #include <errno.h> 796*4882a593Smuzhiyun #include <arpa/telnet.h> 797*4882a593Smuzhiyun 798*4882a593Smuzhiyundiff --git a/telnet/proto.h b/telnet/proto.h 799*4882a593Smuzhiyunindex 8be4a39..92f2419 100644 800*4882a593Smuzhiyun--- a/telnet/proto.h 801*4882a593Smuzhiyun+++ b/telnet/proto.h 802*4882a593Smuzhiyun@@ -13,7 +13,7 @@ int TerminalWindowSize(long *rows, long *cols); 803*4882a593Smuzhiyun void auth_encrypt_user(char *); 804*4882a593Smuzhiyun void auth_name(unsigned char *, int); 805*4882a593Smuzhiyun void auth_printsub(unsigned char *, int, unsigned char *, int); 806*4882a593Smuzhiyun-void cmdrc(const char *m1, const char *m2); 807*4882a593Smuzhiyun+void cmdrc(const char *, const char *, const char *); 808*4882a593Smuzhiyun void env_init(void); 809*4882a593Smuzhiyun int getconnmode(void); 810*4882a593Smuzhiyun void init_network(void); 811*4882a593Smuzhiyundiff --git a/telnet/ring.cc b/telnet/ring.cc 812*4882a593Smuzhiyunindex be57396..772c6c5 100644 813*4882a593Smuzhiyun--- a/telnet/ring.cc 814*4882a593Smuzhiyun+++ b/telnet/ring.cc 815*4882a593Smuzhiyun@@ -165,7 +165,7 @@ int ringbuf::flush() { 816*4882a593Smuzhiyun 817*4882a593Smuzhiyun /////////////////////////////////////////////////// supply ////////////// 818*4882a593Smuzhiyun 819*4882a593Smuzhiyun-void ringbuf::printf(const char *format, ...) { 820*4882a593Smuzhiyun+void ringbuf::xprintf(const char *format, ...) { 821*4882a593Smuzhiyun char xbuf[256]; 822*4882a593Smuzhiyun va_list ap; 823*4882a593Smuzhiyun va_start(ap, format); 824*4882a593Smuzhiyundiff --git a/telnet/ring.h b/telnet/ring.h 825*4882a593Smuzhiyunindex 15d3f3f..049377e 100644 826*4882a593Smuzhiyun--- a/telnet/ring.h 827*4882a593Smuzhiyun+++ b/telnet/ring.h 828*4882a593Smuzhiyun@@ -83,7 +83,7 @@ class ringbuf { 829*4882a593Smuzhiyun // manual supply 830*4882a593Smuzhiyun void putch(char c) { write(&c, 1); } 831*4882a593Smuzhiyun void write(const char *buffer, int ct); 832*4882a593Smuzhiyun- void printf(const char *format, ...); 833*4882a593Smuzhiyun+ void xprintf(const char *format, ...); 834*4882a593Smuzhiyun int empty_count() { return size - count; } 835*4882a593Smuzhiyun 836*4882a593Smuzhiyun // automatic supply 837*4882a593Smuzhiyundiff --git a/telnet/sys_bsd.cc b/telnet/sys_bsd.cc 838*4882a593Smuzhiyunindex 93fba7e..a8c9aab 100644 839*4882a593Smuzhiyun--- a/telnet/sys_bsd.cc 840*4882a593Smuzhiyun+++ b/telnet/sys_bsd.cc 841*4882a593Smuzhiyun@@ -189,18 +189,25 @@ void NetSetPgrp(int fd) { 842*4882a593Smuzhiyun * Various signal handling routines. 843*4882a593Smuzhiyun */ 844*4882a593Smuzhiyun 845*4882a593Smuzhiyun+#if 0 846*4882a593Smuzhiyun static void deadpeer(int /*sig*/) { 847*4882a593Smuzhiyun setcommandmode(); 848*4882a593Smuzhiyun siglongjmp(peerdied, -1); 849*4882a593Smuzhiyun } 850*4882a593Smuzhiyun+#endif 851*4882a593Smuzhiyun 852*4882a593Smuzhiyun static void intr(int /*sig*/) { 853*4882a593Smuzhiyun if (localchars) { 854*4882a593Smuzhiyun intp(); 855*4882a593Smuzhiyun } 856*4882a593Smuzhiyun else { 857*4882a593Smuzhiyun+#if 0 858*4882a593Smuzhiyun setcommandmode(); 859*4882a593Smuzhiyun siglongjmp(toplevel, -1); 860*4882a593Smuzhiyun+#else 861*4882a593Smuzhiyun+ signal(SIGINT, SIG_DFL); 862*4882a593Smuzhiyun+ raise(SIGINT); 863*4882a593Smuzhiyun+#endif 864*4882a593Smuzhiyun } 865*4882a593Smuzhiyun } 866*4882a593Smuzhiyun 867*4882a593Smuzhiyun@@ -214,6 +221,8 @@ static void intr2(int /*sig*/) { 868*4882a593Smuzhiyun sendabort(); 869*4882a593Smuzhiyun return; 870*4882a593Smuzhiyun } 871*4882a593Smuzhiyun+ signal(SIGQUIT, SIG_DFL); 872*4882a593Smuzhiyun+ raise(SIGQUIT); 873*4882a593Smuzhiyun } 874*4882a593Smuzhiyun 875*4882a593Smuzhiyun #ifdef SIGWINCH 876*4882a593Smuzhiyun@@ -238,7 +247,9 @@ void ayt(int sig) { 877*4882a593Smuzhiyun void sys_telnet_init(void) { 878*4882a593Smuzhiyun signal(SIGINT, intr); 879*4882a593Smuzhiyun signal(SIGQUIT, intr2); 880*4882a593Smuzhiyun+#if 0 881*4882a593Smuzhiyun signal(SIGPIPE, deadpeer); 882*4882a593Smuzhiyun+#endif 883*4882a593Smuzhiyun #ifdef SIGWINCH 884*4882a593Smuzhiyun signal(SIGWINCH, sendwin); 885*4882a593Smuzhiyun #endif 886*4882a593Smuzhiyundiff --git a/telnet/telnet.1 b/telnet/telnet.1 887*4882a593Smuzhiyunindex 54a47fb..8365e42 100644 888*4882a593Smuzhiyun--- a/telnet/telnet.1 889*4882a593Smuzhiyun+++ b/telnet/telnet.1 890*4882a593Smuzhiyun@@ -42,8 +42,9 @@ 891*4882a593Smuzhiyun protocol 892*4882a593Smuzhiyun .Sh SYNOPSIS 893*4882a593Smuzhiyun .Nm telnet 894*4882a593Smuzhiyun-.Op Fl 8ELadr 895*4882a593Smuzhiyun+.Op Fl 468ELadr 896*4882a593Smuzhiyun .Op Fl S Ar tos 897*4882a593Smuzhiyun+.Op Fl b Ar address 898*4882a593Smuzhiyun .Op Fl e Ar escapechar 899*4882a593Smuzhiyun .Op Fl l Ar user 900*4882a593Smuzhiyun .Op Fl n Ar tracefile 901*4882a593Smuzhiyun@@ -68,6 +69,10 @@ command implicitly; see the description below. 902*4882a593Smuzhiyun .Pp 903*4882a593Smuzhiyun Options: 904*4882a593Smuzhiyun .Bl -tag -width indent 905*4882a593Smuzhiyun+.It Fl 4 906*4882a593Smuzhiyun+Force IPv4 address resolution. 907*4882a593Smuzhiyun+.It Fl 6 908*4882a593Smuzhiyun+Force IPv6 address resolution. 909*4882a593Smuzhiyun .It Fl 8 910*4882a593Smuzhiyun Request 8-bit operation. This causes an attempt to negotiate the 911*4882a593Smuzhiyun .Dv TELNET BINARY 912*4882a593Smuzhiyun@@ -89,6 +94,8 @@ of the 913*4882a593Smuzhiyun option if supported by the remote system. The username is retrieved 914*4882a593Smuzhiyun via 915*4882a593Smuzhiyun .Xr getlogin 3 . 916*4882a593Smuzhiyun+.It Fl b Ar address 917*4882a593Smuzhiyun+Use bind(2) on the local socket to bind it to a specific local address. 918*4882a593Smuzhiyun .It Fl d 919*4882a593Smuzhiyun Sets the initial value of the 920*4882a593Smuzhiyun .Ic debug 921*4882a593Smuzhiyun@@ -474,17 +481,29 @@ protocol without making a mess. Protocol negotiation can be forced by 922*4882a593Smuzhiyun placing a dash before the port number. 923*4882a593Smuzhiyun .Pp 924*4882a593Smuzhiyun After establishing a connection, any commands associated with the 925*4882a593Smuzhiyun-remote host in the user's 926*4882a593Smuzhiyun+remote host in 927*4882a593Smuzhiyun+.Pa /etc/telnetrc 928*4882a593Smuzhiyun+and the user's 929*4882a593Smuzhiyun .Pa .telnetrc 930*4882a593Smuzhiyun-file are executed. 931*4882a593Smuzhiyun+file are executed, in that order. 932*4882a593Smuzhiyun .Pp 933*4882a593Smuzhiyun-The format of the .telnetrc file is as follows: Lines beginning with a 934*4882a593Smuzhiyun+The format of the telnetrc files is as follows: Lines beginning with a 935*4882a593Smuzhiyun #, and blank lines, are ignored. The rest of the file should consist 936*4882a593Smuzhiyun of hostnames and sequences of 937*4882a593Smuzhiyun .Nm telnet 938*4882a593Smuzhiyun commands to use with that host. Commands should be one per line, 939*4882a593Smuzhiyun indented by whitespace; lines beginning without whitespace are 940*4882a593Smuzhiyun-interpreted as hostnames. Upon connecting to a particular host, the 941*4882a593Smuzhiyun+interpreted as hostnames. Lines beginning with the special hostname 942*4882a593Smuzhiyun+.Ql DEFAULT 943*4882a593Smuzhiyun+will apply to all hosts. Hostnames including 944*4882a593Smuzhiyun+.Ql DEFAULT 945*4882a593Smuzhiyun+may be followed immediately by a colon and a port number or string. 946*4882a593Smuzhiyun+If a port is specified it must match exactly with what is specified 947*4882a593Smuzhiyun+on the command line. If no port was specified on the command line, 948*4882a593Smuzhiyun+then the value 949*4882a593Smuzhiyun+.Ql telnet 950*4882a593Smuzhiyun+is used. 951*4882a593Smuzhiyun+Upon connecting to a particular host, the 952*4882a593Smuzhiyun commands associated with that host are executed. 953*4882a593Smuzhiyun .It Ic quit 954*4882a593Smuzhiyun Close any open session and exit 955*4882a593Smuzhiyun@@ -1184,9 +1203,7 @@ escape sequences are preceded by a '*' to aid in locating them. 956*4882a593Smuzhiyun When the skiprc toggle is 957*4882a593Smuzhiyun .Dv TRUE , 958*4882a593Smuzhiyun .Tn telnet 959*4882a593Smuzhiyun-does not read the 960*4882a593Smuzhiyun-.Pa \&.telnetrc 961*4882a593Smuzhiyun-file. The initial value for this toggle is 962*4882a593Smuzhiyun+does not read the telnetrc files. The initial value for this toggle is 963*4882a593Smuzhiyun .Dv FALSE. 964*4882a593Smuzhiyun .It Ic termdata 965*4882a593Smuzhiyun Toggles the display of all terminal data (in hexadecimal format). 966*4882a593Smuzhiyun@@ -1239,7 +1256,9 @@ to the other side via the 967*4882a593Smuzhiyun .Dv TELNET ENVIRON 968*4882a593Smuzhiyun option. 969*4882a593Smuzhiyun .Sh FILES 970*4882a593Smuzhiyun-.Bl -tag -width ~/.telnetrc -compact 971*4882a593Smuzhiyun+.Bl -tag -width /etc/telnetrc -compact 972*4882a593Smuzhiyun+.It Pa /etc/telnetrc 973*4882a593Smuzhiyun+global telnet startup values 974*4882a593Smuzhiyun .It Pa ~/.telnetrc 975*4882a593Smuzhiyun user customized telnet startup values 976*4882a593Smuzhiyun .El 977*4882a593Smuzhiyundiff --git a/telnet/telnet.cc b/telnet/telnet.cc 978*4882a593Smuzhiyunindex 4fc3b1f..7eca811 100644 979*4882a593Smuzhiyun--- a/telnet/telnet.cc 980*4882a593Smuzhiyun+++ b/telnet/telnet.cc 981*4882a593Smuzhiyun@@ -88,7 +88,8 @@ char do_dont_resp[256]; 982*4882a593Smuzhiyun char will_wont_resp[256]; 983*4882a593Smuzhiyun 984*4882a593Smuzhiyun int 985*4882a593Smuzhiyun-eight = 0, 986*4882a593Smuzhiyun+ eight = 3, 987*4882a593Smuzhiyun+ binary = 0, 988*4882a593Smuzhiyun autologin = 0, /* Autologin anyone? */ 989*4882a593Smuzhiyun skiprc = 0, 990*4882a593Smuzhiyun connected, 991*4882a593Smuzhiyun@@ -639,14 +640,14 @@ static const char *gettermname(void) { 992*4882a593Smuzhiyun if (resettermname) { 993*4882a593Smuzhiyun resettermname = 0; 994*4882a593Smuzhiyun tname = env_getvalue("TERM", 0); 995*4882a593Smuzhiyun- if (!tname || my_setupterm(tname, 1, &err)) { 996*4882a593Smuzhiyun+ if (!tname /* || my_setupterm(tname, 1, &err) */) { 997*4882a593Smuzhiyun termbuf[0] = 0; 998*4882a593Smuzhiyun tname = "UNKNOWN"; 999*4882a593Smuzhiyun } 1000*4882a593Smuzhiyun mklist(termbuf, tname, termtypes); 1001*4882a593Smuzhiyun next = 0; 1002*4882a593Smuzhiyun } 1003*4882a593Smuzhiyun- if (next==termtypes.num()) next = 0; 1004*4882a593Smuzhiyun+ if (next==termtypes.num()-1) next = 0; 1005*4882a593Smuzhiyun return termtypes[next++]; 1006*4882a593Smuzhiyun } 1007*4882a593Smuzhiyun /* 1008*4882a593Smuzhiyun@@ -681,7 +682,7 @@ static void suboption(void) { 1009*4882a593Smuzhiyun } 1010*4882a593Smuzhiyun #endif /* TN3270 */ 1011*4882a593Smuzhiyun name = gettermname(); 1012*4882a593Smuzhiyun- netoring.printf("%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE, 1013*4882a593Smuzhiyun+ netoring.xprintf("%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE, 1014*4882a593Smuzhiyun TELQUAL_IS, name, IAC, SE); 1015*4882a593Smuzhiyun } 1016*4882a593Smuzhiyun break; 1017*4882a593Smuzhiyun@@ -693,7 +694,7 @@ static void suboption(void) { 1018*4882a593Smuzhiyun if (SB_GET() == TELQUAL_SEND) { 1019*4882a593Smuzhiyun long oospeed, iispeed; 1020*4882a593Smuzhiyun TerminalSpeeds(&iispeed, &oospeed); 1021*4882a593Smuzhiyun- netoring.printf("%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED, 1022*4882a593Smuzhiyun+ netoring.xprintf("%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED, 1023*4882a593Smuzhiyun TELQUAL_IS, oospeed, iispeed, IAC, SE); 1024*4882a593Smuzhiyun } 1025*4882a593Smuzhiyun break; 1026*4882a593Smuzhiyun@@ -780,7 +781,7 @@ static void suboption(void) { 1027*4882a593Smuzhiyun send_wont(TELOPT_XDISPLOC, 1); 1028*4882a593Smuzhiyun break; 1029*4882a593Smuzhiyun } 1030*4882a593Smuzhiyun- netoring.printf("%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC, 1031*4882a593Smuzhiyun+ netoring.xprintf("%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC, 1032*4882a593Smuzhiyun TELQUAL_IS, dp, IAC, SE); 1033*4882a593Smuzhiyun } 1034*4882a593Smuzhiyun break; 1035*4882a593Smuzhiyun@@ -798,7 +799,7 @@ void lm_will(unsigned char *cmd, int len) { 1036*4882a593Smuzhiyun return; 1037*4882a593Smuzhiyun } 1038*4882a593Smuzhiyun 1039*4882a593Smuzhiyun- netoring.printf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, 1040*4882a593Smuzhiyun+ netoring.xprintf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, 1041*4882a593Smuzhiyun DONT, cmd[0], IAC, SE); 1042*4882a593Smuzhiyun } 1043*4882a593Smuzhiyun 1044*4882a593Smuzhiyun@@ -815,7 +816,7 @@ void lm_do(unsigned char *cmd, int len) { 1045*4882a593Smuzhiyun /*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */ 1046*4882a593Smuzhiyun return; 1047*4882a593Smuzhiyun } 1048*4882a593Smuzhiyun- netoring.printf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, 1049*4882a593Smuzhiyun+ netoring.xprintf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, 1050*4882a593Smuzhiyun WONT, cmd[0], IAC, SE); 1051*4882a593Smuzhiyun } 1052*4882a593Smuzhiyun 1053*4882a593Smuzhiyun@@ -838,7 +839,7 @@ void lm_mode(unsigned char *cmd, int len, int init) { 1054*4882a593Smuzhiyun k |= MODE_ACK; 1055*4882a593Smuzhiyun } 1056*4882a593Smuzhiyun 1057*4882a593Smuzhiyun- netoring.printf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_MODE, 1058*4882a593Smuzhiyun+ netoring.xprintf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_MODE, 1059*4882a593Smuzhiyun k, IAC, SE); 1060*4882a593Smuzhiyun 1061*4882a593Smuzhiyun setconnmode(0); /* set changed mode */ 1062*4882a593Smuzhiyun@@ -933,11 +934,11 @@ void slc_mode_import(int def) { 1063*4882a593Smuzhiyun 1064*4882a593Smuzhiyun void slc_import(int def) { 1065*4882a593Smuzhiyun if (def) { 1066*4882a593Smuzhiyun- netoring.printf("%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, 1067*4882a593Smuzhiyun+ netoring.xprintf("%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, 1068*4882a593Smuzhiyun LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE); 1069*4882a593Smuzhiyun } 1070*4882a593Smuzhiyun else { 1071*4882a593Smuzhiyun- netoring.printf("%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, 1072*4882a593Smuzhiyun+ netoring.xprintf("%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, 1073*4882a593Smuzhiyun LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE); 1074*4882a593Smuzhiyun } 1075*4882a593Smuzhiyun } 1076*4882a593Smuzhiyun@@ -1050,6 +1051,7 @@ void slc_check(void) { 1077*4882a593Smuzhiyun 1078*4882a593Smuzhiyun 1079*4882a593Smuzhiyun unsigned char slc_reply[128]; 1080*4882a593Smuzhiyun+unsigned char const * const slc_reply_eom = &slc_reply[sizeof(slc_reply)]; 1081*4882a593Smuzhiyun unsigned char *slc_replyp; 1082*4882a593Smuzhiyun 1083*4882a593Smuzhiyun void slc_start_reply(void) { 1084*4882a593Smuzhiyun@@ -1061,6 +1063,14 @@ void slc_start_reply(void) { 1085*4882a593Smuzhiyun } 1086*4882a593Smuzhiyun 1087*4882a593Smuzhiyun void slc_add_reply(int func, int flags, int value) { 1088*4882a593Smuzhiyun+ /* A sequence of up to 6 bytes my be written for this member of the SLC 1089*4882a593Smuzhiyun+ * suboption list by this function. The end of negotiation command, 1090*4882a593Smuzhiyun+ * which is written by slc_end_reply(), will require 2 additional 1091*4882a593Smuzhiyun+ * bytes. Do not proceed unless there is sufficient space for these 1092*4882a593Smuzhiyun+ * items. 1093*4882a593Smuzhiyun+ */ 1094*4882a593Smuzhiyun+ if (&slc_replyp[6+2] > slc_reply_eom) 1095*4882a593Smuzhiyun+ return; 1096*4882a593Smuzhiyun if ((*slc_replyp++ = func) == IAC) 1097*4882a593Smuzhiyun *slc_replyp++ = IAC; 1098*4882a593Smuzhiyun if ((*slc_replyp++ = flags) == IAC) 1099*4882a593Smuzhiyun@@ -1142,6 +1152,7 @@ void env_opt(unsigned char *buf, int len) { 1100*4882a593Smuzhiyun } 1101*4882a593Smuzhiyun } 1102*4882a593Smuzhiyun 1103*4882a593Smuzhiyun+/* OPT_REPLY_SIZE must be a multiple of 2. */ 1104*4882a593Smuzhiyun #define OPT_REPLY_SIZE 256 1105*4882a593Smuzhiyun unsigned char *opt_reply; 1106*4882a593Smuzhiyun unsigned char *opt_replyp; 1107*4882a593Smuzhiyun@@ -1173,6 +1184,7 @@ void env_opt_start_info(void) { 1108*4882a593Smuzhiyun 1109*4882a593Smuzhiyun void env_opt_add(const char *ep) { 1110*4882a593Smuzhiyun const char *vp; 1111*4882a593Smuzhiyun+ const unsigned char *tp; 1112*4882a593Smuzhiyun unsigned char c; 1113*4882a593Smuzhiyun 1114*4882a593Smuzhiyun if (opt_reply == NULL) /*XXX*/ 1115*4882a593Smuzhiyun@@ -1185,11 +1197,12 @@ void env_opt_add(const char *ep) { 1116*4882a593Smuzhiyun return; 1117*4882a593Smuzhiyun } 1118*4882a593Smuzhiyun vp = env_getvalue(ep, 1); 1119*4882a593Smuzhiyun- if (opt_replyp + (vp ? strlen(vp) : 0) + strlen(ep) + 6 > opt_replyend) 1120*4882a593Smuzhiyun+ tp = opt_replyp + (vp ? strlen(vp) * 2 : 0) + strlen(ep) * 2 + 6; 1121*4882a593Smuzhiyun+ if (tp > opt_replyend) 1122*4882a593Smuzhiyun { 1123*4882a593Smuzhiyun register int len; 1124*4882a593Smuzhiyun- opt_replyend += OPT_REPLY_SIZE; 1125*4882a593Smuzhiyun- len = opt_replyend - opt_reply; 1126*4882a593Smuzhiyun+ len = ((tp - opt_reply) + OPT_REPLY_SIZE - 1) & ~(OPT_REPLY_SIZE - 1); 1127*4882a593Smuzhiyun+ opt_replyend = opt_reply + len; 1128*4882a593Smuzhiyun opt_reply = (unsigned char *)realloc(opt_reply, len); 1129*4882a593Smuzhiyun if (opt_reply == NULL) { 1130*4882a593Smuzhiyun /*@*/ printf("env_opt_add: realloc() failed!!!\n"); 1131*4882a593Smuzhiyun@@ -1740,8 +1753,8 @@ void telnet(const char * /*user*/) { 1132*4882a593Smuzhiyun send_do(TELOPT_STATUS, 1); 1133*4882a593Smuzhiyun if (env_getvalue("DISPLAY", 0)) 1134*4882a593Smuzhiyun send_will(TELOPT_XDISPLOC, 1); 1135*4882a593Smuzhiyun- if (eight) 1136*4882a593Smuzhiyun- tel_enter_binary(eight); 1137*4882a593Smuzhiyun+ if (binary) 1138*4882a593Smuzhiyun+ tel_enter_binary(binary); 1139*4882a593Smuzhiyun } 1140*4882a593Smuzhiyun #endif /* !defined(TN3270) */ 1141*4882a593Smuzhiyun 1142*4882a593Smuzhiyundiff --git a/telnet/terminal.cc b/telnet/terminal.cc 1143*4882a593Smuzhiyunindex 9eb47ae..764f18f 100644 1144*4882a593Smuzhiyun--- a/telnet/terminal.cc 1145*4882a593Smuzhiyun+++ b/telnet/terminal.cc 1146*4882a593Smuzhiyun@@ -45,6 +45,8 @@ char terminal_rcsid[] = 1147*4882a593Smuzhiyun #include <signal.h> 1148*4882a593Smuzhiyun #include <errno.h> 1149*4882a593Smuzhiyun #include <stdio.h> 1150*4882a593Smuzhiyun+#include <string.h> 1151*4882a593Smuzhiyun+#include <stdlib.h> 1152*4882a593Smuzhiyun 1153*4882a593Smuzhiyun #include "ring.h" 1154*4882a593Smuzhiyun #include "defines.h" 1155*4882a593Smuzhiyun@@ -155,9 +157,11 @@ int getconnmode(void) { 1156*4882a593Smuzhiyun if (localflow) 1157*4882a593Smuzhiyun mode |= MODE_FLOW; 1158*4882a593Smuzhiyun 1159*4882a593Smuzhiyun- if (my_want_state_is_will(TELOPT_BINARY)) 1160*4882a593Smuzhiyun+ if ((eight & 1) || my_want_state_is_will(TELOPT_BINARY)) 1161*4882a593Smuzhiyun mode |= MODE_INBIN; 1162*4882a593Smuzhiyun 1163*4882a593Smuzhiyun+ if (eight & 2) 1164*4882a593Smuzhiyun+ mode |= MODE_OUT8; 1165*4882a593Smuzhiyun if (his_want_state_is_will(TELOPT_BINARY)) 1166*4882a593Smuzhiyun mode |= MODE_OUTBIN; 1167*4882a593Smuzhiyun 1168*4882a593Smuzhiyun@@ -449,10 +453,13 @@ void TerminalNewMode(int f) 1169*4882a593Smuzhiyun // breaks SunOS. 1170*4882a593Smuzhiyun tmp_tc.c_iflag |= ISTRIP; 1171*4882a593Smuzhiyun } 1172*4882a593Smuzhiyun- if (f & MODE_OUTBIN) { 1173*4882a593Smuzhiyun+ if (f & (MODE_OUTBIN|MODE_OUT8)) { 1174*4882a593Smuzhiyun tmp_tc.c_cflag &= ~(CSIZE|PARENB); 1175*4882a593Smuzhiyun tmp_tc.c_cflag |= CS8; 1176*4882a593Smuzhiyun- tmp_tc.c_oflag &= ~OPOST; 1177*4882a593Smuzhiyun+ if (f & MODE_OUTBIN) 1178*4882a593Smuzhiyun+ tmp_tc.c_oflag &= ~OPOST; 1179*4882a593Smuzhiyun+ else 1180*4882a593Smuzhiyun+ tmp_tc.c_oflag |= OPOST; 1181*4882a593Smuzhiyun } else { 1182*4882a593Smuzhiyun tmp_tc.c_cflag &= ~(CSIZE|PARENB); 1183*4882a593Smuzhiyun tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB); 1184*4882a593Smuzhiyun@@ -468,7 +475,7 @@ void TerminalNewMode(int f) 1185*4882a593Smuzhiyun 1186*4882a593Smuzhiyun #ifdef SIGINFO 1187*4882a593Smuzhiyun signal(SIGINFO, ayt); 1188*4882a593Smuzhiyun-#endif SIGINFO 1189*4882a593Smuzhiyun+#endif /* SIGINFO */ 1190*4882a593Smuzhiyun 1191*4882a593Smuzhiyun #if defined(NOKERNINFO) 1192*4882a593Smuzhiyun tmp_tc.c_lflag |= NOKERNINFO; 1193*4882a593Smuzhiyun@@ -504,7 +511,7 @@ void TerminalNewMode(int f) 1194*4882a593Smuzhiyun 1195*4882a593Smuzhiyun #ifdef SIGINFO 1196*4882a593Smuzhiyun signal(SIGINFO, ayt_status); 1197*4882a593Smuzhiyun-#endif SIGINFO 1198*4882a593Smuzhiyun+#endif /* SIGINFO */ 1199*4882a593Smuzhiyun 1200*4882a593Smuzhiyun #ifdef SIGTSTP 1201*4882a593Smuzhiyun signal(SIGTSTP, SIG_DFL); 1202*4882a593Smuzhiyundiff --git a/telnet/utilities.cc b/telnet/utilities.cc 1203*4882a593Smuzhiyunindex 0448f0a..66839ab 100644 1204*4882a593Smuzhiyun--- a/telnet/utilities.cc 1205*4882a593Smuzhiyun+++ b/telnet/utilities.cc 1206*4882a593Smuzhiyun@@ -47,6 +47,8 @@ char util_rcsid[] = 1207*4882a593Smuzhiyun #include <sys/socket.h> 1208*4882a593Smuzhiyun #include <unistd.h> 1209*4882a593Smuzhiyun #include <ctype.h> 1210*4882a593Smuzhiyun+#include <string.h> 1211*4882a593Smuzhiyun+#include <stdlib.h> 1212*4882a593Smuzhiyun 1213*4882a593Smuzhiyun #include "ring.h" 1214*4882a593Smuzhiyun #include "defines.h" 1215*4882a593Smuzhiyun-- 1216*4882a593Smuzhiyun1.8.4.2 1217*4882a593Smuzhiyun 1218