aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/telnet.c119
1 files changed, 53 insertions, 66 deletions
diff --git a/networking/telnet.c b/networking/telnet.c
index 0ee65c532..6b4accd33 100644
--- a/networking/telnet.c
+++ b/networking/telnet.c
@@ -152,8 +152,10 @@ static void subneg(byte c);
152 152
153static void iac_flush(void) 153static void iac_flush(void)
154{ 154{
155 full_write(netfd, G.iacbuf, G.iaclen); 155 if (G.iaclen != 0) {
156 G.iaclen = 0; 156 full_write(netfd, G.iacbuf, G.iaclen);
157 G.iaclen = 0;
158 }
157} 159}
158 160
159static void doexit(int ev) NORETURN; 161static void doexit(int ev) NORETURN;
@@ -338,88 +340,73 @@ static void handle_net_input(int len)
338 340
339static void put_iac(int c) 341static void put_iac(int c)
340{ 342{
341 G.iacbuf[G.iaclen++] = c; 343 int iaclen = G.iaclen;
344 if (iaclen >= IACBUFSIZE) {
345 iac_flush();
346 iaclen = 0;
347 }
348 G.iacbuf[iaclen] = c; /* "... & 0xff" is implicit */
349 G.iaclen = iaclen + 1;
342} 350}
343 351
344static void put_iac2_merged(unsigned wwdd_and_c) 352static void put_iac2_msb_lsb(unsigned x_y)
345{ 353{
346 if (G.iaclen + 3 > IACBUFSIZE) 354 put_iac(x_y >> 8); /* "... & 0xff" is implicit */
347 iac_flush(); 355 put_iac(x_y); /* "... & 0xff" is implicit */
356}
357#define put_iac2_x_y(x,y) put_iac2_msb_lsb(((x)<<8) + (y))
348 358
359static void put_iac4_msb_lsb(unsigned x_y_z_t)
360{
361 put_iac2_msb_lsb(x_y_z_t >> 16);
362 put_iac2_msb_lsb(x_y_z_t); /* "... & 0xffff" is implicit */
363}
364#define put_iac4_x_y_z_t(x,y,z,t) put_iac4_msb_lsb(((x)<<24) + ((y)<<16) + ((z)<<8) + (t))
365
366static void put_iac3_IAC_x_y_merged(unsigned wwdd_and_c)
367{
349 put_iac(IAC); 368 put_iac(IAC);
350 put_iac(wwdd_and_c >> 8); 369 put_iac2_msb_lsb(wwdd_and_c);
351 put_iac(wwdd_and_c & 0xff);
352} 370}
353#define put_iac2(wwdd,c) put_iac2_merged(((wwdd)<<8) + (c)) 371#define put_iac3_IAC_x_y(wwdd,c) put_iac3_IAC_x_y_merged(((wwdd)<<8) + (c))
354 372
355#if ENABLE_FEATURE_TELNET_TTYPE 373#if ENABLE_FEATURE_TELNET_TTYPE
356static void put_iac_subopt(byte c, char *str) 374static void put_iac_subopt(byte c, char *str)
357{ 375{
358 int len = strlen(str) + 6; // ( 2 + 1 + 1 + strlen + 2 ) 376 put_iac4_x_y_z_t(IAC, SB, c, 0);
359
360 if (G.iaclen + len > IACBUFSIZE)
361 iac_flush();
362
363 put_iac(IAC);
364 put_iac(SB);
365 put_iac(c);
366 put_iac(0);
367 377
368 while (*str) 378 while (*str)
369 put_iac(*str++); 379 put_iac(*str++);
370 380
371 put_iac(IAC); 381 put_iac2_x_y(IAC, SE);
372 put_iac(SE);
373} 382}
374#endif 383#endif
375 384
376#if ENABLE_FEATURE_TELNET_AUTOLOGIN 385#if ENABLE_FEATURE_TELNET_AUTOLOGIN
377static void put_iac_subopt_autologin(void) 386static void put_iac_subopt_autologin(void)
378{ 387{
379 int len = strlen(G.autologin) + 6; // (2 + 1 + 1 + strlen + 2) 388 const char *p;
380 const char *p = "USER";
381
382 if (G.iaclen + len > IACBUFSIZE)
383 iac_flush();
384 389
385 put_iac(IAC); 390 put_iac4_x_y_z_t(IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_IS);
386 put_iac(SB); 391 put_iac4_x_y_z_t(NEW_ENV_VAR, 'U', 'S', 'E'); /* "USER" */
387 put_iac(TELOPT_NEW_ENVIRON); 392 put_iac2_x_y('R', NEW_ENV_VALUE);
388 put_iac(TELQUAL_IS);
389 put_iac(NEW_ENV_VAR);
390
391 while (*p)
392 put_iac(*p++);
393
394 put_iac(NEW_ENV_VALUE);
395 393
396 p = G.autologin; 394 p = G.autologin;
397 while (*p) 395 while (*p)
398 put_iac(*p++); 396 put_iac(*p++);
399 397
400 put_iac(IAC); 398 put_iac2_x_y(IAC, SE);
401 put_iac(SE);
402} 399}
403#endif 400#endif
404 401
405#if ENABLE_FEATURE_TELNET_WIDTH 402#if ENABLE_FEATURE_TELNET_WIDTH
406static void put_iac_naws(byte c, int x, int y) 403static void put_iac_naws(byte c, int x, int y)
407{ 404{
408 if (G.iaclen + 9 > IACBUFSIZE) 405 put_iac3_IAC_x_y(SB, c);
409 iac_flush();
410 406
411 put_iac(IAC); 407 put_iac4_msb_lsb((x << 16) + y);
412 put_iac(SB);
413 put_iac(c);
414
415 /* "... & 0xff" implicitly done below */
416 put_iac(x >> 8);
417 put_iac(x);
418 put_iac(y >> 8);
419 put_iac(y);
420 408
421 put_iac(IAC); 409 put_iac2_x_y(IAC, SE);
422 put_iac(SE);
423} 410}
424#endif 411#endif
425 412
@@ -448,8 +435,8 @@ static void will_charmode(void)
448 G.telflags |= (UF_ECHO | UF_SGA); 435 G.telflags |= (UF_ECHO | UF_SGA);
449 setConMode(); 436 setConMode();
450 437
451 put_iac2(DO, TELOPT_ECHO); 438 put_iac3_IAC_x_y(DO, TELOPT_ECHO);
452 put_iac2(DO, TELOPT_SGA); 439 put_iac3_IAC_x_y(DO, TELOPT_SGA);
453 iac_flush(); 440 iac_flush();
454} 441}
455 442
@@ -459,24 +446,24 @@ static void do_linemode(void)
459 G.telflags &= ~(UF_ECHO | UF_SGA); 446 G.telflags &= ~(UF_ECHO | UF_SGA);
460 setConMode(); 447 setConMode();
461 448
462 put_iac2(DONT, TELOPT_ECHO); 449 put_iac3_IAC_x_y(DONT, TELOPT_ECHO);
463 put_iac2(DONT, TELOPT_SGA); 450 put_iac3_IAC_x_y(DONT, TELOPT_SGA);
464 iac_flush(); 451 iac_flush();
465} 452}
466 453
467static void to_notsup(char c) 454static void to_notsup(char c)
468{ 455{
469 if (G.telwish == WILL) 456 if (G.telwish == WILL)
470 put_iac2(DONT, c); 457 put_iac3_IAC_x_y(DONT, c);
471 else if (G.telwish == DO) 458 else if (G.telwish == DO)
472 put_iac2(WONT, c); 459 put_iac3_IAC_x_y(WONT, c);
473} 460}
474 461
475static void to_echo(void) 462static void to_echo(void)
476{ 463{
477 /* if server requests ECHO, don't agree */ 464 /* if server requests ECHO, don't agree */
478 if (G.telwish == DO) { 465 if (G.telwish == DO) {
479 put_iac2(WONT, TELOPT_ECHO); 466 put_iac3_IAC_x_y(WONT, TELOPT_ECHO);
480 return; 467 return;
481 } 468 }
482 if (G.telwish == DONT) 469 if (G.telwish == DONT)
@@ -492,9 +479,9 @@ static void to_echo(void)
492 G.telflags ^= UF_ECHO; 479 G.telflags ^= UF_ECHO;
493 480
494 if (G.telflags & UF_ECHO) 481 if (G.telflags & UF_ECHO)
495 put_iac2(DO, TELOPT_ECHO); 482 put_iac3_IAC_x_y(DO, TELOPT_ECHO);
496 else 483 else
497 put_iac2(DONT, TELOPT_ECHO); 484 put_iac3_IAC_x_y(DONT, TELOPT_ECHO);
498 485
499 setConMode(); 486 setConMode();
500 full_write1_str("\r\n"); /* sudden modec */ 487 full_write1_str("\r\n"); /* sudden modec */
@@ -512,9 +499,9 @@ static void to_sga(void)
512 499
513 G.telflags ^= UF_SGA; /* toggle */ 500 G.telflags ^= UF_SGA; /* toggle */
514 if (G.telflags & UF_SGA) 501 if (G.telflags & UF_SGA)
515 put_iac2(DO, TELOPT_SGA); 502 put_iac3_IAC_x_y(DO, TELOPT_SGA);
516 else 503 else
517 put_iac2(DONT, TELOPT_SGA); 504 put_iac3_IAC_x_y(DONT, TELOPT_SGA);
518} 505}
519 506
520#if ENABLE_FEATURE_TELNET_TTYPE 507#if ENABLE_FEATURE_TELNET_TTYPE
@@ -522,9 +509,9 @@ static void to_ttype(void)
522{ 509{
523 /* Tell server we will (or won't) do TTYPE */ 510 /* Tell server we will (or won't) do TTYPE */
524 if (G.ttype) 511 if (G.ttype)
525 put_iac2(WILL, TELOPT_TTYPE); 512 put_iac3_IAC_x_y(WILL, TELOPT_TTYPE);
526 else 513 else
527 put_iac2(WONT, TELOPT_TTYPE); 514 put_iac3_IAC_x_y(WONT, TELOPT_TTYPE);
528} 515}
529#endif 516#endif
530 517
@@ -533,9 +520,9 @@ static void to_new_environ(void)
533{ 520{
534 /* Tell server we will (or will not) do AUTOLOGIN */ 521 /* Tell server we will (or will not) do AUTOLOGIN */
535 if (G.autologin) 522 if (G.autologin)
536 put_iac2(WILL, TELOPT_NEW_ENVIRON); 523 put_iac3_IAC_x_y(WILL, TELOPT_NEW_ENVIRON);
537 else 524 else
538 put_iac2(WONT, TELOPT_NEW_ENVIRON); 525 put_iac3_IAC_x_y(WONT, TELOPT_NEW_ENVIRON);
539} 526}
540#endif 527#endif
541 528
@@ -543,7 +530,7 @@ static void to_new_environ(void)
543static void to_naws(void) 530static void to_naws(void)
544{ 531{
545 /* Tell server we will do NAWS */ 532 /* Tell server we will do NAWS */
546 put_iac2(WILL, TELOPT_NAWS); 533 put_iac3_IAC_x_y(WILL, TELOPT_NAWS);
547} 534}
548#endif 535#endif
549 536