예제 #1
0
int fuse_reply_bmap(fuse_req_t req, uint64_t idx)
{
	struct fuse_bmap_out arg;

	memset(&arg, 0, sizeof(arg));
	arg.block = idx;

	return send_reply_ok(req, &arg, sizeof(arg));
}
예제 #2
0
int fuse_reply_poll(fuse_req_t req, unsigned revents)
{
	struct fuse_poll_out arg;

	memset(&arg, 0, sizeof(arg));
	arg.revents = revents;

	return send_reply_ok(req, &arg, sizeof(arg));
}
int fuse_reply_open_compat(fuse_req_t req,
			   const struct fuse_file_info_compat *f)
{
	struct fuse_open_out arg;

	memset(&arg, 0, sizeof(arg));
	fill_open_compat(&arg, f);
	return send_reply_ok(req, &arg, sizeof(arg));
}
예제 #4
0
int fuse_reply_xattr(fuse_req_t req, size_t count)
{
    struct fuse_getxattr_out arg;

    memset(&arg, 0, sizeof(arg));
    arg.size = count;

    return send_reply_ok(req, &arg, sizeof(arg));
}
int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
{
    struct fuse_entry_out arg;

    /* before ABI 7.4 e->ino == 0 was invalid, only ENOENT meant
       negative entry */
    if (!e->ino && req->f->conn.proto_minor < 4)
        return fuse_reply_err(req, ENOENT);

    memset(&arg, 0, sizeof(arg));
    fill_entry(&arg, e);
#ifdef POSIXACLS
    return send_reply_ok(req, &arg, (req->f->conn.proto_minor >= 12 
			? sizeof(arg) : FUSE_COMPAT_ENTRY_OUT_SIZE));
#else
    return send_reply_ok(req, &arg, sizeof(arg));
#endif
}
예제 #6
0
int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf)
{
    struct fuse_statfs_out arg;
    size_t size = req->f->conn.proto_minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(arg);

    memset(&arg, 0, sizeof(arg));
    convert_statfs(stbuf, &arg.st);

    return send_reply_ok(req, &arg, size);
}
예제 #7
0
int fuse_reply_attr(fuse_req_t req, const struct stat *attr,
                    double attr_timeout)
{
    struct fuse_attr_out arg;

    memset(&arg, 0, sizeof(arg));
    arg.attr_valid = calc_timeout_sec(attr_timeout);
    arg.attr_valid_nsec = calc_timeout_nsec(attr_timeout);
    convert_stat(attr, &arg.attr);

    return send_reply_ok(req, &arg, sizeof(arg));
}
예제 #8
0
int fuse_reply_xtimes(fuse_req_t req, const struct timespec *bkuptime,
		      const struct timespec *crtime)
{
	struct fuse_getxtimes_out arg;

	arg.bkuptime = bkuptime->tv_sec;
	arg.bkuptimensec = bkuptime->tv_nsec;
	arg.crtime = crtime->tv_sec;
	arg.crtimensec = crtime->tv_nsec;

	return send_reply_ok(req, &arg, sizeof(arg));
}
예제 #9
0
static void do_destroy(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
{
    struct fuse_ll *f = req->f;

    (void) nodeid;
    (void) inarg;

    f->got_destroy = 1;
    if (f->op.destroy)
        f->op.destroy(f->userdata);

    send_reply_ok(req, NULL, 0);
}
예제 #10
0
int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
{
    struct fuse_entry_out arg;

    /* before ABI 7.4 e->ino == 0 was invalid, only ENOENT meant
       negative entry */
    if (!e->ino && req->f->conn.proto_minor < 4)
        return fuse_reply_err(req, ENOENT);

    memset(&arg, 0, sizeof(arg));
    fill_entry(&arg, e);
    return send_reply_ok(req, &arg, sizeof(arg));
}
예제 #11
0
int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e,
                      const struct fuse_file_info *f)
{
    struct {
        struct fuse_entry_out e;
        struct fuse_open_out o;
    } arg;

    memset(&arg, 0, sizeof(arg));
    fill_entry(&arg.e, e);
    fill_open(&arg.o, f);
    return send_reply_ok(req, &arg, sizeof(arg));
}
예제 #12
0
int fuse_reply_attr(fuse_req_t req, const struct stat *attr,
		    double attr_timeout)
{
	struct fuse_attr_out arg;
	size_t size = req->f->conn.proto_minor < 9 ?
		FUSE_COMPAT_ATTR_OUT_SIZE : sizeof(arg);

	memset(&arg, 0, sizeof(arg));
	arg.attr_valid = calc_timeout_sec(attr_timeout);
	arg.attr_valid_nsec = calc_timeout_nsec(attr_timeout);
	convert_stat(attr, &arg.attr);

	return send_reply_ok(req, &arg, size);
}
예제 #13
0
int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e,
		      const struct fuse_file_info *f)
{
	char buf[sizeof(struct fuse_entry_out) + sizeof(struct fuse_open_out)];
	size_t entrysize = req->f->conn.proto_minor < 9 ?
		FUSE_COMPAT_ENTRY_OUT_SIZE : sizeof(struct fuse_entry_out);
	struct fuse_entry_out *earg = (struct fuse_entry_out *) buf;
	struct fuse_open_out *oarg = (struct fuse_open_out *) (buf + entrysize);

	memset(buf, 0, sizeof(buf));
	fill_entry(earg, e);
	fill_open(oarg, f);
	return send_reply_ok(req, buf,
			     entrysize + sizeof(struct fuse_open_out));
}
예제 #14
0
int fuse_reply_lock(fuse_req_t req, struct flock *lock)
{
    struct fuse_lk_out arg;

    memset(&arg, 0, sizeof(arg));
    arg.lk.type = lock->l_type;
    if (lock->l_type != F_UNLCK) {
        arg.lk.start = lock->l_start;
        if (lock->l_len == 0)
            arg.lk.end = OFFSET_MAX;
        else
            arg.lk.end = lock->l_start + lock->l_len - 1;
    }
    arg.lk.pid = lock->l_pid;
    return send_reply_ok(req, &arg, sizeof(arg));
}
static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
{
	struct fuse_init_in *arg = (struct fuse_init_in *) inarg;
	struct fuse_init_out outarg;
	struct fuse_ll *f = req->f;
	size_t bufsize = fuse_chan_bufsize(req->ch);

	(void) nodeid;
	if (f->debug) {
		fprintf(stderr, "INIT: %u.%u\n", arg->major, arg->minor);
		if (arg->major == 7 && arg->minor >= 6) {
			fprintf(stderr, "flags=0x%08x\n", arg->flags);
			fprintf(stderr, "max_readahead=0x%08x\n",
				arg->max_readahead);
		}
	}
	f->conn.proto_major = arg->major;
	f->conn.proto_minor = arg->minor;
	f->conn.capable = 0;
	f->conn.want = 0;

	memset(&outarg, 0, sizeof(outarg));
	outarg.major = FUSE_KERNEL_VERSION;
	outarg.minor = FUSE_KERNEL_MINOR_VERSION;

	if (arg->major < 7) {
		fprintf(stderr, "fuse: unsupported protocol version: %u.%u\n",
			arg->major, arg->minor);
		fuse_reply_err(req, EPROTO);
		return;
	}

	if (arg->major > 7) {
		/* Wait for a second INIT request with a 7.X version */
		send_reply_ok(req, &outarg, sizeof(outarg));
		return;
	}

	if (arg->minor >= 6) {
		if (f->conn.async_read)
			f->conn.async_read = arg->flags & FUSE_ASYNC_READ;
		if (arg->max_readahead < f->conn.max_readahead)
			f->conn.max_readahead = arg->max_readahead;
		if (arg->flags & FUSE_ASYNC_READ)
			f->conn.capable |= FUSE_CAP_ASYNC_READ;
		if (arg->flags & FUSE_POSIX_LOCKS)
			f->conn.capable |= FUSE_CAP_POSIX_LOCKS;
		if (arg->flags & FUSE_ATOMIC_O_TRUNC)
			f->conn.capable |= FUSE_CAP_ATOMIC_O_TRUNC;
		if (arg->flags & FUSE_EXPORT_SUPPORT)
			f->conn.capable |= FUSE_CAP_EXPORT_SUPPORT;
		if (arg->flags & FUSE_BIG_WRITES)
			f->conn.capable |= FUSE_CAP_BIG_WRITES;
		if (arg->flags & FUSE_DONT_MASK)
			f->conn.capable |= FUSE_CAP_DONT_MASK;
	} else {
		f->conn.async_read = 0;
		f->conn.max_readahead = 0;
	}

	if (f->atomic_o_trunc)
		f->conn.want |= FUSE_CAP_ATOMIC_O_TRUNC;
	if (f->op.getlk && f->op.setlk && !f->no_remote_lock)
		f->conn.want |= FUSE_CAP_POSIX_LOCKS;
	if (f->big_writes)
		f->conn.want |= FUSE_CAP_BIG_WRITES;

	if (bufsize < FUSE_MIN_READ_BUFFER) {
		fprintf(stderr, "fuse: warning: buffer size too small: %zu\n",
			bufsize);
		bufsize = FUSE_MIN_READ_BUFFER;
	}

	bufsize -= 4096;
	if (bufsize < f->conn.max_write)
		f->conn.max_write = bufsize;

	f->got_init = 1;
	if (f->op.init)
		f->op.init(f->userdata, &f->conn);

	if (f->conn.async_read || (f->conn.want & FUSE_CAP_ASYNC_READ))
		outarg.flags |= FUSE_ASYNC_READ;
	if (f->conn.want & FUSE_CAP_POSIX_LOCKS)
		outarg.flags |= FUSE_POSIX_LOCKS;
	if (f->conn.want & FUSE_CAP_ATOMIC_O_TRUNC)
		outarg.flags |= FUSE_ATOMIC_O_TRUNC;
	if (f->conn.want & FUSE_CAP_EXPORT_SUPPORT)
		outarg.flags |= FUSE_EXPORT_SUPPORT;
	if (f->conn.want & FUSE_CAP_BIG_WRITES)
		outarg.flags |= FUSE_BIG_WRITES;
	if (f->conn.want & FUSE_CAP_DONT_MASK)
		outarg.flags |= FUSE_DONT_MASK;
	outarg.max_readahead = f->conn.max_readahead;
	outarg.max_write = f->conn.max_write;

	if (f->debug) {
		fprintf(stderr, "   INIT: %u.%u\n", outarg.major, outarg.minor);
		fprintf(stderr, "   flags=0x%08x\n", outarg.flags);
		fprintf(stderr, "   max_readahead=0x%08x\n",
			outarg.max_readahead);
		fprintf(stderr, "   max_write=0x%08x\n", outarg.max_write);
	}

	send_reply_ok(req, &outarg, arg->minor < 5 ? 8 : sizeof(outarg));
}
예제 #16
0
int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
{
    return send_reply_ok(req, buf, size);
}
예제 #17
0
int fuse_reply_readlink(fuse_req_t req, const char *linkname)
{
    return send_reply_ok(req, linkname, strlen(linkname));
}
예제 #18
0
static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
{
    struct fuse_init_in *arg = (struct fuse_init_in *) inarg;
    struct fuse_init_out outarg;
    struct fuse_ll *f = req->f;
    size_t bufsize = fuse_chan_bufsize(req->ch);

    (void) nodeid;
    if (f->debug) {
        fprintf(stderr, "INIT: %u.%u\n", arg->major, arg->minor);
        if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
            fprintf(stderr, "flags=0x%08x\n", arg->flags);
            fprintf(stderr, "max_readahead=0x%08x\n", arg->max_readahead);
        }
    }
    f->conn.proto_major = arg->major;
    f->conn.proto_minor = arg->minor;

    if (arg->major < 7) {
        fprintf(stderr, "fuse: unsupported protocol version: %u.%u\n",
                arg->major, arg->minor);
        fuse_reply_err(req, EPROTO);
        return;
    }

    if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
        if (f->conn.async_read)
            f->conn.async_read = arg->flags & FUSE_ASYNC_READ;
        if (arg->max_readahead < f->conn.max_readahead)
            f->conn.max_readahead = arg->max_readahead;
    } else {
        f->conn.async_read = 0;
        f->conn.max_readahead = 0;
    }

    if (bufsize < FUSE_MIN_READ_BUFFER) {
        fprintf(stderr, "fuse: warning: buffer size too small: %zu\n",
                bufsize);
        bufsize = FUSE_MIN_READ_BUFFER;
    }

    bufsize -= 4096;
    if (bufsize < f->conn.max_write)
        f->conn.max_write = bufsize;

    f->got_init = 1;
    if (f->op.init)
        f->op.init(f->userdata, &f->conn);

    memset(&outarg, 0, sizeof(outarg));
    outarg.major = FUSE_KERNEL_VERSION;
    outarg.minor = FUSE_KERNEL_MINOR_VERSION;
    if (f->conn.async_read)
        outarg.flags |= FUSE_ASYNC_READ;
    if (f->op.getlk && f->op.setlk)
        outarg.flags |= FUSE_POSIX_LOCKS;
    outarg.max_readahead = f->conn.max_readahead;
    outarg.max_write = f->conn.max_write;

    if (f->debug) {
        fprintf(stderr, "   INIT: %u.%u\n", outarg.major, outarg.minor);
        fprintf(stderr, "   flags=0x%08x\n", outarg.flags);
        fprintf(stderr, "   max_readahead=0x%08x\n", outarg.max_readahead);
        fprintf(stderr, "   max_write=0x%08x\n", outarg.max_write);
    }

    send_reply_ok(req, &outarg, arg->minor < 5 ? 8 : sizeof(outarg));
}
예제 #19
0
/*
 * Callback notification from STUN session when it receives STUN
 * requests. This callback was trigger by STUN incoming message
 * processing in pj_turn_allocation_on_rx_client_pkt().
 */
static pj_status_t stun_on_rx_request(pj_stun_session *sess,
				      const pj_uint8_t *pkt,
				      unsigned pkt_len,
				      const pj_stun_rx_data *rdata,
				      void *token,
				      const pj_sockaddr_t *src_addr,
				      unsigned src_addr_len)
{
    const pj_stun_msg *msg = rdata->msg;
    pj_turn_allocation *alloc;

    PJ_UNUSED_ARG(pkt);
    PJ_UNUSED_ARG(pkt_len);
    PJ_UNUSED_ARG(token);
    PJ_UNUSED_ARG(src_addr);
    PJ_UNUSED_ARG(src_addr_len);

    alloc = (pj_turn_allocation*) pj_stun_session_get_user_data(sess);

    /* Refuse to serve any request if we've been shutdown */
    if (alloc->relay.lifetime == 0) {
	/* Reject with 437 if we're shutting down */
	send_reply_err(alloc, rdata, PJ_TRUE,
		       PJ_STUN_SC_ALLOCATION_MISMATCH, NULL);
	return PJ_SUCCESS;
    }

    if (msg->hdr.type == PJ_STUN_REFRESH_REQUEST) {
	/*
	 * Handle REFRESH request
	 */
	pj_stun_lifetime_attr *lifetime;
	pj_stun_bandwidth_attr *bandwidth;

	/* Get LIFETIME attribute */
	lifetime = (pj_stun_lifetime_attr*)
		   pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_LIFETIME, 0);

	/* Get BANDWIDTH attribute */
	bandwidth = (pj_stun_bandwidth_attr*)
	            pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_BANDWIDTH, 0);

	/* TODO: process bandwidth */
	PJ_UNUSED_ARG(bandwidth);

	if (lifetime && lifetime->value==0) {
	    /*
	     * This is deallocation request.
	     */
	    alloc->relay.lifetime = 0;

	    /* Respond first */
	    send_reply_ok(alloc, rdata);

	    /* Shutdown allocation */
	    PJ_LOG(4,(alloc->obj_name,
		      "Client %s request to dealloc, shutting down",
		      alloc->info));

	    alloc_shutdown(alloc);

	} else {
	    /*
	     * This is a refresh request.
	     */

	    /* Update lifetime */
	    if (lifetime) {
		alloc->relay.lifetime = lifetime->value;
	    }

	    /* Update bandwidth */
	    // TODO:

	    /* Update expiration timer */
	    resched_timeout(alloc);

	    /* Send reply */
	    send_reply_ok(alloc, rdata);
	}

    } else if (msg->hdr.type == PJ_STUN_CHANNEL_BIND_REQUEST) {
	/*
	 * ChannelBind request.
	 */
	pj_stun_channel_number_attr *ch_attr;
	pj_stun_xor_peer_addr_attr *peer_attr;
	pj_turn_permission *p1, *p2;

	ch_attr = (pj_stun_channel_number_attr*)
		  pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_CHANNEL_NUMBER, 0);
	peer_attr = (pj_stun_xor_peer_addr_attr*)
		    pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_XOR_PEER_ADDR, 0);

	if (!ch_attr || !peer_attr) {
	    send_reply_err(alloc, rdata, PJ_TRUE,
			   PJ_STUN_SC_BAD_REQUEST, NULL);
	    return PJ_SUCCESS;
	}

	/* Find permission with the channel number */
	p1 = lookup_permission_by_chnum(alloc, PJ_STUN_GET_CH_NB(ch_attr->value));

	/* If permission is found, this is supposed to be a channel bind
	 * refresh. Make sure it's for the same peer.
	 */
	if (p1) {
	    if (pj_sockaddr_cmp(&p1->hkey.peer_addr, &peer_attr->sockaddr)) {
		/* Address mismatch. Send 400 */
		send_reply_err(alloc, rdata, PJ_TRUE,
			       PJ_STUN_SC_BAD_REQUEST,
			       "Peer address mismatch");
		return PJ_SUCCESS;
	    }

	    /* Refresh permission */
	    refresh_permission(p1);

	    /* Send response */
	    send_reply_ok(alloc, rdata);

	    /* Done */
	    return PJ_SUCCESS;
	}

	/* If permission is not found, create a new one. Make sure the peer
	 * has not alreadyy assigned with a channel number.
	 */
	p2 = lookup_permission_by_addr(alloc, &peer_attr->sockaddr,
				       pj_sockaddr_get_len(&peer_attr->sockaddr));
	if (p2 && p2->channel != PJ_TURN_INVALID_CHANNEL) {
	    send_reply_err(alloc, rdata, PJ_TRUE, PJ_STUN_SC_BAD_REQUEST,
			   "Peer address already assigned a channel number");
	    return PJ_SUCCESS;
	}

	/* Create permission if it doesn't exist */
	if (!p2) {
	    p2 = create_permission(alloc, &peer_attr->sockaddr,
				   pj_sockaddr_get_len(&peer_attr->sockaddr));
	    if (!p2)
		return PJ_SUCCESS;
	}

	/* Assign channel number to permission */
	p2->channel = PJ_STUN_GET_CH_NB(ch_attr->value);

	/* Register to hash table */
	pj_assert(sizeof(p2->channel)==2);
	pj_hash_set(alloc->pool, alloc->ch_table, &p2->channel,
		    sizeof(p2->channel), 0, p2);

	/* Update */
	refresh_permission(p2);

	/* Reply */
	send_reply_ok(alloc, rdata);

	return PJ_SUCCESS;

    } else if (msg->hdr.type == PJ_STUN_ALLOCATE_REQUEST) {

	/* Respond with 437 (section 6.3 turn-07) */
	send_reply_err(alloc, rdata, PJ_TRUE, PJ_STUN_SC_ALLOCATION_MISMATCH,
		       NULL);

    } else {

	/* Respond with Bad Request? */
	send_reply_err(alloc, rdata, PJ_TRUE, PJ_STUN_SC_BAD_REQUEST, NULL);

    }

    return PJ_SUCCESS;
}
static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
{
    const struct fuse_init_in *arg = (const struct fuse_init_in *) inarg;
    struct fuse_init_out outarg;
    struct fuse_ll *f = req->f;
    size_t bufsize = fuse_chan_bufsize(req->ch);

    (void) nodeid;
    if (f->debug) {
        fprintf(stderr, "INIT: %u.%u\n", arg->major, arg->minor);
        if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
            fprintf(stderr, "flags=0x%08x\n", arg->flags);
            fprintf(stderr, "max_readahead=0x%08x\n", arg->max_readahead);
        }
    }
    f->conn.proto_major = arg->major;
    f->conn.proto_minor = arg->minor;

    if (arg->major < 7) {
        fprintf(stderr, "fuse: unsupported protocol version: %u.%u\n",
                arg->major, arg->minor);
        fuse_reply_err(req, EPROTO);
        return;
    }

    if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
        if (f->conn.async_read)
            f->conn.async_read = arg->flags & FUSE_ASYNC_READ;
        if (arg->max_readahead < f->conn.max_readahead)
            f->conn.max_readahead = arg->max_readahead;
#ifdef POSIXACLS
	if (arg->flags & FUSE_DONT_MASK)
	    f->conn.capable |= FUSE_CAP_DONT_MASK;
#endif
    } else {
        f->conn.async_read = 0;
        f->conn.max_readahead = 0;
    }

    if (bufsize < FUSE_MIN_READ_BUFFER) {
        fprintf(stderr, "fuse: warning: buffer size too small: %zu\n",
                bufsize);
        bufsize = FUSE_MIN_READ_BUFFER;
    }

    bufsize -= 4096;
    if (bufsize < f->conn.max_write)
        f->conn.max_write = bufsize;

    f->got_init = 1;
    if (f->op.init)
        f->op.init(f->userdata, &f->conn);

    memset(&outarg, 0, sizeof(outarg));
    outarg.major = FUSE_KERNEL_VERSION;
	/*
	 * if POSIXACLS is not set, protocol 7.8 provides a good
	 * compatibility with older kernel modules.
	 * if POSIXACLS is set, we try to use protocol 7.12 supposed
	 * to have the ability to process the umask conditionnally,
	 * but, when using an older kernel module, we fallback to 7.8
	 */
#ifdef POSIXACLS
    if (arg->major > 7 || (arg->major == 7 && arg->minor >= 12))
	    outarg.minor = FUSE_KERNEL_MINOR_VERSION;
    else
	    outarg.minor = FUSE_KERNEL_MINOR_FALLBACK;
#else
    outarg.minor = FUSE_KERNEL_MINOR_VERSION;
#endif
    if (f->conn.async_read)
        outarg.flags |= FUSE_ASYNC_READ;
    if (f->op.getlk && f->op.setlk)
        outarg.flags |= FUSE_POSIX_LOCKS;
#ifdef POSIXACLS
    if (f->conn.want & FUSE_CAP_DONT_MASK)
	outarg.flags |= FUSE_DONT_MASK;
#endif
    outarg.flags |= FUSE_BIG_WRITES	 ;
    outarg.max_readahead = f->conn.max_readahead;
    outarg.max_write = f->conn.max_write;

    if (f->debug) {
        fprintf(stderr, "   INIT: %u.%u\n", outarg.major, outarg.minor);
        fprintf(stderr, "   flags=0x%08x\n", outarg.flags);
        fprintf(stderr, "   max_readahead=0x%08x\n", outarg.max_readahead);
        fprintf(stderr, "   max_write=0x%08x\n", outarg.max_write);
    }

    send_reply_ok(req, &outarg, arg->minor < 5 ? 8 : sizeof(outarg));
}