|
|
e4a049 |
diff -uNr netkit-telnet-0.17/telnetd/telnetd.c netkit-telnet-0.17.ipv6/telnetd/telnetd.c
|
|
|
e4a049 |
--- netkit-telnet-0.17/telnetd/telnetd.c 2006-07-13 08:37:18.000000000 +0200
|
|
|
e4a049 |
+++ netkit-telnet-0.17.ipv6/telnetd/telnetd.c 2006-07-14 08:36:11.000000000 +0200
|
|
|
e4a049 |
@@ -49,6 +49,7 @@
|
|
|
e4a049 |
/* #include <netinet/ip.h> */ /* Don't think this is used at all here */
|
|
|
e4a049 |
#include <arpa/inet.h>
|
|
|
e4a049 |
#include <assert.h>
|
|
|
e4a049 |
+#include <sys/poll.h>
|
|
|
e4a049 |
#include "telnetd.h"
|
|
|
e4a049 |
#include "pathnames.h"
|
|
|
e4a049 |
#include "setproctitle.h"
|
|
|
e4a049 |
@@ -68,7 +69,7 @@
|
|
|
e4a049 |
#define HAS_IPPROTO_IP
|
|
|
e4a049 |
#endif
|
|
|
e4a049 |
|
|
|
e4a049 |
-static void doit(struct sockaddr_in *who);
|
|
|
e4a049 |
+static void doit(struct sockaddr *who, socklen_t wholen);
|
|
|
e4a049 |
static int terminaltypeok(const char *s);
|
|
|
e4a049 |
|
|
|
e4a049 |
/*
|
|
|
e4a049 |
@@ -90,7 +91,7 @@
|
|
|
e4a049 |
int
|
|
|
e4a049 |
main(int argc, char *argv[], char *env[])
|
|
|
e4a049 |
{
|
|
|
e4a049 |
- struct sockaddr_in from;
|
|
|
e4a049 |
+ struct sockaddr from;
|
|
|
e4a049 |
int on = 1;
|
|
|
e4a049 |
socklen_t fromlen;
|
|
|
e4a049 |
register int ch;
|
|
|
e4a049 |
@@ -248,64 +249,89 @@
|
|
|
e4a049 |
argc -= optind;
|
|
|
e4a049 |
argv += optind;
|
|
|
e4a049 |
|
|
|
e4a049 |
- if (debug) {
|
|
|
e4a049 |
- int s, ns;
|
|
|
e4a049 |
- socklen_t foo;
|
|
|
e4a049 |
- struct servent *sp;
|
|
|
e4a049 |
- struct sockaddr_in sn;
|
|
|
e4a049 |
+ int s = 0;
|
|
|
e4a049 |
|
|
|
e4a049 |
- memset(&sn, 0, sizeof(sn));
|
|
|
e4a049 |
- sn.sin_family = AF_INET;
|
|
|
e4a049 |
+ if (debug) {
|
|
|
e4a049 |
+ struct addrinfo *ai;
|
|
|
e4a049 |
+ unsigned int nfds = 0;
|
|
|
e4a049 |
+ struct pollfd fds[2];
|
|
|
e4a049 |
|
|
|
e4a049 |
if (argc > 1) {
|
|
|
e4a049 |
- usage();
|
|
|
e4a049 |
- /* NOTREACHED */
|
|
|
e4a049 |
- } else if (argc == 1) {
|
|
|
e4a049 |
- if ((sp = getservbyname(*argv, "tcp"))!=NULL) {
|
|
|
e4a049 |
- sn.sin_port = sp->s_port;
|
|
|
e4a049 |
- }
|
|
|
e4a049 |
- else {
|
|
|
e4a049 |
- int pt = atoi(*argv);
|
|
|
e4a049 |
- if (pt <= 0) {
|
|
|
e4a049 |
- fprintf(stderr, "telnetd: %s: bad port number\n",
|
|
|
e4a049 |
- *argv);
|
|
|
e4a049 |
- usage();
|
|
|
e4a049 |
- /* NOTREACHED */
|
|
|
e4a049 |
- }
|
|
|
e4a049 |
- sn.sin_port = htons(pt);
|
|
|
e4a049 |
- }
|
|
|
e4a049 |
+ usage();
|
|
|
e4a049 |
+ /* NOTREACHED */
|
|
|
e4a049 |
} else {
|
|
|
e4a049 |
- sp = getservbyname("telnet", "tcp");
|
|
|
e4a049 |
- if (sp == 0) {
|
|
|
e4a049 |
- fprintf(stderr, "telnetd: tcp/telnet: unknown service\n");
|
|
|
e4a049 |
- exit(1);
|
|
|
e4a049 |
- }
|
|
|
e4a049 |
- sn.sin_port = sp->s_port;
|
|
|
e4a049 |
- }
|
|
|
e4a049 |
+ struct addrinfo hints;
|
|
|
e4a049 |
+
|
|
|
e4a049 |
+ memset (&hints, '\0', sizeof (hints));
|
|
|
e4a049 |
+ hints.ai_socktype = SOCK_STREAM;
|
|
|
e4a049 |
+ hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
|
|
|
e4a049 |
+ hints.ai_protocol = IPPROTO_TCP;
|
|
|
e4a049 |
+
|
|
|
e4a049 |
+ if (argc == 0) {
|
|
|
e4a049 |
+ if (getaddrinfo(NULL, "telnet", &hints, &ai) != 0) {
|
|
|
e4a049 |
+ fprintf(stderr, "telnetd: %s: bad port number\n", *argv);
|
|
|
e4a049 |
+ usage();
|
|
|
e4a049 |
+ /* NOTREACHED */
|
|
|
e4a049 |
+ }
|
|
|
e4a049 |
+ } else {
|
|
|
e4a049 |
+ if (getaddrinfo(NULL, *argv, &hints, &ai) != 0) {
|
|
|
e4a049 |
+ fprintf(stderr, "telnetd: %s: bad port number\n", *argv);
|
|
|
e4a049 |
+ usage();
|
|
|
e4a049 |
+ /* NOTREACHED */
|
|
|
e4a049 |
+ }
|
|
|
e4a049 |
+ }
|
|
|
e4a049 |
+ }
|
|
|
e4a049 |
|
|
|
e4a049 |
- s = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
e4a049 |
- if (s < 0) {
|
|
|
e4a049 |
+ struct addrinfo *runp;
|
|
|
e4a049 |
+ int b = 0;
|
|
|
e4a049 |
+ for (runp = ai; ((runp != NULL) && (nfds < sizeof (fds) / sizeof (fds[0]))); runp = runp->ai_next) {
|
|
|
e4a049 |
+ fds[nfds].fd = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
|
|
|
e4a049 |
+ if (fds[nfds].fd < 0) {
|
|
|
e4a049 |
perror("telnetd: socket");;
|
|
|
e4a049 |
- exit(1);
|
|
|
e4a049 |
+ exit(1);
|
|
|
e4a049 |
+ }
|
|
|
e4a049 |
+ fds[nfds].events = POLLIN;
|
|
|
e4a049 |
+ (void) setsockopt(fds[nfds].fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
|
|
e4a049 |
+
|
|
|
e4a049 |
+ if (bind(fds[nfds].fd, runp->ai_addr, runp->ai_addrlen) != 0) {
|
|
|
e4a049 |
+ // Unable to bind to given port. One of the reason can be
|
|
|
e4a049 |
+ // that we can't bind to both IPv4 and IPv6
|
|
|
e4a049 |
+ break;
|
|
|
e4a049 |
+ } else {
|
|
|
e4a049 |
+ b++;
|
|
|
e4a049 |
+ }
|
|
|
e4a049 |
+
|
|
|
e4a049 |
+ if (listen(fds[nfds].fd, 1) < 0) {
|
|
|
e4a049 |
+ perror("listen");
|
|
|
e4a049 |
+ exit(1);
|
|
|
e4a049 |
+ }
|
|
|
e4a049 |
+ nfds++;
|
|
|
e4a049 |
}
|
|
|
e4a049 |
- (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
|
|
e4a049 |
- if (bind(s, (struct sockaddr *)&sn, sizeof(sn)) < 0) {
|
|
|
e4a049 |
- perror("bind");
|
|
|
e4a049 |
- exit(1);
|
|
|
e4a049 |
- }
|
|
|
e4a049 |
- if (listen(s, 1) < 0) {
|
|
|
e4a049 |
- perror("listen");
|
|
|
e4a049 |
- exit(1);
|
|
|
e4a049 |
+ freeaddrinfo(ai);
|
|
|
e4a049 |
+
|
|
|
e4a049 |
+ if (b == 0) {
|
|
|
e4a049 |
+ perror("bind");
|
|
|
e4a049 |
+ exit(1);
|
|
|
e4a049 |
}
|
|
|
e4a049 |
- foo = sizeof(sn);
|
|
|
e4a049 |
- ns = accept(s, (struct sockaddr *)&sn, &foo;;
|
|
|
e4a049 |
- if (ns < 0) {
|
|
|
e4a049 |
- perror("accept");
|
|
|
e4a049 |
- exit(1);
|
|
|
e4a049 |
+
|
|
|
e4a049 |
+ int n = poll (fds, nfds, -1);
|
|
|
e4a049 |
+ if (n > 0) {
|
|
|
e4a049 |
+ unsigned int i;
|
|
|
e4a049 |
+ for (i = 0; i < nfds; i++) {
|
|
|
e4a049 |
+ if (fds[i].revents & POLLIN) {
|
|
|
e4a049 |
+ struct sockaddr_storage rem;
|
|
|
e4a049 |
+ socklen_t remlen = sizeof(rem);
|
|
|
e4a049 |
+ int fd = accept(fds[i].fd, (struct sockaddr *) &rem, &remlen);
|
|
|
e4a049 |
+
|
|
|
e4a049 |
+ if (fd < 0) {
|
|
|
e4a049 |
+ perror("accept");
|
|
|
e4a049 |
+ exit(1);
|
|
|
e4a049 |
+ }
|
|
|
e4a049 |
+
|
|
|
e4a049 |
+ s = fd;
|
|
|
e4a049 |
+ }
|
|
|
e4a049 |
+ }
|
|
|
e4a049 |
}
|
|
|
e4a049 |
- (void) dup2(ns, 0);
|
|
|
e4a049 |
- (void) close(ns);
|
|
|
e4a049 |
- (void) close(s);
|
|
|
e4a049 |
} else if (argc > 0) {
|
|
|
e4a049 |
usage();
|
|
|
e4a049 |
/* NOT REACHED */
|
|
|
e4a049 |
@@ -313,13 +339,13 @@
|
|
|
e4a049 |
|
|
|
e4a049 |
openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
|
|
|
e4a049 |
fromlen = sizeof (from);
|
|
|
e4a049 |
- if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
|
|
|
e4a049 |
+ if (getpeername(s, &from, &fromlen) < 0) {
|
|
|
e4a049 |
fprintf(stderr, "%s: ", progname);
|
|
|
e4a049 |
perror("getpeername");
|
|
|
e4a049 |
_exit(1);
|
|
|
e4a049 |
}
|
|
|
e4a049 |
if (keepalive &&
|
|
|
e4a049 |
- setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {
|
|
|
e4a049 |
+ setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {
|
|
|
e4a049 |
syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
|
|
|
e4a049 |
}
|
|
|
e4a049 |
|
|
|
e4a049 |
@@ -333,13 +359,13 @@
|
|
|
e4a049 |
if (tos < 0)
|
|
|
e4a049 |
tos = 020; /* Low Delay bit */
|
|
|
e4a049 |
if (tos
|
|
|
e4a049 |
- && (setsockopt(0, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
|
|
|
e4a049 |
+ && (setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
|
|
|
e4a049 |
&& (errno != ENOPROTOOPT) )
|
|
|
e4a049 |
syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
|
|
|
e4a049 |
}
|
|
|
e4a049 |
#endif /* defined(HAS_IPPROTO_IP) && defined(IP_TOS) */
|
|
|
e4a049 |
- net = 0;
|
|
|
e4a049 |
- doit(&from;;
|
|
|
e4a049 |
+ net = s;
|
|
|
e4a049 |
+ doit(&from, fromlen);
|
|
|
e4a049 |
/* NOTREACHED */
|
|
|
e4a049 |
return 0;
|
|
|
e4a049 |
} /* end of main */
|
|
|
e4a049 |
@@ -608,10 +634,9 @@
|
|
|
e4a049 |
* Get a pty, scan input lines.
|
|
|
e4a049 |
*/
|
|
|
e4a049 |
static void
|
|
|
e4a049 |
-doit(struct sockaddr_in *who)
|
|
|
e4a049 |
+doit(struct sockaddr *who, socklen_t wholen)
|
|
|
e4a049 |
{
|
|
|
e4a049 |
const char *host;
|
|
|
e4a049 |
- struct hostent *hp;
|
|
|
e4a049 |
int level;
|
|
|
e4a049 |
char user_name[256];
|
|
|
e4a049 |
|
|
|
e4a049 |
@@ -623,12 +648,18 @@
|
|
|
e4a049 |
fatal(net, "All network ports in use");
|
|
|
e4a049 |
|
|
|
e4a049 |
/* get name of connected client */
|
|
|
e4a049 |
- hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr),
|
|
|
e4a049 |
- who->sin_family);
|
|
|
e4a049 |
- if (hp)
|
|
|
e4a049 |
- host = hp->h_name;
|
|
|
e4a049 |
- else
|
|
|
e4a049 |
- host = inet_ntoa(who->sin_addr);
|
|
|
e4a049 |
+ int error = -1;
|
|
|
e4a049 |
+ char namebuf[255];
|
|
|
e4a049 |
+
|
|
|
e4a049 |
+ error = getnameinfo(who, wholen, namebuf, sizeof(namebuf), NULL, 0, 0);
|
|
|
e4a049 |
+
|
|
|
e4a049 |
+ if (error) {
|
|
|
e4a049 |
+ perror("getnameinfo: localhost");
|
|
|
e4a049 |
+ perror(gai_strerror(error));
|
|
|
e4a049 |
+ exit(1);
|
|
|
e4a049 |
+ }
|
|
|
e4a049 |
+
|
|
|
e4a049 |
+ host = namebuf;
|
|
|
e4a049 |
|
|
|
e4a049 |
/*
|
|
|
e4a049 |
* We must make a copy because Kerberos is probably going
|
|
|
e4a049 |
@@ -649,13 +680,21 @@
|
|
|
e4a049 |
|
|
|
e4a049 |
/* Get local host name */
|
|
|
e4a049 |
{
|
|
|
e4a049 |
- struct hostent *h;
|
|
|
e4a049 |
+ struct addrinfo hints;
|
|
|
e4a049 |
+ struct addrinfo *res;
|
|
|
e4a049 |
+ int e;
|
|
|
e4a049 |
+
|
|
|
e4a049 |
+ memset(&hints, '\0', sizeof(hints));
|
|
|
e4a049 |
+ hints.ai_socktype = SOCK_STREAM;
|
|
|
e4a049 |
+ hints.ai_flags = AI_ADDRCONFIG;
|
|
|
e4a049 |
+
|
|
|
e4a049 |
gethostname(host_name, sizeof(host_name));
|
|
|
e4a049 |
- h = gethostbyname(host_name);
|
|
|
e4a049 |
- if (h) {
|
|
|
e4a049 |
- strncpy(host_name, h->h_name, sizeof(host_name));
|
|
|
e4a049 |
- host_name[sizeof(host_name)-1] = 0;
|
|
|
e4a049 |
+ if ((e = getaddrinfo(host_name, NULL, &hints, &res)) != 0) {
|
|
|
e4a049 |
+ perror("getaddrinfo: localhost");
|
|
|
e4a049 |
+ perror(gai_strerror(e));
|
|
|
e4a049 |
+ exit(1);
|
|
|
e4a049 |
}
|
|
|
e4a049 |
+ freeaddrinfo(res);
|
|
|
e4a049 |
}
|
|
|
e4a049 |
|
|
|
e4a049 |
#if defined(AUTHENTICATE) || defined(ENCRYPT)
|