summaryrefslogtreecommitdiff
path: root/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'misc.c')
-rw-r--r--misc.c173
1 files changed, 169 insertions, 4 deletions
diff --git a/misc.c b/misc.c
index 2dd8ae6e3..29e928886 100644
--- a/misc.c
+++ b/misc.c
@@ -24,7 +24,11 @@
24 */ 24 */
25 25
26#include "includes.h" 26#include "includes.h"
27RCSID("$OpenBSD: misc.c,v 1.34 2005/07/08 09:26:18 dtucker Exp $"); 27RCSID("$OpenBSD: misc.c,v 1.42 2006/01/31 10:19:02 djm Exp $");
28
29#ifdef SSH_TUN_OPENBSD
30#include <net/if.h>
31#endif
28 32
29#include "misc.h" 33#include "misc.h"
30#include "log.h" 34#include "log.h"
@@ -194,6 +198,37 @@ a2port(const char *s)
194 return port; 198 return port;
195} 199}
196 200
201int
202a2tun(const char *s, int *remote)
203{
204 const char *errstr = NULL;
205 char *sp, *ep;
206 int tun;
207
208 if (remote != NULL) {
209 *remote = SSH_TUNID_ANY;
210 sp = xstrdup(s);
211 if ((ep = strchr(sp, ':')) == NULL) {
212 xfree(sp);
213 return (a2tun(s, NULL));
214 }
215 ep[0] = '\0'; ep++;
216 *remote = a2tun(ep, NULL);
217 tun = a2tun(sp, NULL);
218 xfree(sp);
219 return (*remote == SSH_TUNID_ERR ? *remote : tun);
220 }
221
222 if (strcasecmp(s, "any") == 0)
223 return (SSH_TUNID_ANY);
224
225 tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr);
226 if (errstr != NULL)
227 return (SSH_TUNID_ERR);
228
229 return (tun);
230}
231
197#define SECONDS 1 232#define SECONDS 1
198#define MINUTES (SECONDS * 60) 233#define MINUTES (SECONDS * 60)
199#define HOURS (MINUTES * 60) 234#define HOURS (MINUTES * 60)
@@ -356,12 +391,15 @@ void
356addargs(arglist *args, char *fmt, ...) 391addargs(arglist *args, char *fmt, ...)
357{ 392{
358 va_list ap; 393 va_list ap;
359 char buf[1024]; 394 char *cp;
360 u_int nalloc; 395 u_int nalloc;
396 int r;
361 397
362 va_start(ap, fmt); 398 va_start(ap, fmt);
363 vsnprintf(buf, sizeof(buf), fmt, ap); 399 r = vasprintf(&cp, fmt, ap);
364 va_end(ap); 400 va_end(ap);
401 if (r == -1)
402 fatal("addargs: argument too long");
365 403
366 nalloc = args->nalloc; 404 nalloc = args->nalloc;
367 if (args->list == NULL) { 405 if (args->list == NULL) {
@@ -372,10 +410,44 @@ addargs(arglist *args, char *fmt, ...)
372 410
373 args->list = xrealloc(args->list, nalloc * sizeof(char *)); 411 args->list = xrealloc(args->list, nalloc * sizeof(char *));
374 args->nalloc = nalloc; 412 args->nalloc = nalloc;
375 args->list[args->num++] = xstrdup(buf); 413 args->list[args->num++] = cp;
376 args->list[args->num] = NULL; 414 args->list[args->num] = NULL;
377} 415}
378 416
417void
418replacearg(arglist *args, u_int which, char *fmt, ...)
419{
420 va_list ap;
421 char *cp;
422 int r;
423
424 va_start(ap, fmt);
425 r = vasprintf(&cp, fmt, ap);
426 va_end(ap);
427 if (r == -1)
428 fatal("replacearg: argument too long");
429
430 if (which >= args->num)
431 fatal("replacearg: tried to replace invalid arg %d >= %d",
432 which, args->num);
433 xfree(args->list[which]);
434 args->list[which] = cp;
435}
436
437void
438freeargs(arglist *args)
439{
440 u_int i;
441
442 if (args->list != NULL) {
443 for (i = 0; i < args->num; i++)
444 xfree(args->list[i]);
445 xfree(args->list);
446 args->nalloc = args->num = 0;
447 args->list = NULL;
448 }
449}
450
379/* 451/*
380 * Expands tildes in the file name. Returns data allocated by xmalloc. 452 * Expands tildes in the file name. Returns data allocated by xmalloc.
381 * Warning: this calls getpw*. 453 * Warning: this calls getpw*.
@@ -507,6 +579,99 @@ read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz,
507 return -1; 579 return -1;
508} 580}
509 581
582int
583tun_open(int tun, int mode)
584{
585#if defined(CUSTOM_SYS_TUN_OPEN)
586 return (sys_tun_open(tun, mode));
587#elif defined(SSH_TUN_OPENBSD)
588 struct ifreq ifr;
589 char name[100];
590 int fd = -1, sock;
591
592 /* Open the tunnel device */
593 if (tun <= SSH_TUNID_MAX) {
594 snprintf(name, sizeof(name), "/dev/tun%d", tun);
595 fd = open(name, O_RDWR);
596 } else if (tun == SSH_TUNID_ANY) {
597 for (tun = 100; tun >= 0; tun--) {
598 snprintf(name, sizeof(name), "/dev/tun%d", tun);
599 if ((fd = open(name, O_RDWR)) >= 0)
600 break;
601 }
602 } else {
603 debug("%s: invalid tunnel %u", __func__, tun);
604 return (-1);
605 }
606
607 if (fd < 0) {
608 debug("%s: %s open failed: %s", __func__, name, strerror(errno));
609 return (-1);
610 }
611
612 debug("%s: %s mode %d fd %d", __func__, name, mode, fd);
613
614 /* Set the tunnel device operation mode */
615 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tun%d", tun);
616 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
617 goto failed;
618
619 if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)
620 goto failed;
621
622 /* Set interface mode */
623 ifr.ifr_flags &= ~IFF_UP;
624 if (mode == SSH_TUNMODE_ETHERNET)
625 ifr.ifr_flags |= IFF_LINK0;
626 else
627 ifr.ifr_flags &= ~IFF_LINK0;
628 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
629 goto failed;
630
631 /* Bring interface up */
632 ifr.ifr_flags |= IFF_UP;
633 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
634 goto failed;
635
636 close(sock);
637 return (fd);
638
639 failed:
640 if (fd >= 0)
641 close(fd);
642 if (sock >= 0)
643 close(sock);
644 debug("%s: failed to set %s mode %d: %s", __func__, name,
645 mode, strerror(errno));
646 return (-1);
647#else
648 error("Tunnel interfaces are not supported on this platform");
649 return (-1);
650#endif
651}
652
653void
654sanitise_stdfd(void)
655{
656 int nullfd, dupfd;
657
658 if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
659 fprintf(stderr, "Couldn't open /dev/null: %s", strerror(errno));
660 exit(1);
661 }
662 while (++dupfd <= 2) {
663 /* Only clobber closed fds */
664 if (fcntl(dupfd, F_GETFL, 0) >= 0)
665 continue;
666 if (dup2(nullfd, dupfd) == -1) {
667 fprintf(stderr, "dup2: %s", strerror(errno));
668 exit(1);
669 }
670 }
671 if (nullfd > 2)
672 close(nullfd);
673}
674
510char * 675char *
511tohex(const u_char *d, u_int l) 676tohex(const u_char *d, u_int l)
512{ 677{