Esempio n. 1
0
int
ttyname_r(int fd, char *buf, size_t len)
{
	struct stat sb;
	struct termios ttyb;
	struct ptmget ptm;

	_DIAGASSERT(fd != -1);

	/* If it is a pty, deal with it quickly */
	if (ioctl(fd, TIOCPTSNAME, &ptm) != -1) {
		if (strlcpy(buf, ptm.sn, len) >= len) {
			return ERANGE;
		}
		return 0;
	}

	/* Must be a terminal. */
	if (tcgetattr(fd, &ttyb) == -1)
		return errno;

	if (fstat(fd, &sb))
		return errno;

	if (strlcpy(buf, _PATH_DEV, len) >= len)
		return ERANGE;
	buf += strlen(_PATH_DEV);
	len -= strlen(_PATH_DEV);
	return devname_r(sb.st_rdev, sb.st_mode & S_IFMT, buf, len);
}
Esempio n. 2
0
char *
devname(dev_t dev, mode_t type)
{
    static char buf[30];	 /* XXX: pick up from <sys/conf.h> */

    strlcpy(buf, devname_r(dev, type, buf, sizeof(buf)), sizeof(buf));

    return (buf);
}
Esempio n. 3
0
void
gf_fuse_unmount(const char *mountpoint, int fd)
{
    int ret;
    struct stat sbuf;
    char dev[128];
    char resolved_path[PATH_MAX];
    char *ep, *rp = NULL;

    unsigned int hs_complete = 0;

    ret = ioctl(fd, FUSEDEVIOCGETHANDSHAKECOMPLETE, &hs_complete);
    if (ret || !hs_complete) {
        return;
    }
    /* XXX does this have any use here? */
    ret = ioctl(fd,  FUSEDEVIOCSETDAEMONDEAD, &fd);
    if (ret) {
        return;
    }

    if (fstat(fd, &sbuf) == -1) {
        return;
    }

    devname_r(sbuf.st_rdev, S_IFCHR, dev, 128);

    if (strncmp(dev, MACFUSE_DEVICE_BASENAME,
                sizeof(MACFUSE_DEVICE_BASENAME) - 1)) {
        return;
    }

    strtol(dev + 4, &ep, 10);
    if (*ep != '\0') {
        return;
    }

    rp = realpath(mountpoint, resolved_path);
    if (rp) {
        ret = unmount(resolved_path, 0);
    }

    close(fd);

    return;
}
Esempio n. 4
0
int
ttyname_r(int fd, char *buf, size_t len)
{
	struct stat	sb;
	struct fiodname_args fa;
	size_t used;

	*buf = '\0';

	/* Must be a valid file descriptor */
	if (_fstat(fd, &sb))
		return (EBADF);
	/* Must be a character device */
	if (!S_ISCHR(sb.st_mode))
		return (ENOTTY);
	/* Must be a terminal. */
	if (!isatty(fd))
		return (ENOTTY);
	/* Must have enough room */
	if (len <= sizeof(_PATH_DEV))
		return (ERANGE);

	strcpy(buf, _PATH_DEV);
	used = strlen(buf);
	fa.len = len - used;
	fa.name = buf + used;
	if (_ioctl(fd, FIODNAME, &fa) == -1) {
#ifdef TTYNAME_DEVFS_COMPAT
		/* If compat mode is set, fall back to old method */
		devname_r(sb.st_rdev, S_IFCHR, buf + used, len - used);
#else
		return ERANGE;
#endif
	}
	return (0);
}
Esempio n. 5
0
static void
tapdev_init_darwin_routes(void)
{
  struct stat st;

  if(-1 == fstat(fd, &st)) {
    perror("tapdev: fstat failed.");
    exit(EXIT_FAILURE);
  }

  /************* Add address *************/

  struct in6_aliasreq addreq6 = { };
  reqfd = socket(AF_INET6, SOCK_DGRAM, 0);

  if(-1 == fcntl(reqfd, F_SETFD, FD_CLOEXEC)) {
    perror("tapdev: fcntl failed.");
    exit(EXIT_FAILURE);
  }

  devname_r(st.st_rdev, S_IFCHR, addreq6.ifra_name,
            sizeof(addreq6.ifra_name));

  addreq6.ifra_addr.sin6_family = AF_INET6;
  addreq6.ifra_addr.sin6_len = sizeof(addreq6.ifra_addr);
  addreq6.ifra_addr.sin6_addr.__u6_addr.__u6_addr16[0] = UIP_HTONS(0xFD00);
  addreq6.ifra_addr.sin6_addr.__u6_addr.__u6_addr16[7] = UIP_HTONS(0x0001);

  addreq6.ifra_prefixmask.sin6_family = AF_INET6;
  addreq6.ifra_prefixmask.sin6_len = sizeof(addreq6.ifra_prefixmask);
  addreq6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr16[0] =
    UIP_HTONS(0xFFFF);
  addreq6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr16[1] =
    UIP_HTONS(0xFFFF);
  addreq6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr16[2] =
    UIP_HTONS(0xFFFF);
  addreq6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr16[3] =
    UIP_HTONS(0xFFFF);

  addreq6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
  addreq6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
  addreq6.ifra_lifetime.ia6t_expire = ND6_INFINITE_LIFETIME;
  addreq6.ifra_lifetime.ia6t_preferred = ND6_INFINITE_LIFETIME;

  if(-1 == ioctl(reqfd, SIOCAIFADDR_IN6, &addreq6)) {
    perror("tapdev: Uable to add address, call to ioctl failed.");
    exit(EXIT_FAILURE);
  }

  /************* Add route *************/

  int s = socket(AF_ROUTE, SOCK_RAW, AF_INET6);

  if(s == -1) {
    perror("tapdev: Unable to add route, call to socket() failed.");

    // Failing to add the route is not fatal, so just return.
    return;
  }

  sfd = s;
  interface_index = if_nametoindex(devname(st.st_rdev, S_IFCHR));

  PRINTF("tapdev: if_nametoindex(devname(st.st_rdev, S_IFCHR)) = %d\n",
         interface_index);
  PRINTF("tapdev: devname(st.st_rdev, S_IFCHR) = %s\n",
         devname(st.st_rdev, S_IFCHR));

  struct {
    struct rt_msghdr hdr;
    struct sockaddr_in6 dst;
    struct sockaddr_dl gw;
    struct sockaddr_in6 mask;
  } msg = {};

  msg.hdr.rtm_msglen = sizeof(msg);
  msg.hdr.rtm_version = RTM_VERSION;
  msg.hdr.rtm_type = RTM_ADD;
  msg.hdr.rtm_index = interface_index;
  msg.hdr.rtm_flags = RTF_UP | RTF_STATIC;
  msg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
  msg.hdr.rtm_pid = getpid();
  msg.hdr.rtm_seq = 0;

  msg.dst.sin6_family = AF_INET6;
  msg.dst.sin6_len = sizeof(msg.dst);
  msg.dst.sin6_addr.__u6_addr.__u6_addr16[0] = UIP_HTONS(0xFD00);

  msg.gw.sdl_family = AF_LINK;
  msg.gw.sdl_len = sizeof(msg.gw);
  msg.gw.sdl_index = interface_index;

  msg.mask.sin6_family = AF_INET6;
  msg.mask.sin6_len = sizeof(msg.mask);
  msg.mask.sin6_addr.__u6_addr.__u6_addr16[0] = UIP_HTONS(0xFFFF);
  msg.mask.sin6_addr.__u6_addr.__u6_addr16[1] = UIP_HTONS(0xFFFF);
  msg.mask.sin6_addr.__u6_addr.__u6_addr16[2] = UIP_HTONS(0xFFFF);
  msg.mask.sin6_addr.__u6_addr.__u6_addr16[3] = UIP_HTONS(0xFFFF);

  if(-1 == write(s, &msg, sizeof(msg))) {
    perror("tapdev: Unable to add route, call to write() failed.");

    // Failing to add the route is not fatal, so just return.
    return;
  }
}
Esempio n. 6
0
int
main(int argc, char **argv)
{
    int       result    = -1;
    int       mntflags  = 0;
    int       fd        = -1;
    int32_t   dindex    = -1;
    char     *fdnam     = NULL;
    uint64_t  altflags  = 0ULL;
    char     *mntpath   = NULL;

    int i, ch = '\0', done = 0;
    struct mntopt *mo;
    struct mntval *mv;
    struct statfs statfsb;
    fuse_mount_args args;

    if (!getenv("MOUNT_FUSEFS_CALL_BY_LIB")) {
        showhelp();
        /* NOTREACHED */
    }

    /* Kludge to make "<fsdaemon> --version" happy. */
    if ((argc == 2) &&
        ((!strncmp(argv[1], "--version", strlen("--version"))) ||
         (!strncmp(argv[1], "-v", strlen("-v"))))) {
        showversion(1);
    }

    /* Kludge to make "<fsdaemon> --help" happy. */
    if ((argc == 2) &&
        ((!strncmp(argv[1], "--help", strlen("--help"))) ||
         (!strncmp(argv[1], "-h", strlen("-h"))))) {
        showhelp();
    }

    memset((void *)&args, 0, sizeof(args));

    do {
        for (i = 0; i < 3; i++) {
            if (optind < argc && argv[optind][0] != '-') {
                if (mntpath) {
                    done = 1;
                    break;
                }
                if (fdnam)
                    mntpath = argv[optind];
                else
                    fdnam = argv[optind];
                optind++;
            }
        }

        switch(ch) {
        case 'o':
            getmntopts(optarg, mopts, &mntflags, &altflags);
            for (mv = mvals; mv->mv_mntflag; ++mv) {
                if (!(altflags & mv->mv_mntflag)) {
                    continue;
                }
                for (mo = mopts; mo->m_option; ++mo) {
                    char *p, *q;
                    if (mo->m_flag != mv->mv_mntflag) {
                        continue;
                    }
                    p = strstr(optarg, mo->m_option);
                    if (p) {
                        p += strlen(mo->m_option);
                        q = p;
                        while (*q != '\0' && *q != ',') {
                            q++;
                        }
                        mv->mv_len = q - p + 1;
                        mv->mv_value = malloc(mv->mv_len);
                        memcpy(mv->mv_value, p, mv->mv_len - 1);
                        ((char *)mv->mv_value)[mv->mv_len - 1] = '\0';
                        break;
                    }
                }
            }
            break;

        case '\0':
            break;

        case 'v':
            showversion(1);
            break;

        case '?':
        case 'h':
        default:
            showhelp();
            break;
        }

        if (done) {
            break;
        }

    } while ((ch = getopt(argc, argv, "ho:v")) != -1);

    argc -= optind;
    argv += optind;

    if ((!fdnam) && argc > 0) {
        fdnam = *argv++;
        argc--;
    }

    if (!fdnam) {
        errx(EX_USAGE, "missing " OSXFUSE_DISPLAY_NAME
             " device file descriptor");
    }

    errno = 0;
    fd = (int)strtol(fdnam, NULL, 10);
    if ((errno == EINVAL) || (errno == ERANGE)) {
        errx(EX_USAGE, "invalid name (%s) for " OSXFUSE_DISPLAY_NAME
             " device file descriptor", fdnam);
    }

    signal_fd = fd;

    {
        char  ndev[MAXPATHLEN];
        char *ndevbas;
        struct stat sb;

        if (fstat(fd, &sb) == -1) {
            err(EX_OSERR, "fstat failed for " OSXFUSE_DISPLAY_NAME
                " device file descriptor");
        }
        args.rdev = sb.st_rdev;
        (void)strlcpy(ndev, _PATH_DEV, sizeof(ndev));
        ndevbas = ndev + strlen(_PATH_DEV);
        devname_r(sb.st_rdev, S_IFCHR, ndevbas,
                  (int)(sizeof(ndev) - strlen(_PATH_DEV)));

        if (strncmp(ndevbas, OSXFUSE_DEVICE_BASENAME,
                    strlen(OSXFUSE_DEVICE_BASENAME))) {
            errx(EX_USAGE, "mounting inappropriate device");
        }

        errno = 0;
        dindex = (int)strtol(ndevbas + strlen(OSXFUSE_DEVICE_BASENAME),
                             NULL, 10);
        if ((errno == EINVAL) || (errno == ERANGE) ||
            (dindex < 0) || (dindex > OSXFUSE_NDEVICES)) {
            errx(EX_USAGE, "invalid " OSXFUSE_DISPLAY_NAME
                 " device unit (#%d)\n", dindex);
        }
    }

    signal_idx = dindex;

    atexit(signal_idx_atexit_handler);

    result = check_kext_status();

    switch (result) {

    case 0:
        break;

    case ESRCH:
        errx(EX_UNAVAILABLE, "the " OSXFUSE_DISPLAY_NAME
             " kernel extension is not loaded");
        break;

    case EINVAL:
        errx(EX_UNAVAILABLE, "the loaded " OSXFUSE_DISPLAY_NAME
             " kernel extension has a mismatched version");
        break;

    default:
        errx(EX_UNAVAILABLE, "failed to query the loaded " OSXFUSE_DISPLAY_NAME
             " kernel extension (%d)", result);
        break;
    }

    if ((!mntpath) && argc > 0) {
        mntpath = *argv++;
        argc--;
    }

    if (!mntpath) {
        errx(EX_USAGE, "missing mount point");
    }

    (void)checkpath(mntpath, args.mntpath);

    mntpath = args.mntpath;

    fuse_process_mvals();

    if (statfs(mntpath, &statfsb)) {
        errx(EX_OSFILE, "cannot stat the mount point %s", mntpath);
    }

    if (((strlen(statfsb.f_fstypename) == strlen(OSXFUSE_NAME)) &&
         (strcmp(statfsb.f_fstypename, OSXFUSE_NAME) == 0)) ||
        ((strlen(OSXFUSE_TYPE_NAME_PREFIX) > 0) &&
         (strncmp(statfsb.f_fstypename, OSXFUSE_TYPE_NAME_PREFIX,
                  strlen(OSXFUSE_TYPE_NAME_PREFIX)) == 0))) {
        if (!(altflags & FUSE_MOPT_ALLOW_RECURSION)) {
            errx(EX_USAGE, "mount point %s is itself on a "
                 OSXFUSE_DISPLAY_NAME " volume", mntpath);
        }
    }

    /* allow_root and allow_other checks are done in the kernel. */

    if (altflags & FUSE_MOPT_NO_LOCALCACHES) {
        altflags |= FUSE_MOPT_NO_ATTRCACHE;
        altflags |= FUSE_MOPT_NO_READAHEAD;
        altflags |= FUSE_MOPT_NO_UBC;
        altflags |= FUSE_MOPT_NO_VNCACHE;
    }

    if ((altflags & FUSE_MOPT_NEGATIVE_VNCACHE) &&
        (altflags & FUSE_MOPT_NO_VNCACHE)) {
        errx(EX_USAGE, "'negative_vncache' can't be used with 'novncache'");
    }

    /*
     * 'nosyncwrites' must not appear with either 'noubc' or 'noreadahead'.
     */
    if ((altflags & FUSE_MOPT_NO_SYNCWRITES) &&
        (altflags & (FUSE_MOPT_NO_UBC | FUSE_MOPT_NO_READAHEAD))) {
        errx(EX_USAGE,
             "disabling local caching can't be used with 'nosyncwrites'");
    }

    /*
     * 'nosynconclose' only allowed if 'nosyncwrites' is also there.
     */
    if ((altflags & FUSE_MOPT_NO_SYNCONCLOSE) &&
        !(altflags & FUSE_MOPT_NO_SYNCWRITES)) {
        errx(EX_USAGE, "the 'nosynconclose' option requires 'nosyncwrites'");
    }

    if ((altflags & FUSE_MOPT_DEFAULT_PERMISSIONS) &&
        (altflags & FUSE_MOPT_DEFER_PERMISSIONS)) {
        errx(EX_USAGE,
             "'default_permissions' can't be used with 'defer_permissions'");
    }

    if ((altflags & FUSE_MOPT_AUTO_XATTR) &&
        (altflags & FUSE_MOPT_NATIVE_XATTR)) {
        errx(EX_USAGE,
             "'auto_xattr' can't be used with 'native_xattr'");
    }

    if (daemon_timeout < FUSE_MIN_DAEMON_TIMEOUT) {
        daemon_timeout = FUSE_MIN_DAEMON_TIMEOUT;
    }

    if (daemon_timeout > FUSE_MAX_DAEMON_TIMEOUT) {
        daemon_timeout = FUSE_MAX_DAEMON_TIMEOUT;
    }

    result = ioctl(fd, FUSEDEVIOCGETRANDOM, &drandom);
    if (result) {
        errx(EX_UNAVAILABLE, "failed to negotiate with /dev/"
             OSXFUSE_DEVICE_BASENAME "%d", dindex);
    }

    args.altflags       = altflags;
    args.blocksize      = (uint32_t) blocksize;
    args.daemon_timeout = (uint32_t) daemon_timeout;
    args.fsid           = (uint32_t) fsid;
    args.fssubtype      = (uint32_t) fssubtype;
    args.iosize         = (uint32_t) iosize;
    args.random         = drandom;

    char *daemon_name = NULL;
    char *daemon_path = getenv("MOUNT_OSXFUSE_DAEMON_PATH");
    if (daemon_path) {
        daemon_name = basename(daemon_path);
    }

    if (!fsname) {
        if (daemon_name) {
            snprintf(args.fsname, MAXPATHLEN, "%s@" OSXFUSE_DEVICE_BASENAME
                     "%d", daemon_name, dindex);
        } else {
            snprintf(args.fsname, MAXPATHLEN, "instance@"
                     OSXFUSE_DEVICE_BASENAME "%d", dindex);
        }
    } else {
        snprintf(args.fsname, MAXPATHLEN, "%s", fsname);
    }

    if (fstypename) {
        if (strlen(fstypename) > FUSE_TYPE_NAME_MAXLEN) {
            errx(EX_USAGE, "fstypename can be at most %lu characters",
                 (long unsigned int) FUSE_TYPE_NAME_MAXLEN);
        } else {
            snprintf(args.fstypename, MFSTYPENAMELEN, "%s", fstypename);
        }
    }

    if (!volname) {
        #if __clang__
            #pragma clang diagnostic push
            #pragma clang diagnostic ignored "-Wformat-extra-args"
        #endif

        if (daemon_name) {
            snprintf(args.volname, MAXPATHLEN, OSXFUSE_VOLNAME_DAEMON_FORMAT,
                     dindex, daemon_name);
        } else {
            snprintf(args.volname, MAXPATHLEN, OSXFUSE_VOLNAME_FORMAT, dindex);
        }

        #if __clang__
            #pragma clang diagnostic pop
        #endif
    } else {
        snprintf(args.volname, MAXPATHLEN, "%s", volname);
    }

    /* Finally! */
    result = mount(OSXFUSE_NAME, mntpath, mntflags, (void *)&args);

    if (result < 0) {
        err(EX_OSERR, "failed to mount %s@/dev/" OSXFUSE_DEVICE_BASENAME "%d",
            mntpath, dindex);
    } else {
        const char *dict[][2] = { { kFUSEMountPathKey, mntpath } };
        post_notification(NOTIFICATION_MOUNT, dict, 1);
    }

    signal_idx = -1;

    exit(0);
}
Esempio n. 7
0
int
main(int argc, char **argv)
{
    int       result    = -1;
    int       mntflags  = 0;
    int       cfd       = -1;
    char     *fdnam     = NULL;
    char     *dev       = NULL;
    int       r         = 0;
    char      devpath[MAXPATHLEN];
    int       fd        = -1;
    int32_t   dindex    = -1;
    uint64_t  altflags  = 0ULL;
    char     *mntpath   = NULL;

    struct mntopt *mo;
    struct mntval *mv;
    struct statfs statfsb;
    fuse_mount_args args;

    // Drop to real uid and gid
    seteuid(getuid());
    setegid(getgid());

    if (!getenv("MOUNT_OSXFUSE_CALL_BY_LIB")) {
        showhelp();
    }

    memset((void *)&args, 0, sizeof(args));

    while (true) {
        static struct option long_options[] = {
            { "help",    no_argument, NULL, 'h' },
            { "version", no_argument, NULL, 'v' },
            { NULL, 0, NULL, 0 }
        };

        int c = getopt_long(argc, argv, "ho:qv", long_options, NULL);
        if (c == -1) {
            break;
        }

        switch (c) {
            case 'o':
                getmntopts(optarg, mopts, &mntflags, &altflags);
                for (mv = mvals; mv->mv_mntflag; ++mv) {
                    if (!(altflags & mv->mv_mntflag)) {
                        continue;
                    }
                    for (mo = mopts; mo->m_option; ++mo) {
                        char *p, *q;
                        if (!mo->m_altloc || mo->m_flag != mv->mv_mntflag) {
                            continue;
                        }
                        p = strstr(optarg, mo->m_option);
                        if (p) {
                            p += strlen(mo->m_option);
                            q = p;
                            while (*q != '\0' && *q != ',') {
                                q++;
                            }
                            mv->mv_len = q - p + 1;
                            mv->mv_value = malloc(mv->mv_len);
                            memcpy(mv->mv_value, p, mv->mv_len - 1);
                            ((char *)mv->mv_value)[mv->mv_len - 1] = '\0';
                            break;
                        }
                    }
                }
                break;

            case 'q':
                quiet_mode = true;
                break;

            case 'v':
                showversion(true);
                break;

            case 'h':
            case '?':
            default:
                showhelp();
                break;
        }
    }

    argc -= optind;
    argv += optind;

    if (argc >= 1) {
        mntpath = argv[0];
        argc--;
        argv++;
    }

    if (!mntpath) {
        errx(EX_USAGE, "missing mount point");
    }

    {
        char *commfd;

        commfd = getenv("_FUSE_COMMFD");
        if (commfd == NULL) {
            errx(EX_USAGE, "mew style mounting requires commfd");
        }

        errno = 0;
        cfd = (int)strtol(commfd, NULL, 10);
        if (errno == EINVAL || errno == ERANGE || cfd < 0) {
            errx(EX_USAGE, "invalid commfd");
        }
    }

    result = load_kext();
    if (result) {
        if (result == EINVAL) {
            if (!quiet_mode) {
                CFUserNotificationDisplayNotice(
                    (CFTimeInterval)0,
                    kCFUserNotificationCautionAlertLevel,
                    (CFURLRef)0,
                    (CFURLRef)0,
                    (CFURLRef)0,
                    CFSTR("Installed version of macOS unsupported"),
                    CFSTR("The installed version of FUSE is too new for the operating system. Please downgrade your FUSE installation to one that is compatible with the currently running version of macOS."),
                    CFSTR("OK"));
            }
            post_notification(NOTIFICATION_OS_IS_TOO_OLD, NULL, 0);
        }
        if (result == ENOENT) {
            if (!quiet_mode) {
                CFUserNotificationDisplayNotice(
                    (CFTimeInterval)0,
                    kCFUserNotificationCautionAlertLevel,
                    (CFURLRef)0,
                    (CFURLRef)0,
                    (CFURLRef)0,
                    CFSTR("Installed version of macOS unsupported"),
                    CFSTR("The installed version of FUSE is too old for the operating system. Please upgrade your FUSE installation to one that is compatible with the currently running version of macOS."),
                    CFSTR("OK"));
            }
            post_notification(NOTIFICATION_OS_IS_TOO_NEW, NULL, 0);
        } else if (result == EBUSY) {
            if (!quiet_mode) {
                CFUserNotificationDisplayNotice(
                    (CFTimeInterval)0,
                    kCFUserNotificationCautionAlertLevel,
                    (CFURLRef)0,
                    (CFURLRef)0,
                    (CFURLRef)0,
                    CFSTR("FUSE version mismatch"),
                    CFSTR("FUSE has been updated but an incompatible or old version of the FUSE kernel extension is already loaded. It failed to unload, possibly because a FUSE volume is currently mounted.\n\nPlease eject all FUSE volumes and try again, or simply restart the system for changes to take effect."),
                    CFSTR("OK"));
            }
            post_notification(NOTIFICATION_VERSION_MISMATCH, NULL, 0);
        }
        errx(EX_UNAVAILABLE, "the " OSXFUSE_DISPLAY_NAME " file system is not available (%d)", result);
    }

    result = check_kext_status();
    switch (result) {
        case 0:
            break;

        case ESRCH:
            errx(EX_UNAVAILABLE, "the " OSXFUSE_DISPLAY_NAME
                 " kernel extension is not loaded");
            break;

        case EINVAL:
            errx(EX_UNAVAILABLE, "the loaded " OSXFUSE_DISPLAY_NAME
                 " kernel extension has a mismatched version");
            break;

        default:
            errx(EX_UNAVAILABLE, "failed to query the loaded " OSXFUSE_DISPLAY_NAME
                 " kernel extension (%d)", result);
            break;
    }

    fdnam = getenv("FUSE_DEV_FD");
    if (fdnam) {
        errno = 0;
        fd = (int)strtol(fdnam, NULL, 10);
        if (errno == EINVAL || errno == ERANGE || fd < 0) {
            errx(EX_USAGE, "invalid value given in FUSE_DEV_FD");
        }

        goto mount;
    }

    dev = getenv("FUSE_DEV_NAME");
    if (dev) {
        fd = open(dev, O_RDWR);
        if (fd < 0) {
            errx(EX_USAGE, "failed to open device");
        }

        goto mount;
    }

    for (r = 0; r < OSXFUSE_NDEVICES; r++) {
        snprintf(devpath, MAXPATHLEN - 1,
                 _PATH_DEV OSXFUSE_DEVICE_BASENAME "%d", r);
        fd = open(devpath, O_RDWR);
        if (fd >= 0) {
            dindex = r;
            break;
        }
    }
    if (dindex == -1) {
        errx(EX_OSERR, "failed to open device");
    }

mount:
    signal_fd = fd;
    atexit(&signal_idx_atexit_handler);

    {
        struct stat sb;
        if (fstat(fd, &sb) == -1) {
            err(EX_OSERR, "fstat failed for " OSXFUSE_DISPLAY_NAME " device file descriptor");
        }
        args.rdev = sb.st_rdev;
    }

    if (dindex < 0) {
        char  ndev[MAXPATHLEN];
        char *ndevbas;

        (void)strlcpy(ndev, _PATH_DEV, sizeof(ndev));
        ndevbas = ndev + strlen(_PATH_DEV);
        devname_r(args.rdev, S_IFCHR, ndevbas, (int)(sizeof(ndev) - strlen(_PATH_DEV)));

        if (strncmp(ndevbas, OSXFUSE_DEVICE_BASENAME, strlen(OSXFUSE_DEVICE_BASENAME))) {
            errx(EX_USAGE, "mounting inappropriate device");
        }

        errno = 0;
        dindex = (int)strtol(ndevbas + strlen(OSXFUSE_DEVICE_BASENAME), NULL, 10);
        if (errno == EINVAL || errno == ERANGE || dindex < 0 || dindex > OSXFUSE_NDEVICES) {
            errx(EX_USAGE, "invalid " OSXFUSE_DISPLAY_NAME " device unit (#%d)\n", dindex);
        }
    }

    while (true) {
        struct stat sb;

        if (realpath(mntpath, args.mntpath) != NULL &&
            stat(args.mntpath, &sb) == 0) {

            if (S_ISDIR(sb.st_mode)) {
                break;
            } else {
                errx(EX_USAGE, "%s: not a directory", args.mntpath);
            }

        } else if (errno == ENOENT) {
            bool volumes = strncmp(args.mntpath, "/Volumes/", 9) == 0 &&
                           strchr(args.mntpath + 9, '/') == NULL;

            if (volumes) {
                (void)seteuid(0);
                (void)setegid(0);
            }

            if (mkdir(args.mntpath, 0755)) {
                errx(EX_USAGE, "%s: %s", args.mntpath, strerror(errno));
            }

            if (volumes) {
                uid_t uid = getuid();
                gid_t gid = getgid();

                (void)chown(args.mntpath, uid, gid);
                (void)seteuid(uid);
                (void)setegid(gid);
            }

        } else {
            errx(EX_USAGE, "%s: %s", args.mntpath, strerror(errno));
        }
    }

    mntpath = args.mntpath;

    fuse_process_mvals();

    if (statfs(mntpath, &statfsb)) {
        errx(EX_OSFILE, "cannot stat the mount point %s", mntpath);
    }

    if (((strlen(statfsb.f_fstypename) == strlen(OSXFUSE_NAME)) &&
         (strcmp(statfsb.f_fstypename, OSXFUSE_NAME) == 0)) ||
        ((strlen(OSXFUSE_TYPE_NAME_PREFIX) > 0) &&
         (strncmp(statfsb.f_fstypename, OSXFUSE_TYPE_NAME_PREFIX,
                  strlen(OSXFUSE_TYPE_NAME_PREFIX)) == 0))) {
        if (!(altflags & FUSE_MOPT_ALLOW_RECURSION)) {
            errx(EX_USAGE, "mount point %s is itself on a "
                 OSXFUSE_DISPLAY_NAME " volume", mntpath);
        }
    }

    /* allow_root and allow_other checks are done in the kernel. */

    if (altflags & FUSE_MOPT_NO_LOCALCACHES) {
        altflags |= FUSE_MOPT_NO_ATTRCACHE;
        altflags |= FUSE_MOPT_NO_READAHEAD;
        altflags |= FUSE_MOPT_NO_UBC;
        altflags |= FUSE_MOPT_NO_VNCACHE;
    }

    if ((altflags & FUSE_MOPT_NEGATIVE_VNCACHE) &&
        (altflags & FUSE_MOPT_NO_VNCACHE)) {
        errx(EX_USAGE, "'negative_vncache' can't be used with 'novncache'");
    }

    /*
     * 'nosyncwrites' must not appear with either 'noubc' or 'noreadahead'.
     */
    if ((altflags & FUSE_MOPT_NO_SYNCWRITES) &&
        (altflags & (FUSE_MOPT_NO_UBC | FUSE_MOPT_NO_READAHEAD))) {
        errx(EX_USAGE,
             "disabling local caching can't be used with 'nosyncwrites'");
    }

    /*
     * 'nosynconclose' only allowed if 'nosyncwrites' is also there.
     */
    if ((altflags & FUSE_MOPT_NO_SYNCONCLOSE) &&
        !(altflags & FUSE_MOPT_NO_SYNCWRITES)) {
        errx(EX_USAGE, "the 'nosynconclose' option requires 'nosyncwrites'");
    }

    if ((altflags & FUSE_MOPT_DEFAULT_PERMISSIONS) &&
        (altflags & FUSE_MOPT_DEFER_PERMISSIONS)) {
        errx(EX_USAGE,
             "'default_permissions' can't be used with 'defer_permissions'");
    }

    if ((altflags & FUSE_MOPT_AUTO_XATTR) &&
        (altflags & FUSE_MOPT_NATIVE_XATTR)) {
        errx(EX_USAGE,
             "'auto_xattr' can't be used with 'native_xattr'");
    }

    if (daemon_timeout < FUSE_MIN_DAEMON_TIMEOUT) {
        daemon_timeout = FUSE_MIN_DAEMON_TIMEOUT;
    }

    if (daemon_timeout > FUSE_MAX_DAEMON_TIMEOUT) {
        daemon_timeout = FUSE_MAX_DAEMON_TIMEOUT;
    }

    result = ioctl(fd, FUSEDEVIOCGETRANDOM, &drandom);
    if (result) {
        errx(EX_UNAVAILABLE, "failed to negotiate with /dev/"
             OSXFUSE_DEVICE_BASENAME "%d", dindex);
    }

    args.altflags       = altflags;
    args.blocksize      = (uint32_t)blocksize;
    args.daemon_timeout = (uint32_t)daemon_timeout;
    args.fsid           = (uint32_t)fsid;
    args.fssubtype      = (uint32_t)fssubtype;
    args.iosize         = (uint32_t)iosize;
    args.random         = drandom;

    char *daemon_name = NULL;
    char *daemon_path = getenv("MOUNT_OSXFUSE_DAEMON_PATH");
    if (daemon_path) {
        daemon_name = basename(daemon_path);
    }

    if (!fsname) {
        if (daemon_name) {
            snprintf(args.fsname, MAXPATHLEN, "%s@" OSXFUSE_DEVICE_BASENAME
                     "%d", daemon_name, dindex);
        } else {
            snprintf(args.fsname, MAXPATHLEN, "instance@"
                     OSXFUSE_DEVICE_BASENAME "%d", dindex);
        }
    } else {
        snprintf(args.fsname, MAXPATHLEN, "%s", fsname);
    }

    if (fstypename) {
        if (strlen(fstypename) > FUSE_TYPE_NAME_MAXLEN) {
            errx(EX_USAGE, "fstypename can be at most %lu characters",
                 (long unsigned int) FUSE_TYPE_NAME_MAXLEN);
        } else {
            snprintf(args.fstypename, MFSTYPENAMELEN, "%s", fstypename);
        }
    }

    if (!volname) {
        #if __clang__
            #pragma clang diagnostic push
            #pragma clang diagnostic ignored "-Wformat-extra-args"
        #endif

        if (daemon_name) {
            snprintf(args.volname, MAXPATHLEN, OSXFUSE_VOLNAME_DAEMON_FORMAT,
                     dindex, daemon_name);
        } else {
            snprintf(args.volname, MAXPATHLEN, OSXFUSE_VOLNAME_FORMAT, dindex);
        }

        #if __clang__
            #pragma clang diagnostic pop
        #endif
    } else {
        snprintf(args.volname, MAXPATHLEN, "%s", volname);
    }

    if (cfd != -1) {
        result = send_fd(cfd, fd);
        if (result == -1) {
            err(EX_OSERR, "failed to send file descriptor");
        }
    }

    /* Finally! */
    result = mount(OSXFUSE_NAME, mntpath, mntflags, (void *)&args);

    if (result < 0) {
        err(EX_OSERR, "failed to mount %s@/dev/" OSXFUSE_DEVICE_BASENAME "%d",
            mntpath, dindex);
    } else {
        const char *dict[][2] = { { kFUSEMountPathKey, mntpath } };
        post_notification(NOTIFICATION_MOUNT, dict, 1);
    }

    signal_fd = -1;
    exit(0);
}
Esempio n. 8
0
/*---------------------------------------------------------------------------*/
void
tapdev_init(void)
{
  char buf[1024];
  
  fd = open(DEVTAP, O_RDWR);
  if(fd == -1) {
    perror("tapdev: tapdev_init: open");
    return;
  }

#ifdef linux
  {
    struct ifreq ifr;
    memset(&ifr, 0, sizeof(ifr));
    ifr.ifr_flags = IFF_TAP|IFF_NO_PI;
    if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
      perror(buf);
      exit(1);
    }
  }
#endif /* Linux */

#if defined(__APPLE__)
	struct stat st;
	fstat(fd,&st);
	{	// Add address
		struct in6_aliasreq addreq6 = {};
		reqfd = socket(AF_INET6,SOCK_DGRAM,0);
		
		if(-1 == fcntl(reqfd,F_SETFD,FD_CLOEXEC)) {
			printf("Call to fcntl(reqfd,F_SETFD,FD_CLOEXEC) failed, errno=%d (%s)\n",errno,strerror(errno));
		}

		devname_r(st.st_rdev, S_IFCHR, addreq6.ifra_name, sizeof(addreq6.ifra_name));
		//printf("Interface name: %s\n",addreq6.ifra_name);

		addreq6.ifra_addr.sin6_family = AF_INET6;
		addreq6.ifra_addr.sin6_len = sizeof(addreq6.ifra_addr);
		addreq6.ifra_addr.sin6_addr.__u6_addr.__u6_addr16[0]=UIP_HTONS(0xAAAA);
		addreq6.ifra_addr.sin6_addr.__u6_addr.__u6_addr16[7]=UIP_HTONS(0x0001);

/*
		addreq6.ifra_dstaddr.sin6_family = AF_INET6;
		addreq6.ifra_dstaddr.sin6_len = sizeof(addreq6.ifra_dstaddr);
		addreq6.ifra_dstaddr.sin6_addr.__u6_addr.__u6_addr16[0]=UIP_HTONS(0xAAAA);
*/

		addreq6.ifra_prefixmask.sin6_family = AF_INET6;
		addreq6.ifra_prefixmask.sin6_len = sizeof(addreq6.ifra_prefixmask);
		addreq6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr16[0]=UIP_HTONS(0xFFFF);
		addreq6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr16[1]=UIP_HTONS(0xFFFF);
		addreq6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr16[2]=UIP_HTONS(0xFFFF);
		addreq6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr16[3]=UIP_HTONS(0xFFFF);

		addreq6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
		addreq6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
		addreq6.ifra_lifetime.ia6t_expire = ND6_INFINITE_LIFETIME;
		addreq6.ifra_lifetime.ia6t_preferred = ND6_INFINITE_LIFETIME;
		//addreq6.ifra_flags |= IN6_IFF_AUTOCONF;
		
		if(-1 == ioctl (reqfd, SIOCAIFADDR_IN6, &addreq6)) {
			printf("Unable to set interface address, errno=%d (%s)\n",errno,strerror(errno));
		}
	}
	{	// Add route
		int s = socket (AF_ROUTE, SOCK_RAW, AF_INET6);
		sfd = s;
		interface_index = if_nametoindex(devname(st.st_rdev, S_IFCHR));
		if(s == -1) {
			printf("Unable to create AF_ROUTE socket, errno=%d (%s)\n",errno,strerror(errno));
		}

		printf("if_nametoindex(devname(st.st_rdev, S_IFCHR)) = %d\n",interface_index);
		printf("devname(st.st_rdev, S_IFCHR) = %s\n",devname(st.st_rdev, S_IFCHR));
		
		struct
		{
			struct rt_msghdr hdr;
			struct sockaddr_in6 dst;
			struct sockaddr_dl gw;
			struct sockaddr_in6 mask;
		} msg = {};

/*
		if(-1==shutdown (s, 0)) {
			printf("Call to shutdown failed, errno=%d (%s)\n",errno,strerror(errno));
		}
*/

		msg.hdr.rtm_msglen = sizeof (msg);
		msg.hdr.rtm_version = RTM_VERSION;
		msg.hdr.rtm_type = RTM_ADD;
		msg.hdr.rtm_index = interface_index;
		msg.hdr.rtm_flags = RTF_UP | RTF_STATIC;
		msg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
		msg.hdr.rtm_pid = getpid ();
		msg.hdr.rtm_seq = 0;

		msg.dst.sin6_family = AF_INET6;
		msg.dst.sin6_len = sizeof (msg.dst);
		msg.dst.sin6_addr.__u6_addr.__u6_addr16[0]=UIP_HTONS(0xAAAA);

		msg.gw.sdl_family = AF_LINK;
		msg.gw.sdl_len = sizeof (msg.gw);
		msg.gw.sdl_index = interface_index;

		msg.mask.sin6_family = AF_INET6;
		msg.mask.sin6_len = sizeof(msg.mask);
		msg.mask.sin6_addr.__u6_addr.__u6_addr16[0]=UIP_HTONS(0xFFFF);
		msg.mask.sin6_addr.__u6_addr.__u6_addr16[1]=UIP_HTONS(0xFFFF);
		msg.mask.sin6_addr.__u6_addr.__u6_addr16[2]=UIP_HTONS(0xFFFF);
		msg.mask.sin6_addr.__u6_addr.__u6_addr16[3]=UIP_HTONS(0xFFFF);
		if(-1==write(s,&msg,sizeof(msg))) {
			printf("Unable to add route, errno=%d (%s)\n",errno,strerror(errno));
		}
		
	}
#endif // defined(__DARWIN__)


  /* Linux (ubuntu)
     snprintf(buf, sizeof(buf), "ip link set tap0 up");
     system(buf);
     PRINTF("%s\n", buf);
     snprintf(buf, sizeof(buf), "ip -6 address add fc00::231/7 dev tap0");
     system(buf);
     PRINTF("%s\n", buf);
     snprintf(buf, sizeof(buf), "ip -6 route add fc00::0/7 dev tap0");
     system(buf);
     PRINTF("%s\n", buf);
  */
  /* freebsd */
  snprintf(buf, sizeof(buf), "ifconfig tap0 up");
  system(buf);
  printf("%s\n", buf);
  
  /*  */
  lasttime = 0;
  
  /*  gdk_input_add(fd, GDK_INPUT_READ,
      read_callback, NULL);*/
  atexit(&tapdev_exit);
}