diff options
-rw-r--r-- | networking/telnet.c | 119 |
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 | ||
153 | static void iac_flush(void) | 153 | static 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 | ||
159 | static void doexit(int ev) NORETURN; | 161 | static void doexit(int ev) NORETURN; |
@@ -338,88 +340,73 @@ static void handle_net_input(int len) | |||
338 | 340 | ||
339 | static void put_iac(int c) | 341 | static 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 | ||
344 | static void put_iac2_merged(unsigned wwdd_and_c) | 352 | static 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 | ||
359 | static 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 | |||
366 | static 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 |
356 | static void put_iac_subopt(byte c, char *str) | 374 | static 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 |
377 | static void put_iac_subopt_autologin(void) | 386 | static 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 |
406 | static void put_iac_naws(byte c, int x, int y) | 403 | static 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 | ||
467 | static void to_notsup(char c) | 454 | static 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 | ||
475 | static void to_echo(void) | 462 | static 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) | |||
543 | static void to_naws(void) | 530 | static 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 | ||