xref: /freebsd/crypto/openssh/ssh-keyscan.c (revision 42c159fe388a3765f69860c84183700af37aca8a)
1 /*
2  * Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
3  *
4  * Modification and redistribution in source and binary forms is
5  * permitted provided that due credit is given to the author and the
6  * OpenBSD project by leaving this copyright notice intact.
7  */
8 
9 #include "includes.h"
10 RCSID("$OpenBSD: ssh-keyscan.c,v 1.35 2002/03/04 18:30:23 stevesk Exp $");
11 
12 #include <sys/queue.h>
13 #include <errno.h>
14 
15 #include <openssl/bn.h>
16 
17 #include <setjmp.h>
18 #include "xmalloc.h"
19 #include "ssh.h"
20 #include "ssh1.h"
21 #include "key.h"
22 #include "kex.h"
23 #include "compat.h"
24 #include "myproposal.h"
25 #include "packet.h"
26 #include "dispatch.h"
27 #include "buffer.h"
28 #include "bufaux.h"
29 #include "log.h"
30 #include "atomicio.h"
31 #include "misc.h"
32 
33 /* Flag indicating whether IPv4 or IPv6.  This can be set on the command line.
34    Default value is AF_UNSPEC means both IPv4 and IPv6. */
35 int IPv4or6 = AF_UNSPEC;
36 
37 int ssh_port = SSH_DEFAULT_PORT;
38 
39 #define KT_RSA1	1
40 #define KT_DSA	2
41 #define KT_RSA	4
42 
43 int get_keytypes = KT_RSA1;	/* Get only RSA1 keys by default */
44 
45 #define MAXMAXFD 256
46 
47 /* The number of seconds after which to give up on a TCP connection */
48 int timeout = 5;
49 
50 int maxfd;
51 #define MAXCON (maxfd - 10)
52 
53 extern char *__progname;
54 fd_set *read_wait;
55 size_t read_wait_size;
56 int ncon;
57 int nonfatal_fatal = 0;
58 jmp_buf kexjmp;
59 Key *kexjmp_key;
60 
61 /*
62  * Keep a connection structure for each file descriptor.  The state
63  * associated with file descriptor n is held in fdcon[n].
64  */
65 typedef struct Connection {
66 	u_char c_status;	/* State of connection on this file desc. */
67 #define CS_UNUSED 0		/* File descriptor unused */
68 #define CS_CON 1		/* Waiting to connect/read greeting */
69 #define CS_SIZE 2		/* Waiting to read initial packet size */
70 #define CS_KEYS 3		/* Waiting to read public key packet */
71 	int c_fd;		/* Quick lookup: c->c_fd == c - fdcon */
72 	int c_plen;		/* Packet length field for ssh packet */
73 	int c_len;		/* Total bytes which must be read. */
74 	int c_off;		/* Length of data read so far. */
75 	int c_keytype;		/* Only one of KT_RSA1, KT_DSA, or KT_RSA */
76 	char *c_namebase;	/* Address to free for c_name and c_namelist */
77 	char *c_name;		/* Hostname of connection for errors */
78 	char *c_namelist;	/* Pointer to other possible addresses */
79 	char *c_output_name;	/* Hostname of connection for output */
80 	char *c_data;		/* Data read from this fd */
81 	Kex *c_kex;		/* The key-exchange struct for ssh2 */
82 	struct timeval c_tv;	/* Time at which connection gets aborted */
83 	TAILQ_ENTRY(Connection) c_link;	/* List of connections in timeout order. */
84 } con;
85 
86 TAILQ_HEAD(conlist, Connection) tq;	/* Timeout Queue */
87 con *fdcon;
88 
89 /*
90  *  This is just a wrapper around fgets() to make it usable.
91  */
92 
93 /* Stress-test.  Increase this later. */
94 #define LINEBUF_SIZE 16
95 
96 typedef struct {
97 	char *buf;
98 	u_int size;
99 	int lineno;
100 	const char *filename;
101 	FILE *stream;
102 	void (*errfun) (const char *,...);
103 } Linebuf;
104 
105 static Linebuf *
106 Linebuf_alloc(const char *filename, void (*errfun) (const char *,...))
107 {
108 	Linebuf *lb;
109 
110 	if (!(lb = malloc(sizeof(*lb)))) {
111 		if (errfun)
112 			(*errfun) ("linebuf (%s): malloc failed\n", lb->filename);
113 		return (NULL);
114 	}
115 	if (filename) {
116 		lb->filename = filename;
117 		if (!(lb->stream = fopen(filename, "r"))) {
118 			xfree(lb);
119 			if (errfun)
120 				(*errfun) ("%s: %s\n", filename, strerror(errno));
121 			return (NULL);
122 		}
123 	} else {
124 		lb->filename = "(stdin)";
125 		lb->stream = stdin;
126 	}
127 
128 	if (!(lb->buf = malloc(lb->size = LINEBUF_SIZE))) {
129 		if (errfun)
130 			(*errfun) ("linebuf (%s): malloc failed\n", lb->filename);
131 		xfree(lb);
132 		return (NULL);
133 	}
134 	lb->errfun = errfun;
135 	lb->lineno = 0;
136 	return (lb);
137 }
138 
139 static void
140 Linebuf_free(Linebuf * lb)
141 {
142 	fclose(lb->stream);
143 	xfree(lb->buf);
144 	xfree(lb);
145 }
146 
147 #if 0
148 static void
149 Linebuf_restart(Linebuf * lb)
150 {
151 	clearerr(lb->stream);
152 	rewind(lb->stream);
153 	lb->lineno = 0;
154 }
155 
156 static int
157 Linebuf_lineno(Linebuf * lb)
158 {
159 	return (lb->lineno);
160 }
161 #endif
162 
163 static char *
164 Linebuf_getline(Linebuf * lb)
165 {
166 	int n = 0;
167 
168 	lb->lineno++;
169 	for (;;) {
170 		/* Read a line */
171 		if (!fgets(&lb->buf[n], lb->size - n, lb->stream)) {
172 			if (ferror(lb->stream) && lb->errfun)
173 				(*lb->errfun) ("%s: %s\n", lb->filename,
174 				    strerror(errno));
175 			return (NULL);
176 		}
177 		n = strlen(lb->buf);
178 
179 		/* Return it or an error if it fits */
180 		if (n > 0 && lb->buf[n - 1] == '\n') {
181 			lb->buf[n - 1] = '\0';
182 			return (lb->buf);
183 		}
184 		if (n != lb->size - 1) {
185 			if (lb->errfun)
186 				(*lb->errfun) ("%s: skipping incomplete last line\n",
187 				    lb->filename);
188 			return (NULL);
189 		}
190 		/* Double the buffer if we need more space */
191 		if (!(lb->buf = realloc(lb->buf, (lb->size *= 2)))) {
192 			if (lb->errfun)
193 				(*lb->errfun) ("linebuf (%s): realloc failed\n",
194 				    lb->filename);
195 			return (NULL);
196 		}
197 	}
198 }
199 
200 static int
201 fdlim_get(int hard)
202 {
203 	struct rlimit rlfd;
204 
205 	if (getrlimit(RLIMIT_NOFILE, &rlfd) < 0)
206 		return (-1);
207 	if ((hard ? rlfd.rlim_max : rlfd.rlim_cur) == RLIM_INFINITY)
208 		return 10000;
209 	else
210 		return hard ? rlfd.rlim_max : rlfd.rlim_cur;
211 }
212 
213 static int
214 fdlim_set(int lim)
215 {
216 	struct rlimit rlfd;
217 	if (lim <= 0)
218 		return (-1);
219 	if (getrlimit(RLIMIT_NOFILE, &rlfd) < 0)
220 		return (-1);
221 	rlfd.rlim_cur = lim;
222 	if (setrlimit(RLIMIT_NOFILE, &rlfd) < 0)
223 		return (-1);
224 	return (0);
225 }
226 
227 /*
228  * This is an strsep function that returns a null field for adjacent
229  * separators.  This is the same as the 4.4BSD strsep, but different from the
230  * one in the GNU libc.
231  */
232 static char *
233 xstrsep(char **str, const char *delim)
234 {
235 	char *s, *e;
236 
237 	if (!**str)
238 		return (NULL);
239 
240 	s = *str;
241 	e = s + strcspn(s, delim);
242 
243 	if (*e != '\0')
244 		*e++ = '\0';
245 	*str = e;
246 
247 	return (s);
248 }
249 
250 /*
251  * Get the next non-null token (like GNU strsep).  Strsep() will return a
252  * null token for two adjacent separators, so we may have to loop.
253  */
254 static char *
255 strnnsep(char **stringp, char *delim)
256 {
257 	char *tok;
258 
259 	do {
260 		tok = xstrsep(stringp, delim);
261 	} while (tok && *tok == '\0');
262 	return (tok);
263 }
264 
265 static Key *
266 keygrab_ssh1(con *c)
267 {
268 	static Key *rsa;
269 	static Buffer msg;
270 
271 	if (rsa == NULL) {
272 		buffer_init(&msg);
273 		rsa = key_new(KEY_RSA1);
274 	}
275 	buffer_append(&msg, c->c_data, c->c_plen);
276 	buffer_consume(&msg, 8 - (c->c_plen & 7));	/* padding */
277 	if (buffer_get_char(&msg) != (int) SSH_SMSG_PUBLIC_KEY) {
278 		error("%s: invalid packet type", c->c_name);
279 		buffer_clear(&msg);
280 		return NULL;
281 	}
282 	buffer_consume(&msg, 8);		/* cookie */
283 
284 	/* server key */
285 	(void) buffer_get_int(&msg);
286 	buffer_get_bignum(&msg, rsa->rsa->e);
287 	buffer_get_bignum(&msg, rsa->rsa->n);
288 
289 	/* host key */
290 	(void) buffer_get_int(&msg);
291 	buffer_get_bignum(&msg, rsa->rsa->e);
292 	buffer_get_bignum(&msg, rsa->rsa->n);
293 
294 	buffer_clear(&msg);
295 
296 	return (rsa);
297 }
298 
299 static int
300 hostjump(Key *hostkey)
301 {
302 	kexjmp_key = hostkey;
303 	longjmp(kexjmp, 1);
304 }
305 
306 static int
307 ssh2_capable(int remote_major, int remote_minor)
308 {
309 	switch (remote_major) {
310 	case 1:
311 		if (remote_minor == 99)
312 			return 1;
313 		break;
314 	case 2:
315 		return 1;
316 	default:
317 		break;
318 	}
319 	return 0;
320 }
321 
322 static Key *
323 keygrab_ssh2(con *c)
324 {
325 	int j;
326 
327 	packet_set_connection(c->c_fd, c->c_fd);
328 	enable_compat20();
329 	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = c->c_keytype == KT_DSA?
330 	    "ssh-dss": "ssh-rsa";
331 	c->c_kex = kex_setup(myproposal);
332 	c->c_kex->verify_host_key = hostjump;
333 
334 	if (!(j = setjmp(kexjmp))) {
335 		nonfatal_fatal = 1;
336 		dispatch_run(DISPATCH_BLOCK, &c->c_kex->done, c->c_kex);
337 		fprintf(stderr, "Impossible! dispatch_run() returned!\n");
338 		exit(1);
339 	}
340 	nonfatal_fatal = 0;
341 	xfree(c->c_kex);
342 	c->c_kex = NULL;
343 	packet_close();
344 
345 	return j < 0? NULL : kexjmp_key;
346 }
347 
348 static void
349 keyprint(con *c, Key *key)
350 {
351 	if (!key)
352 		return;
353 
354 	fprintf(stdout, "%s ", c->c_output_name ? c->c_output_name : c->c_name);
355 	key_write(key, stdout);
356 	fputs("\n", stdout);
357 }
358 
359 static int
360 tcpconnect(char *host)
361 {
362 	struct addrinfo hints, *ai, *aitop;
363 	char strport[NI_MAXSERV];
364 	int gaierr, s = -1;
365 
366 	snprintf(strport, sizeof strport, "%d", ssh_port);
367 	memset(&hints, 0, sizeof(hints));
368 	hints.ai_family = IPv4or6;
369 	hints.ai_socktype = SOCK_STREAM;
370 	if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0)
371 		fatal("getaddrinfo %s: %s", host, gai_strerror(gaierr));
372 	for (ai = aitop; ai; ai = ai->ai_next) {
373 		s = socket(ai->ai_family, SOCK_STREAM, 0);
374 		if (s < 0) {
375 			error("socket: %s", strerror(errno));
376 			continue;
377 		}
378 		if (fcntl(s, F_SETFL, O_NONBLOCK) < 0)
379 			fatal("F_SETFL: %s", strerror(errno));
380 		if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0 &&
381 		    errno != EINPROGRESS)
382 			error("connect (`%s'): %s", host, strerror(errno));
383 		else
384 			break;
385 		close(s);
386 		s = -1;
387 	}
388 	freeaddrinfo(aitop);
389 	return s;
390 }
391 
392 static int
393 conalloc(char *iname, char *oname, int keytype)
394 {
395 	int s;
396 	char *namebase, *name, *namelist;
397 
398 	namebase = namelist = xstrdup(iname);
399 
400 	do {
401 		name = xstrsep(&namelist, ",");
402 		if (!name) {
403 			xfree(namebase);
404 			return (-1);
405 		}
406 	} while ((s = tcpconnect(name)) < 0);
407 
408 	if (s >= maxfd)
409 		fatal("conalloc: fdno %d too high", s);
410 	if (fdcon[s].c_status)
411 		fatal("conalloc: attempt to reuse fdno %d", s);
412 
413 	fdcon[s].c_fd = s;
414 	fdcon[s].c_status = CS_CON;
415 	fdcon[s].c_namebase = namebase;
416 	fdcon[s].c_name = name;
417 	fdcon[s].c_namelist = namelist;
418 	fdcon[s].c_output_name = xstrdup(oname);
419 	fdcon[s].c_data = (char *) &fdcon[s].c_plen;
420 	fdcon[s].c_len = 4;
421 	fdcon[s].c_off = 0;
422 	fdcon[s].c_keytype = keytype;
423 	gettimeofday(&fdcon[s].c_tv, NULL);
424 	fdcon[s].c_tv.tv_sec += timeout;
425 	TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link);
426 	FD_SET(s, read_wait);
427 	ncon++;
428 	return (s);
429 }
430 
431 static void
432 confree(int s)
433 {
434 	if (s >= maxfd || fdcon[s].c_status == CS_UNUSED)
435 		fatal("confree: attempt to free bad fdno %d", s);
436 	close(s);
437 	xfree(fdcon[s].c_namebase);
438 	xfree(fdcon[s].c_output_name);
439 	if (fdcon[s].c_status == CS_KEYS)
440 		xfree(fdcon[s].c_data);
441 	fdcon[s].c_status = CS_UNUSED;
442 	fdcon[s].c_keytype = 0;
443 	TAILQ_REMOVE(&tq, &fdcon[s], c_link);
444 	FD_CLR(s, read_wait);
445 	ncon--;
446 }
447 
448 static void
449 contouch(int s)
450 {
451 	TAILQ_REMOVE(&tq, &fdcon[s], c_link);
452 	gettimeofday(&fdcon[s].c_tv, NULL);
453 	fdcon[s].c_tv.tv_sec += timeout;
454 	TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link);
455 }
456 
457 static int
458 conrecycle(int s)
459 {
460 	int ret;
461 	con *c = &fdcon[s];
462 
463 	ret = conalloc(c->c_namelist, c->c_output_name, c->c_keytype);
464 	confree(s);
465 	return (ret);
466 }
467 
468 static void
469 congreet(int s)
470 {
471 	char buf[256], *cp;
472 	char remote_version[sizeof buf];
473 	size_t bufsiz;
474 	int remote_major, remote_minor, n = 0;
475 	con *c = &fdcon[s];
476 
477 	bufsiz = sizeof(buf);
478 	cp = buf;
479 	while (bufsiz-- && (n = read(s, cp, 1)) == 1 && *cp != '\n') {
480 		if (*cp == '\r')
481 			*cp = '\n';
482 		cp++;
483 	}
484 	if (n < 0) {
485 		if (errno != ECONNREFUSED)
486 			error("read (%s): %s", c->c_name, strerror(errno));
487 		conrecycle(s);
488 		return;
489 	}
490 	if (n == 0) {
491 		error("%s: Connection closed by remote host", c->c_name);
492 		conrecycle(s);
493 		return;
494 	}
495 	if (*cp != '\n' && *cp != '\r') {
496 		error("%s: bad greeting", c->c_name);
497 		confree(s);
498 		return;
499 	}
500 	*cp = '\0';
501 	if (sscanf(buf, "SSH-%d.%d-%[^\n]\n",
502 	    &remote_major, &remote_minor, remote_version) == 3)
503 		compat_datafellows(remote_version);
504 	else
505 		datafellows = 0;
506 	if (c->c_keytype != KT_RSA1) {
507 		if (!ssh2_capable(remote_major, remote_minor)) {
508 			debug("%s doesn't support ssh2", c->c_name);
509 			confree(s);
510 			return;
511 		}
512 	} else if (remote_major != 1) {
513 		debug("%s doesn't support ssh1", c->c_name);
514 		confree(s);
515 		return;
516 	}
517 	fprintf(stderr, "# %s %s\n", c->c_name, chop(buf));
518 	n = snprintf(buf, sizeof buf, "SSH-%d.%d-OpenSSH-keyscan\r\n",
519 	    c->c_keytype == KT_RSA1? PROTOCOL_MAJOR_1 : PROTOCOL_MAJOR_2,
520 	    c->c_keytype == KT_RSA1? PROTOCOL_MINOR_1 : PROTOCOL_MINOR_2);
521 	if (atomicio(write, s, buf, n) != n) {
522 		error("write (%s): %s", c->c_name, strerror(errno));
523 		confree(s);
524 		return;
525 	}
526 	if (c->c_keytype != KT_RSA1) {
527 		keyprint(c, keygrab_ssh2(c));
528 		confree(s);
529 		return;
530 	}
531 	c->c_status = CS_SIZE;
532 	contouch(s);
533 }
534 
535 static void
536 conread(int s)
537 {
538 	int n;
539 	con *c = &fdcon[s];
540 
541 	if (c->c_status == CS_CON) {
542 		congreet(s);
543 		return;
544 	}
545 	n = read(s, c->c_data + c->c_off, c->c_len - c->c_off);
546 	if (n < 0) {
547 		error("read (%s): %s", c->c_name, strerror(errno));
548 		confree(s);
549 		return;
550 	}
551 	c->c_off += n;
552 
553 	if (c->c_off == c->c_len)
554 		switch (c->c_status) {
555 		case CS_SIZE:
556 			c->c_plen = htonl(c->c_plen);
557 			c->c_len = c->c_plen + 8 - (c->c_plen & 7);
558 			c->c_off = 0;
559 			c->c_data = xmalloc(c->c_len);
560 			c->c_status = CS_KEYS;
561 			break;
562 		case CS_KEYS:
563 			keyprint(c, keygrab_ssh1(c));
564 			confree(s);
565 			return;
566 			break;
567 		default:
568 			fatal("conread: invalid status %d", c->c_status);
569 			break;
570 		}
571 
572 	contouch(s);
573 }
574 
575 static void
576 conloop(void)
577 {
578 	fd_set *r, *e;
579 	struct timeval seltime, now;
580 	int i;
581 	con *c;
582 
583 	gettimeofday(&now, NULL);
584 	c = tq.tqh_first;
585 
586 	if (c && (c->c_tv.tv_sec > now.tv_sec ||
587 	    (c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec > now.tv_usec))) {
588 		seltime = c->c_tv;
589 		seltime.tv_sec -= now.tv_sec;
590 		seltime.tv_usec -= now.tv_usec;
591 		if (seltime.tv_usec < 0) {
592 			seltime.tv_usec += 1000000;
593 			seltime.tv_sec--;
594 		}
595 	} else
596 		seltime.tv_sec = seltime.tv_usec = 0;
597 
598 	r = xmalloc(read_wait_size);
599 	memcpy(r, read_wait, read_wait_size);
600 	e = xmalloc(read_wait_size);
601 	memcpy(e, read_wait, read_wait_size);
602 
603 	while (select(maxfd, r, NULL, e, &seltime) == -1 &&
604 	    (errno == EAGAIN || errno == EINTR))
605 		;
606 
607 	for (i = 0; i < maxfd; i++) {
608 		if (FD_ISSET(i, e)) {
609 			error("%s: exception!", fdcon[i].c_name);
610 			confree(i);
611 		} else if (FD_ISSET(i, r))
612 			conread(i);
613 	}
614 	xfree(r);
615 	xfree(e);
616 
617 	c = tq.tqh_first;
618 	while (c && (c->c_tv.tv_sec < now.tv_sec ||
619 	    (c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec < now.tv_usec))) {
620 		int s = c->c_fd;
621 
622 		c = c->c_link.tqe_next;
623 		conrecycle(s);
624 	}
625 }
626 
627 static void
628 do_host(char *host)
629 {
630 	char *name = strnnsep(&host, " \t\n");
631 	int j;
632 
633 	if (name == NULL)
634 		return;
635 	for (j = KT_RSA1; j <= KT_RSA; j *= 2) {
636 		if (get_keytypes & j) {
637 			while (ncon >= MAXCON)
638 				conloop();
639 			conalloc(name, *host ? host : name, j);
640 		}
641 	}
642 }
643 
644 void
645 fatal(const char *fmt,...)
646 {
647 	va_list args;
648 	va_start(args, fmt);
649 	do_log(SYSLOG_LEVEL_FATAL, fmt, args);
650 	va_end(args);
651 	if (nonfatal_fatal)
652 		longjmp(kexjmp, -1);
653 	else
654 		fatal_cleanup();
655 }
656 
657 static void
658 usage(void)
659 {
660 	fprintf(stderr, "Usage: %s [options] host ...\n",
661 	    __progname);
662 	fprintf(stderr, "Options:\n");
663 	fprintf(stderr, "  -f file     Read hosts or addresses from file.\n");
664 	fprintf(stderr, "  -p port     Connect to the specified port.\n");
665 	fprintf(stderr, "  -t keytype  Specify the host key type.\n");
666 	fprintf(stderr, "  -T timeout  Set connection timeout.\n");
667 	fprintf(stderr, "  -v          Verbose; display verbose debugging messages.\n");
668 	fprintf(stderr, "  -4          Use IPv4 only.\n");
669 	fprintf(stderr, "  -6          Use IPv6 only.\n");
670 	exit(1);
671 }
672 
673 int
674 main(int argc, char **argv)
675 {
676 	int debug_flag = 0, log_level = SYSLOG_LEVEL_INFO;
677 	int opt, fopt_count = 0;
678 	char *tname;
679 
680 	extern int optind;
681 	extern char *optarg;
682 
683 	TAILQ_INIT(&tq);
684 
685 	if (argc <= 1)
686 		usage();
687 
688 	while ((opt = getopt(argc, argv, "v46p:T:t:f:")) != -1) {
689 		switch (opt) {
690 		case 'p':
691 			ssh_port = a2port(optarg);
692 			if (ssh_port == 0) {
693 				fprintf(stderr, "Bad port '%s'\n", optarg);
694 				exit(1);
695 			}
696 			break;
697 		case 'T':
698 			timeout = atoi(optarg);
699 			if (timeout <= 0)
700 				usage();
701 			break;
702 		case 'v':
703 			if (!debug_flag) {
704 				debug_flag = 1;
705 				log_level = SYSLOG_LEVEL_DEBUG1;
706 			}
707 			else if (log_level < SYSLOG_LEVEL_DEBUG3)
708 				log_level++;
709 			else
710 				fatal("Too high debugging level.");
711 			break;
712 		case 'f':
713 			if (strcmp(optarg, "-") == 0)
714 				optarg = NULL;
715 			argv[fopt_count++] = optarg;
716 			break;
717 		case 't':
718 			get_keytypes = 0;
719 			tname = strtok(optarg, ",");
720 			while (tname) {
721 				int type = key_type_from_name(tname);
722 				switch (type) {
723 				case KEY_RSA1:
724 					get_keytypes |= KT_RSA1;
725 					break;
726 				case KEY_DSA:
727 					get_keytypes |= KT_DSA;
728 					break;
729 				case KEY_RSA:
730 					get_keytypes |= KT_RSA;
731 					break;
732 				case KEY_UNSPEC:
733 					fatal("unknown key type %s", tname);
734 				}
735 				tname = strtok(NULL, ",");
736 			}
737 			break;
738 		case '4':
739 			IPv4or6 = AF_INET;
740 			break;
741 		case '6':
742 			IPv4or6 = AF_INET6;
743 			break;
744 		case '?':
745 		default:
746 			usage();
747 		}
748 	}
749 	if (optind == argc && !fopt_count)
750 		usage();
751 
752 	log_init("ssh-keyscan", log_level, SYSLOG_FACILITY_USER, 1);
753 
754 	maxfd = fdlim_get(1);
755 	if (maxfd < 0)
756 		fatal("%s: fdlim_get: bad value", __progname);
757 	if (maxfd > MAXMAXFD)
758 		maxfd = MAXMAXFD;
759 	if (MAXCON <= 0)
760 		fatal("%s: not enough file descriptors", __progname);
761 	if (maxfd > fdlim_get(0))
762 		fdlim_set(maxfd);
763 	fdcon = xmalloc(maxfd * sizeof(con));
764 	memset(fdcon, 0, maxfd * sizeof(con));
765 
766 	read_wait_size = howmany(maxfd, NFDBITS) * sizeof(fd_mask);
767 	read_wait = xmalloc(read_wait_size);
768 	memset(read_wait, 0, read_wait_size);
769 
770 	if (fopt_count) {
771 		Linebuf *lb;
772 		char *line;
773 		int j;
774 
775 		for (j = 0; j < fopt_count; j++) {
776 			lb = Linebuf_alloc(argv[j], error);
777 			if (!lb)
778 				continue;
779 			while ((line = Linebuf_getline(lb)) != NULL)
780 				do_host(line);
781 			Linebuf_free(lb);
782 		}
783 	}
784 
785 	while (optind < argc)
786 		do_host(argv[optind++]);
787 
788 	while (ncon > 0)
789 		conloop();
790 
791 	return (0);
792 }
793