-/* $Id: telnetd.c,v 1.11 2004/03/15 08:28:53 andersen Exp $
- *
+/* vi: set sw=4 ts=4: */
+/*
* Simple telnet server
* Bjorn Wesen, Axis Communications AB (bjornw@axis.com)
*
- * This file is distributed under the Gnu Public License (GPL),
- * please see the file LICENSE for further information.
+ * Licensed under GPL, see file LICENSE in this tarball for details.
*
* ---------------------------------------------------------------------------
* (C) Copyright 2000, Axis Communications AB, LUND, SWEDEN
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#include <fcntl.h>
#include <stdio.h>
#include <signal.h>
#define BUFSIZE 4000
-static const char *loginpath
+#ifdef CONFIG_FEATURE_IPV6
+#define SOCKET_TYPE AF_INET6
+typedef struct sockaddr_in6 sockaddr_type;
+#else
+#define SOCKET_TYPE AF_INET
+typedef struct sockaddr_in sockaddr_type;
+#endif
+
+
#ifdef CONFIG_LOGIN
- = "/bin/login";
+static const char *loginpath = "/bin/login";
#else
-;
+static const char *loginpath;
#endif
static const char *issuefile = "/etc/issue.net";
+-------+ wridx1++ +------+ rdidx1++ +----------+
| | <-------------- | buf1 | <-------------- | |
| | size1-- +------+ size1++ | |
- | pty | | socket |
+ | pty | | socket |
| | rdidx2++ +------+ wridx2++ | |
| | --------------> | buf2 | --------------> | |
+-------+ size2++ +------+ size2-- +----------+
*/
static char *
remove_iacs(struct tsession *ts, int *pnum_totty) {
- unsigned char *ptr0 = ts->buf1 + ts->wridx1;
+ unsigned char *ptr0 = (unsigned char *)ts->buf1 + ts->wridx1;
unsigned char *ptr = ptr0;
unsigned char *totty = ptr;
unsigned char *end = ptr + MIN(BUFSIZE - ts->wridx1, ts->size1);
else if (ptr[1] == SB && ptr[2] == TELOPT_NAWS) {
struct winsize ws;
if ((ptr+8) >= end)
- break; /* incomplete, can't process */
+ break; /* incomplete, can't process */
ws.ws_col = (ptr[3] << 8) | ptr[4];
ws.ws_row = (ptr[5] << 8) | ptr[6];
(void) ioctl(ts->ptyfd, TIOCSWINSZ, (char *)&ws);
pty = getpty(tty_name);
if (pty < 0) {
- syslog_msg(LOG_USER, LOG_ERR, "All network ports in use!");
+ syslog(LOG_ERR, "All network ports in use!");
return 0;
}
if ((pid = fork()) < 0) {
- syslog_msg(LOG_USER, LOG_ERR, "Can`t forking");
+ syslog(LOG_ERR, "Can`t forking");
}
if (pid == 0) {
/* In child, open the child's side of the tty. */
setsid();
if (open(tty_name, O_RDWR /*| O_NOCTTY*/) < 0) {
- syslog_msg(LOG_USER, LOG_ERR, "Could not open tty");
+ syslog(LOG_ERR, "Could not open tty");
exit(1);
}
dup(0);
execv(loginpath, (char *const *)argv_init);
/* NOT REACHED */
- syslog_msg(LOG_USER, LOG_ERR, "execv error");
+ syslog(LOG_ERR, "execv error");
exit(1);
}
telnetd_main(int argc, char **argv)
{
#ifndef CONFIG_FEATURE_TELNETD_INETD
- struct sockaddr_in sa;
+ sockaddr_type sa;
int master_fd;
#endif /* CONFIG_FEATURE_TELNETD_INETD */
fd_set rdfdset, wrfdset;
#ifndef CONFIG_FEATURE_TELNETD_INETD
int on = 1;
int portnbr = 23;
+ struct in_addr bind_addr = { .s_addr = 0x0 };
#endif /* CONFIG_FEATURE_TELNETD_INETD */
int c;
static const char options[] =
#ifdef CONFIG_FEATURE_TELNETD_INETD
"f:l:";
#else /* CONFIG_EATURE_TELNETD_INETD */
- "f:l:p:";
+ "f:l:p:b:";
#endif /* CONFIG_FEATURE_TELNETD_INETD */
int maxlen, w, r;
if (c == EOF) break;
switch (c) {
case 'f':
- issuefile = strdup (optarg);
+ issuefile = optarg;
break;
case 'l':
- loginpath = strdup (optarg);
+ loginpath = optarg;
break;
#ifndef CONFIG_FEATURE_TELNETD_INETD
case 'p':
portnbr = atoi(optarg);
break;
+ case 'b':
+ if (inet_aton(optarg, &bind_addr) == 0)
+ bb_show_usage();
+ break;
#endif /* CONFIG_FEATURE_TELNETD_INETD */
default:
bb_show_usage();
argv_init[0] = loginpath;
+ openlog(bb_applet_name, 0, LOG_USER);
+
#ifdef CONFIG_FEATURE_TELNETD_INETD
maxfd = 1;
sessions = make_new_session();
/* Grab a TCP socket. */
- master_fd = socket(AF_INET, SOCK_STREAM, 0);
- if (master_fd < 0) {
- bb_perror_msg_and_die("socket");
- }
+ master_fd = bb_xsocket(SOCKET_TYPE, SOCK_STREAM, 0);
(void)setsockopt(master_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
/* Set it to listen to specified port. */
memset((void *)&sa, 0, sizeof(sa));
+#ifdef CONFIG_FEATURE_IPV6
+ sa.sin6_family = AF_INET6;
+ sa.sin6_port = htons(portnbr);
+ /* sa.sin6_addr = bind_addr6; */
+#else
sa.sin_family = AF_INET;
sa.sin_port = htons(portnbr);
+ sa.sin_addr = bind_addr;
+#endif
- if (bind(master_fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
- bb_perror_msg_and_die("bind");
- }
-
- if (listen(master_fd, 1) < 0) {
- bb_perror_msg_and_die("listen");
- }
-
- if (daemon(0, 0) < 0)
- bb_perror_msg_and_die("daemon");
-
+ bb_xbind(master_fd, (struct sockaddr *) &sa, sizeof(sa));
+ bb_xlisten(master_fd, 1);
+ bb_xdaemon(0, 0);
maxfd = master_fd;
#endif /* CONFIG_FEATURE_TELNETD_INETD */