diff options
Diffstat (limited to 'networking/telnetd.c')
-rw-r--r-- | networking/telnetd.c | 107 |
1 files changed, 99 insertions, 8 deletions
diff --git a/networking/telnetd.c b/networking/telnetd.c index d208319a3..d17682eb4 100644 --- a/networking/telnetd.c +++ b/networking/telnetd.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: telnetd.c,v 1.2 2002/11/10 22:26:19 bug1 Exp $ | 1 | /* $Id: telnetd.c,v 1.3 2003/01/21 20:55:56 bug1 Exp $ |
2 | * | 2 | * |
3 | * Simple telnet server | 3 | * Simple telnet server |
4 | * Bjorn Wesen, Axis Communications AB (bjornw@axis.com) | 4 | * Bjorn Wesen, Axis Communications AB (bjornw@axis.com) |
@@ -48,7 +48,13 @@ | |||
48 | 48 | ||
49 | #define BUFSIZE 4000 | 49 | #define BUFSIZE 4000 |
50 | 50 | ||
51 | static const char *loginpath = "/bin/sh"; | 51 | static const char *loginpath = |
52 | #ifdef CONFIG_LOGIN | ||
53 | "/bin/login"; | ||
54 | #else | ||
55 | "/bin/sh"; | ||
56 | #endif | ||
57 | static const char *issuefile = "/etc/issue.net"; | ||
52 | 58 | ||
53 | /* shell name and arguments */ | 59 | /* shell name and arguments */ |
54 | 60 | ||
@@ -57,8 +63,12 @@ static const char *argv_init[] = {NULL, NULL}; | |||
57 | /* structure that describes a session */ | 63 | /* structure that describes a session */ |
58 | 64 | ||
59 | struct tsession { | 65 | struct tsession { |
66 | #ifdef CONFIG_FEATURE_TELNETD_INETD | ||
67 | int sockfd_read, sockfd_write, ptyfd; | ||
68 | #else /* CONFIG_FEATURE_TELNETD_INETD */ | ||
60 | struct tsession *next; | 69 | struct tsession *next; |
61 | int sockfd, ptyfd; | 70 | int sockfd, ptyfd; |
71 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
62 | int shell_pid; | 72 | int shell_pid; |
63 | /* two circular buffers */ | 73 | /* two circular buffers */ |
64 | char *buf1, *buf2; | 74 | char *buf1, *buf2; |
@@ -204,7 +214,11 @@ send_iac(struct tsession *ts, unsigned char command, int option) | |||
204 | 214 | ||
205 | 215 | ||
206 | static struct tsession * | 216 | static struct tsession * |
217 | #ifdef CONFIG_FEATURE_TELNETD_INETD | ||
218 | make_new_session(void) | ||
219 | #else /* CONFIG_FEATURE_TELNETD_INETD */ | ||
207 | make_new_session(int sockfd) | 220 | make_new_session(int sockfd) |
221 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
208 | { | 222 | { |
209 | struct termios termbuf; | 223 | struct termios termbuf; |
210 | int pty, pid; | 224 | int pty, pid; |
@@ -214,7 +228,12 @@ make_new_session(int sockfd) | |||
214 | ts->buf1 = (char *)(&ts[1]); | 228 | ts->buf1 = (char *)(&ts[1]); |
215 | ts->buf2 = ts->buf1 + BUFSIZE; | 229 | ts->buf2 = ts->buf1 + BUFSIZE; |
216 | 230 | ||
231 | #ifdef CONFIG_FEATURE_TELNETD_INETD | ||
232 | ts->sockfd_read = 0; | ||
233 | ts->sockfd_write = 1; | ||
234 | #else /* CONFIG_FEATURE_TELNETD_INETD */ | ||
217 | ts->sockfd = sockfd; | 235 | ts->sockfd = sockfd; |
236 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
218 | 237 | ||
219 | ts->rdidx1 = ts->wridx1 = ts->size1 = 0; | 238 | ts->rdidx1 = ts->wridx1 = ts->size1 = 0; |
220 | ts->rdidx2 = ts->wridx2 = ts->size2 = 0; | 239 | ts->rdidx2 = ts->wridx2 = ts->size2 = 0; |
@@ -278,6 +297,8 @@ make_new_session(int sockfd) | |||
278 | /*termbuf.c_lflag &= ~ICANON;*/ | 297 | /*termbuf.c_lflag &= ~ICANON;*/ |
279 | tcsetattr(0, TCSANOW, &termbuf); | 298 | tcsetattr(0, TCSANOW, &termbuf); |
280 | 299 | ||
300 | print_login_issue(issuefile, NULL); | ||
301 | |||
281 | /* exec shell, with correct argv and env */ | 302 | /* exec shell, with correct argv and env */ |
282 | execv(loginpath, (char *const *)argv_init); | 303 | execv(loginpath, (char *const *)argv_init); |
283 | 304 | ||
@@ -291,6 +312,7 @@ make_new_session(int sockfd) | |||
291 | return ts; | 312 | return ts; |
292 | } | 313 | } |
293 | 314 | ||
315 | #ifndef CONFIG_FEATURE_TELNETD_INETD | ||
294 | static void | 316 | static void |
295 | free_session(struct tsession *ts) | 317 | free_session(struct tsession *ts) |
296 | { | 318 | { |
@@ -319,30 +341,44 @@ free_session(struct tsession *ts) | |||
319 | 341 | ||
320 | free(ts); | 342 | free(ts); |
321 | } | 343 | } |
344 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
322 | 345 | ||
323 | int | 346 | int |
324 | telnetd_main(int argc, char **argv) | 347 | telnetd_main(int argc, char **argv) |
325 | { | 348 | { |
349 | #ifndef CONFIG_FEATURE_TELNETD_INETD | ||
326 | struct sockaddr_in sa; | 350 | struct sockaddr_in sa; |
327 | int master_fd; | 351 | int master_fd; |
352 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
328 | fd_set rdfdset, wrfdset; | 353 | fd_set rdfdset, wrfdset; |
329 | int selret; | 354 | int selret; |
355 | #ifndef CONFIG_FEATURE_TELNETD_INETD | ||
330 | int on = 1; | 356 | int on = 1; |
331 | int portnbr = 23; | 357 | int portnbr = 23; |
358 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
332 | int c; | 359 | int c; |
333 | 360 | static const char options[] = | |
334 | /* check if user supplied a port number */ | 361 | #ifdef CONFIG_FEATURE_TELNETD_INETD |
362 | "f:l:"; | ||
363 | #else /* CONFIG_EATURE_TELNETD_INETD */ | ||
364 | "f:l:p:"; | ||
365 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
335 | 366 | ||
336 | for (;;) { | 367 | for (;;) { |
337 | c = getopt( argc, argv, "p:l:"); | 368 | c = getopt( argc, argv, options); |
338 | if (c == EOF) break; | 369 | if (c == EOF) break; |
339 | switch (c) { | 370 | switch (c) { |
340 | case 'p': | 371 | case 'f': |
341 | portnbr = atoi(optarg); | 372 | issuefile = strdup (optarg); |
342 | break; | 373 | break; |
343 | case 'l': | 374 | case 'l': |
344 | loginpath = strdup (optarg); | 375 | loginpath = strdup (optarg); |
345 | break; | 376 | break; |
377 | #ifndef CONFIG_FEATURE_TELNETD_INETD | ||
378 | case 'p': | ||
379 | portnbr = atoi(optarg); | ||
380 | break; | ||
381 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
346 | default: | 382 | default: |
347 | show_usage(); | 383 | show_usage(); |
348 | } | 384 | } |
@@ -353,6 +389,12 @@ telnetd_main(int argc, char **argv) | |||
353 | } | 389 | } |
354 | 390 | ||
355 | argv_init[0] = loginpath; | 391 | argv_init[0] = loginpath; |
392 | |||
393 | #ifdef CONFIG_FEATURE_TELNETD_INETD | ||
394 | sessions = make_new_session(); | ||
395 | |||
396 | maxfd = 1; | ||
397 | #else /* CONFIG_EATURE_TELNETD_INETD */ | ||
356 | sessions = 0; | 398 | sessions = 0; |
357 | 399 | ||
358 | /* Grab a TCP socket. */ | 400 | /* Grab a TCP socket. */ |
@@ -382,6 +424,7 @@ telnetd_main(int argc, char **argv) | |||
382 | 424 | ||
383 | 425 | ||
384 | maxfd = master_fd; | 426 | maxfd = master_fd; |
427 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
385 | 428 | ||
386 | do { | 429 | do { |
387 | struct tsession *ts; | 430 | struct tsession *ts; |
@@ -393,10 +436,14 @@ telnetd_main(int argc, char **argv) | |||
393 | * ptys if there is room in their respective session buffers. | 436 | * ptys if there is room in their respective session buffers. |
394 | */ | 437 | */ |
395 | 438 | ||
439 | #ifndef CONFIG_FEATURE_TELNETD_INETD | ||
396 | FD_SET(master_fd, &rdfdset); | 440 | FD_SET(master_fd, &rdfdset); |
441 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
397 | 442 | ||
398 | ts = sessions; | 443 | ts = sessions; |
444 | #ifndef CONFIG_FEATURE_TELNETD_INETD | ||
399 | while (ts) { | 445 | while (ts) { |
446 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
400 | /* buf1 is used from socket to pty | 447 | /* buf1 is used from socket to pty |
401 | * buf2 is used from pty to socket | 448 | * buf2 is used from pty to socket |
402 | */ | 449 | */ |
@@ -404,22 +451,33 @@ telnetd_main(int argc, char **argv) | |||
404 | FD_SET(ts->ptyfd, &wrfdset); /* can write to pty */ | 451 | FD_SET(ts->ptyfd, &wrfdset); /* can write to pty */ |
405 | } | 452 | } |
406 | if (ts->size1 < BUFSIZE) { | 453 | if (ts->size1 < BUFSIZE) { |
454 | #ifdef CONFIG_FEATURE_TELNETD_INETD | ||
455 | FD_SET(ts->sockfd_read, &rdfdset); /* can read from socket */ | ||
456 | #else /* CONFIG_FEATURE_TELNETD_INETD */ | ||
407 | FD_SET(ts->sockfd, &rdfdset); /* can read from socket */ | 457 | FD_SET(ts->sockfd, &rdfdset); /* can read from socket */ |
458 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
408 | } | 459 | } |
409 | if (ts->size2 > 0) { | 460 | if (ts->size2 > 0) { |
461 | #ifdef CONFIG_FEATURE_TELNETD_INETD | ||
462 | FD_SET(ts->sockfd_write, &wrfdset); /* can write to socket */ | ||
463 | #else /* CONFIG_FEATURE_TELNETD_INETD */ | ||
410 | FD_SET(ts->sockfd, &wrfdset); /* can write to socket */ | 464 | FD_SET(ts->sockfd, &wrfdset); /* can write to socket */ |
465 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
411 | } | 466 | } |
412 | if (ts->size2 < BUFSIZE) { | 467 | if (ts->size2 < BUFSIZE) { |
413 | FD_SET(ts->ptyfd, &rdfdset); /* can read from pty */ | 468 | FD_SET(ts->ptyfd, &rdfdset); /* can read from pty */ |
414 | } | 469 | } |
470 | #ifndef CONFIG_FEATURE_TELNETD_INETD | ||
415 | ts = ts->next; | 471 | ts = ts->next; |
416 | } | 472 | } |
473 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
417 | 474 | ||
418 | selret = select(maxfd + 1, &rdfdset, &wrfdset, 0, 0); | 475 | selret = select(maxfd + 1, &rdfdset, &wrfdset, 0, 0); |
419 | 476 | ||
420 | if (!selret) | 477 | if (!selret) |
421 | break; | 478 | break; |
422 | 479 | ||
480 | #ifndef CONFIG_FEATURE_TELNETD_INETD | ||
423 | /* First check for and accept new sessions. */ | 481 | /* First check for and accept new sessions. */ |
424 | if (FD_ISSET(master_fd, &rdfdset)) { | 482 | if (FD_ISSET(master_fd, &rdfdset)) { |
425 | int fd, salen; | 483 | int fd, salen; |
@@ -447,9 +505,12 @@ telnetd_main(int argc, char **argv) | |||
447 | 505 | ||
448 | ts = sessions; | 506 | ts = sessions; |
449 | while (ts) { /* For all sessions... */ | 507 | while (ts) { /* For all sessions... */ |
508 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
450 | int maxlen, w, r; | 509 | int maxlen, w, r; |
510 | #ifndef CONFIG_FEATURE_TELNETD_INETD | ||
451 | struct tsession *next = ts->next; /* in case we free ts. */ | 511 | struct tsession *next = ts->next; /* in case we free ts. */ |
452 | 512 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | |
513 | |||
453 | if (ts->size1 && FD_ISSET(ts->ptyfd, &wrfdset)) { | 514 | if (ts->size1 && FD_ISSET(ts->ptyfd, &wrfdset)) { |
454 | int num_totty; | 515 | int num_totty; |
455 | char *ptr; | 516 | char *ptr; |
@@ -459,9 +520,13 @@ telnetd_main(int argc, char **argv) | |||
459 | 520 | ||
460 | w = write(ts->ptyfd, ptr, num_totty); | 521 | w = write(ts->ptyfd, ptr, num_totty); |
461 | if (w < 0) { | 522 | if (w < 0) { |
523 | #ifdef CONFIG_FEATURE_TELNETD_INETD | ||
524 | exit(0); | ||
525 | #else /* CONFIG_FEATURE_TELNETD_INETD */ | ||
462 | free_session(ts); | 526 | free_session(ts); |
463 | ts = next; | 527 | ts = next; |
464 | continue; | 528 | continue; |
529 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
465 | } | 530 | } |
466 | ts->wridx1 += w; | 531 | ts->wridx1 += w; |
467 | ts->size1 -= w; | 532 | ts->size1 -= w; |
@@ -469,31 +534,51 @@ telnetd_main(int argc, char **argv) | |||
469 | ts->wridx1 = 0; | 534 | ts->wridx1 = 0; |
470 | } | 535 | } |
471 | 536 | ||
537 | #ifdef CONFIG_FEATURE_TELNETD_INETD | ||
538 | if (ts->size2 && FD_ISSET(ts->sockfd_write, &wrfdset)) { | ||
539 | #else /* CONFIG_FEATURE_TELNETD_INETD */ | ||
472 | if (ts->size2 && FD_ISSET(ts->sockfd, &wrfdset)) { | 540 | if (ts->size2 && FD_ISSET(ts->sockfd, &wrfdset)) { |
541 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
473 | /* Write to socket from buffer 2. */ | 542 | /* Write to socket from buffer 2. */ |
474 | maxlen = MIN(BUFSIZE - ts->wridx2, ts->size2); | 543 | maxlen = MIN(BUFSIZE - ts->wridx2, ts->size2); |
544 | #ifdef CONFIG_FEATURE_TELNETD_INETD | ||
545 | w = write(ts->sockfd_write, ts->buf2 + ts->wridx2, maxlen); | ||
546 | if (w < 0) | ||
547 | exit(0); | ||
548 | #else /* CONFIG_FEATURE_TELNETD_INETD */ | ||
475 | w = write(ts->sockfd, ts->buf2 + ts->wridx2, maxlen); | 549 | w = write(ts->sockfd, ts->buf2 + ts->wridx2, maxlen); |
476 | if (w < 0) { | 550 | if (w < 0) { |
477 | free_session(ts); | 551 | free_session(ts); |
478 | ts = next; | 552 | ts = next; |
479 | continue; | 553 | continue; |
480 | } | 554 | } |
555 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
481 | ts->wridx2 += w; | 556 | ts->wridx2 += w; |
482 | ts->size2 -= w; | 557 | ts->size2 -= w; |
483 | if (ts->wridx2 == BUFSIZE) | 558 | if (ts->wridx2 == BUFSIZE) |
484 | ts->wridx2 = 0; | 559 | ts->wridx2 = 0; |
485 | } | 560 | } |
486 | 561 | ||
562 | #ifdef CONFIG_FEATURE_TELNETD_INETD | ||
563 | if (ts->size1 < BUFSIZE && FD_ISSET(ts->sockfd_read, &rdfdset)) { | ||
564 | #else /* CONFIG_FEATURE_TELNETD_INETD */ | ||
487 | if (ts->size1 < BUFSIZE && FD_ISSET(ts->sockfd, &rdfdset)) { | 565 | if (ts->size1 < BUFSIZE && FD_ISSET(ts->sockfd, &rdfdset)) { |
566 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
488 | /* Read from socket to buffer 1. */ | 567 | /* Read from socket to buffer 1. */ |
489 | maxlen = MIN(BUFSIZE - ts->rdidx1, | 568 | maxlen = MIN(BUFSIZE - ts->rdidx1, |
490 | BUFSIZE - ts->size1); | 569 | BUFSIZE - ts->size1); |
570 | #ifdef CONFIG_FEATURE_TELNETD_INETD | ||
571 | r = read(ts->sockfd_read, ts->buf1 + ts->rdidx1, maxlen); | ||
572 | if (!r || (r < 0 && errno != EINTR)) | ||
573 | exit(0); | ||
574 | #else /* CONFIG_FEATURE_TELNETD_INETD */ | ||
491 | r = read(ts->sockfd, ts->buf1 + ts->rdidx1, maxlen); | 575 | r = read(ts->sockfd, ts->buf1 + ts->rdidx1, maxlen); |
492 | if (!r || (r < 0 && errno != EINTR)) { | 576 | if (!r || (r < 0 && errno != EINTR)) { |
493 | free_session(ts); | 577 | free_session(ts); |
494 | ts = next; | 578 | ts = next; |
495 | continue; | 579 | continue; |
496 | } | 580 | } |
581 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
497 | if(!*(ts->buf1 + ts->rdidx1 + r - 1)) { | 582 | if(!*(ts->buf1 + ts->rdidx1 + r - 1)) { |
498 | r--; | 583 | r--; |
499 | if(!r) | 584 | if(!r) |
@@ -511,9 +596,13 @@ telnetd_main(int argc, char **argv) | |||
511 | BUFSIZE - ts->size2); | 596 | BUFSIZE - ts->size2); |
512 | r = read(ts->ptyfd, ts->buf2 + ts->rdidx2, maxlen); | 597 | r = read(ts->ptyfd, ts->buf2 + ts->rdidx2, maxlen); |
513 | if (!r || (r < 0 && errno != EINTR)) { | 598 | if (!r || (r < 0 && errno != EINTR)) { |
599 | #ifdef CONFIG_FEATURE_TELNETD_INETD | ||
600 | exit(0); | ||
601 | #else /* CONFIG_FEATURE_TELNETD_INETD */ | ||
514 | free_session(ts); | 602 | free_session(ts); |
515 | ts = next; | 603 | ts = next; |
516 | continue; | 604 | continue; |
605 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
517 | } | 606 | } |
518 | ts->rdidx2 += r; | 607 | ts->rdidx2 += r; |
519 | ts->size2 += r; | 608 | ts->size2 += r; |
@@ -529,8 +618,10 @@ telnetd_main(int argc, char **argv) | |||
529 | ts->rdidx2 = 0; | 618 | ts->rdidx2 = 0; |
530 | ts->wridx2 = 0; | 619 | ts->wridx2 = 0; |
531 | } | 620 | } |
621 | #ifndef CONFIG_FEATURE_TELNETD_INETD | ||
532 | ts = next; | 622 | ts = next; |
533 | } | 623 | } |
624 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | ||
534 | 625 | ||
535 | } while (1); | 626 | } while (1); |
536 | 627 | ||