]>
Commit | Line | Data |
---|---|---|
b52f6eb2 DW |
1 | diff -uNr netkit-telnet-0.17/telnetd/telnetd.c netkit-telnet-0.17.ipv6/telnetd/telnetd.c\r |
2 | --- netkit-telnet-0.17/telnetd/telnetd.c 2006-07-13 08:37:18.000000000 +0200\r | |
3 | +++ netkit-telnet-0.17.ipv6/telnetd/telnetd.c 2006-07-14 08:36:11.000000000 +0200\r | |
4 | @@ -49,6 +49,7 @@\r | |
5 | /* #include <netinet/ip.h> */ /* Don't think this is used at all here */\r | |
6 | #include <arpa/inet.h>\r | |
7 | #include <assert.h>\r | |
8 | +#include <sys/poll.h>\r | |
9 | #include "telnetd.h"\r | |
10 | #include "pathnames.h"\r | |
11 | #include "setproctitle.h"\r | |
12 | @@ -68,7 +69,7 @@\r | |
13 | #define HAS_IPPROTO_IP\r | |
14 | #endif\r | |
15 | \r | |
16 | -static void doit(struct sockaddr_in *who);\r | |
17 | +static void doit(struct sockaddr *who, socklen_t wholen);\r | |
18 | static int terminaltypeok(const char *s);\r | |
19 | \r | |
20 | /*\r | |
21 | @@ -90,7 +91,7 @@\r | |
22 | int\r | |
23 | main(int argc, char *argv[], char *env[])\r | |
24 | {\r | |
25 | - struct sockaddr_in from;\r | |
26 | + struct sockaddr from;\r | |
27 | int on = 1;\r | |
28 | socklen_t fromlen;\r | |
29 | register int ch;\r | |
30 | @@ -248,64 +249,89 @@\r | |
31 | argc -= optind;\r | |
32 | argv += optind;\r | |
33 | \r | |
34 | - if (debug) {\r | |
35 | - int s, ns;\r | |
36 | - socklen_t foo;\r | |
37 | - struct servent *sp;\r | |
38 | - struct sockaddr_in sn;\r | |
39 | + int s = 0;\r | |
40 | \r | |
41 | - memset(&sn, 0, sizeof(sn));\r | |
42 | - sn.sin_family = AF_INET;\r | |
43 | + if (debug) {\r | |
44 | + struct addrinfo *ai;\r | |
45 | + unsigned int nfds = 0;\r | |
46 | + struct pollfd fds[2];\r | |
47 | \r | |
48 | if (argc > 1) {\r | |
49 | - usage();\r | |
50 | - /* NOTREACHED */\r | |
51 | - } else if (argc == 1) {\r | |
52 | - if ((sp = getservbyname(*argv, "tcp"))!=NULL) {\r | |
53 | - sn.sin_port = sp->s_port;\r | |
54 | - } \r | |
55 | - else {\r | |
56 | - int pt = atoi(*argv);\r | |
57 | - if (pt <= 0) {\r | |
58 | - fprintf(stderr, "telnetd: %s: bad port number\n",\r | |
59 | - *argv);\r | |
60 | - usage();\r | |
61 | - /* NOTREACHED */\r | |
62 | - }\r | |
63 | - sn.sin_port = htons(pt);\r | |
64 | - }\r | |
65 | + usage();\r | |
66 | + /* NOTREACHED */\r | |
67 | } else {\r | |
68 | - sp = getservbyname("telnet", "tcp");\r | |
69 | - if (sp == 0) {\r | |
70 | - fprintf(stderr, "telnetd: tcp/telnet: unknown service\n");\r | |
71 | - exit(1);\r | |
72 | - }\r | |
73 | - sn.sin_port = sp->s_port;\r | |
74 | - }\r | |
75 | + struct addrinfo hints;\r | |
76 | +\r | |
77 | + memset (&hints, '\0', sizeof (hints));\r | |
78 | + hints.ai_socktype = SOCK_STREAM;\r | |
79 | + hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;\r | |
80 | + hints.ai_protocol = IPPROTO_TCP;\r | |
81 | +\r | |
82 | + if (argc == 0) {\r | |
83 | + if (getaddrinfo(NULL, "telnet", &hints, &ai) != 0) {\r | |
84 | + fprintf(stderr, "telnetd: %s: bad port number\n", *argv);\r | |
85 | + usage();\r | |
86 | + /* NOTREACHED */\r | |
87 | + }\r | |
88 | + } else {\r | |
89 | + if (getaddrinfo(NULL, *argv, &hints, &ai) != 0) {\r | |
90 | + fprintf(stderr, "telnetd: %s: bad port number\n", *argv);\r | |
91 | + usage();\r | |
92 | + /* NOTREACHED */\r | |
93 | + }\r | |
94 | + }\r | |
95 | + } \r | |
96 | \r | |
97 | - s = socket(AF_INET, SOCK_STREAM, 0);\r | |
98 | - if (s < 0) {\r | |
99 | + struct addrinfo *runp;\r | |
100 | + int b = 0;\r | |
101 | + for (runp = ai; ((runp != NULL) && (nfds < sizeof (fds) / sizeof (fds[0]))); runp = runp->ai_next) {\r | |
102 | + fds[nfds].fd = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);\r | |
103 | + if (fds[nfds].fd < 0) {\r | |
104 | perror("telnetd: socket");;\r | |
105 | - exit(1);\r | |
106 | + exit(1);\r | |
107 | + }\r | |
108 | + fds[nfds].events = POLLIN;\r | |
109 | + (void) setsockopt(fds[nfds].fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));\r | |
110 | +\r | |
111 | + if (bind(fds[nfds].fd, runp->ai_addr, runp->ai_addrlen) != 0) {\r | |
112 | + // Unable to bind to given port. One of the reason can be\r | |
113 | + // that we can't bind to both IPv4 and IPv6\r | |
114 | + break;\r | |
115 | + } else { \r | |
116 | + b++;\r | |
117 | + }\r | |
118 | +\r | |
119 | + if (listen(fds[nfds].fd, 1) < 0) {\r | |
120 | + perror("listen");\r | |
121 | + exit(1);\r | |
122 | + }\r | |
123 | + nfds++;\r | |
124 | }\r | |
125 | - (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));\r | |
126 | - if (bind(s, (struct sockaddr *)&sn, sizeof(sn)) < 0) {\r | |
127 | - perror("bind");\r | |
128 | - exit(1);\r | |
129 | - }\r | |
130 | - if (listen(s, 1) < 0) {\r | |
131 | - perror("listen");\r | |
132 | - exit(1);\r | |
133 | + freeaddrinfo(ai);\r | |
134 | +\r | |
135 | + if (b == 0) {\r | |
136 | + perror("bind");\r | |
137 | + exit(1);\r | |
138 | }\r | |
139 | - foo = sizeof(sn);\r | |
140 | - ns = accept(s, (struct sockaddr *)&sn, &foo);\r | |
141 | - if (ns < 0) {\r | |
142 | - perror("accept");\r | |
143 | - exit(1);\r | |
144 | +\r | |
145 | + int n = poll (fds, nfds, -1);\r | |
146 | + if (n > 0) {\r | |
147 | + unsigned int i;\r | |
148 | + for (i = 0; i < nfds; i++) {\r | |
149 | + if (fds[i].revents & POLLIN) {\r | |
150 | + struct sockaddr_storage rem;\r | |
151 | + socklen_t remlen = sizeof(rem);\r | |
152 | + int fd = accept(fds[i].fd, (struct sockaddr *) &rem, &remlen);\r | |
153 | +\r | |
154 | + if (fd < 0) {\r | |
155 | + perror("accept");\r | |
156 | + exit(1);\r | |
157 | + }\r | |
158 | +\r | |
159 | + s = fd;\r | |
160 | + }\r | |
161 | + }\r | |
162 | }\r | |
163 | - (void) dup2(ns, 0);\r | |
164 | - (void) close(ns);\r | |
165 | - (void) close(s);\r | |
166 | } else if (argc > 0) {\r | |
167 | usage();\r | |
168 | /* NOT REACHED */\r | |
169 | @@ -313,13 +339,13 @@\r | |
170 | \r | |
171 | openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);\r | |
172 | fromlen = sizeof (from);\r | |
173 | - if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {\r | |
174 | + if (getpeername(s, &from, &fromlen) < 0) {\r | |
175 | fprintf(stderr, "%s: ", progname);\r | |
176 | perror("getpeername");\r | |
177 | _exit(1);\r | |
178 | }\r | |
179 | if (keepalive &&\r | |
180 | - setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {\r | |
181 | + setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {\r | |
182 | syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");\r | |
183 | }\r | |
184 | \r | |
185 | @@ -333,13 +359,13 @@\r | |
186 | if (tos < 0)\r | |
187 | tos = 020; /* Low Delay bit */\r | |
188 | if (tos\r | |
189 | - && (setsockopt(0, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)\r | |
190 | + && (setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)\r | |
191 | && (errno != ENOPROTOOPT) )\r | |
192 | syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");\r | |
193 | }\r | |
194 | #endif /* defined(HAS_IPPROTO_IP) && defined(IP_TOS) */\r | |
195 | - net = 0;\r | |
196 | - doit(&from);\r | |
197 | + net = s;\r | |
198 | + doit(&from, fromlen);\r | |
199 | /* NOTREACHED */\r | |
200 | return 0;\r | |
201 | } /* end of main */\r | |
202 | @@ -608,10 +634,9 @@\r | |
203 | * Get a pty, scan input lines.\r | |
204 | */\r | |
205 | static void\r | |
206 | -doit(struct sockaddr_in *who)\r | |
207 | +doit(struct sockaddr *who, socklen_t wholen)\r | |
208 | {\r | |
209 | const char *host;\r | |
210 | - struct hostent *hp;\r | |
211 | int level;\r | |
212 | char user_name[256];\r | |
213 | \r | |
214 | @@ -623,12 +648,18 @@\r | |
215 | fatal(net, "All network ports in use");\r | |
216 | \r | |
217 | /* get name of connected client */\r | |
218 | - hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr),\r | |
219 | - who->sin_family);\r | |
220 | - if (hp)\r | |
221 | - host = hp->h_name;\r | |
222 | - else\r | |
223 | - host = inet_ntoa(who->sin_addr);\r | |
224 | + int error = -1;\r | |
225 | + char namebuf[255];\r | |
226 | +\r | |
227 | + error = getnameinfo(who, wholen, namebuf, sizeof(namebuf), NULL, 0, 0);\r | |
228 | + \r | |
229 | + if (error) {\r | |
230 | + perror("getnameinfo: localhost");\r | |
231 | + perror(gai_strerror(error));\r | |
232 | + exit(1); \r | |
233 | + }\r | |
234 | + \r | |
235 | + host = namebuf;\r | |
236 | \r | |
237 | /*\r | |
238 | * We must make a copy because Kerberos is probably going\r | |
239 | @@ -649,13 +680,21 @@\r | |
240 | \r | |
241 | /* Get local host name */\r | |
242 | {\r | |
243 | - struct hostent *h;\r | |
244 | + struct addrinfo hints;\r | |
245 | + struct addrinfo *res;\r | |
246 | + int e;\r | |
247 | +\r | |
248 | + memset(&hints, '\0', sizeof(hints));\r | |
249 | + hints.ai_socktype = SOCK_STREAM;\r | |
250 | + hints.ai_flags = AI_ADDRCONFIG;\r | |
251 | +\r | |
252 | gethostname(host_name, sizeof(host_name));\r | |
253 | - h = gethostbyname(host_name);\r | |
254 | - if (h) {\r | |
255 | - strncpy(host_name, h->h_name, sizeof(host_name));\r | |
256 | - host_name[sizeof(host_name)-1] = 0;\r | |
257 | + if ((e = getaddrinfo(host_name, NULL, &hints, &res)) != 0) {\r | |
258 | + perror("getaddrinfo: localhost");\r | |
259 | + perror(gai_strerror(e));\r | |
260 | + exit(1);\r | |
261 | }\r | |
262 | + freeaddrinfo(res);\r | |
263 | }\r | |
264 | \r | |
265 | #if defined(AUTHENTICATE) || defined(ENCRYPT)\r |