Example #1
0
static bool delete_gid_cache(gid_t pgid)
{
	DATA_BLOB gid = data_blob_const(&pgid, sizeof(pgid));
	DATA_BLOB sid;
	if (!memcache_lookup(NULL, GID_SID_CACHE, gid, &sid)) {
		DEBUG(3, ("GID %d is not memcached!\n", (int)pgid));
		return false;
	}
	DEBUG(3, ("Delete mapping GID %d <-> %s from memcache\n", (int)pgid,
		  sid_string_dbg((struct dom_sid*)sid.data)));
	memcache_delete(NULL, SID_GID_CACHE, sid);
	memcache_delete(NULL, GID_SID_CACHE, gid);
	return true;
}
Example #2
0
static bool delete_getpwnam_cache(const char *username)
{
	DATA_BLOB name = data_blob_string_const_null(username);
	DEBUG(6, ("Delete passwd struct for %s from memcache\n",
		  username));
	memcache_delete(NULL, GETPWNAM_CACHE, name);
	return true;
}
Example #3
0
static bool delete_sid_cache(const struct dom_sid* psid)
{
	DATA_BLOB sid = data_blob_const(psid, ndr_size_dom_sid(psid, 0));
	DATA_BLOB id;
	if (memcache_lookup(NULL, SID_GID_CACHE, sid, &id)) {
		DEBUG(3, ("Delete mapping %s <-> GID %d from memcache\n",
			  sid_string_dbg(psid), *(int*)id.data));
		memcache_delete(NULL, SID_GID_CACHE, sid);
		memcache_delete(NULL, GID_SID_CACHE, id);
	} else if (memcache_lookup(NULL, SID_UID_CACHE, sid, &id)) {
		DEBUG(3, ("Delete mapping %s <-> UID %d from memcache\n",
			  sid_string_dbg(psid), *(int*)id.data));
		memcache_delete(NULL, SID_UID_CACHE, sid);
		memcache_delete(NULL, UID_SID_CACHE, id);
	} else {
		DEBUG(3, ("SID %s is not memcached!\n", sid_string_dbg(psid)));
		return false;
	}
	return true;
}
Example #4
0
static void share_mode_memcache_delete(struct share_mode_data *d)
{
	const DATA_BLOB key = memcache_key(&d->id);

	DEBUG(10,("deleting entry for file %s seq 0x%llu key %s\n",
		d->base_name,
		(unsigned long long) d->sequence_number,
		file_id_string(talloc_tos(), &d->id)));

	memcache_delete(NULL,
			SHARE_MODE_LOCK_CACHE,
			key);
}
Example #5
0
void stat_cache_delete(const char *name)
{
	char *lname = talloc_strdup_upper(talloc_tos(), name);

	if (!lname) {
		return;
	}
	DEBUG(10,("stat_cache_delete: deleting name [%s] -> %s\n",
			lname, name ));

	memcache_delete(smbd_memcache(), STAT_CACHE,
			data_blob_const(lname, talloc_get_size(lname)-1));
	TALLOC_FREE(lname);
}
Example #6
0
void
memcache_parse_req(struct msg *r)
{
    struct mbuf *b;
    uint8_t *p, *m;
    uint8_t ch;
    enum {
        SW_START,
        SW_REQ_TYPE,
        SW_SPACES_BEFORE_KEY,
        SW_KEY,
        SW_SPACES_BEFORE_KEYS,
        SW_SPACES_BEFORE_FLAGS,
        SW_FLAGS,
        SW_SPACES_BEFORE_EXPIRY,
        SW_EXPIRY,
        SW_SPACES_BEFORE_VLEN,
        SW_VLEN,
        SW_SPACES_BEFORE_CAS,
        SW_CAS,
        SW_RUNTO_VAL,
        SW_VAL,
        SW_SPACES_BEFORE_NUM,
        SW_NUM,
        SW_RUNTO_CRLF,
        SW_CRLF,
        SW_NOREPLY,
        SW_AFTER_NOREPLY,
        SW_ALMOST_DONE,
        SW_SENTINEL
    } state;

    state = r->state;
    b = STAILQ_LAST(&r->mhdr, mbuf, next);

    ASSERT(r->request);
    ASSERT(state >= SW_START && state < SW_SENTINEL);
    ASSERT(b != NULL);
    ASSERT(b->pos <= b->last);

    /* validate the parsing maker */
    ASSERT(r->pos != NULL);
    ASSERT(r->pos >= b->pos && r->pos <= b->last);

    for (p = r->pos; p < b->last; p++) {
        ch = *p;

        switch (state) {

        case SW_START:
            if (ch == ' ') {
                break;
            }

            if (!islower(ch)) {
                goto error;
            }

            /* req_start <- p; type_start <- p */
            r->token = p;
            state = SW_REQ_TYPE;

            break;

        case SW_REQ_TYPE:
            if (ch == ' ' || ch == CR) {
                /* type_end = p - 1 */
                m = r->token;
                r->token = NULL;
                r->type = MSG_UNKNOWN;

                switch (p - m) {

                case 3:
                    if (str4cmp(m, 'g', 'e', 't', ' ')) {
                        r->type = MSG_REQ_GET;
                        break;
                    }

                    if (str4cmp(m, 's', 'e', 't', ' ')) {
                        r->type = MSG_REQ_SET;
                        break;
                    }

                    if (str4cmp(m, 'a', 'd', 'd', ' ')) {
                        r->type = MSG_REQ_ADD;
                        break;
                    }

                    if (str4cmp(m, 'c', 'a', 's', ' ')) {
                        r->type = MSG_REQ_CAS;
                        break;
                    }

                    break;

                case 4:
                    if (str4cmp(m, 'g', 'e', 't', 's')) {
                        r->type = MSG_REQ_GETS;
                        break;
                    }

                    if (str4cmp(m, 'i', 'n', 'c', 'r')) {
                        r->type = MSG_REQ_INCR;
                        break;
                    }

                    if (str4cmp(m, 'd', 'e', 'c', 'r')) {
                        r->type = MSG_REQ_DECR;
                        break;
                    }

                    if (str4cmp(m, 'q', 'u', 'i', 't')) {
                        r->type = MSG_REQ_QUIT;
                        r->quit = 1;
                        break;
                    }

                    break;

                case 6:
                    if (str6cmp(m, 'a', 'p', 'p', 'e', 'n', 'd')) {
                        r->type = MSG_REQ_APPEND;
                        break;
                    }

                    if (str6cmp(m, 'd', 'e', 'l', 'e', 't', 'e')) {
                        r->type = MSG_REQ_DELETE;
                        break;
                    }

                    break;

                case 7:
                    if (str7cmp(m, 'p', 'r', 'e', 'p', 'e', 'n', 'd')) {
                        r->type = MSG_REQ_PREPEND;
                        break;
                    }

                    if (str7cmp(m, 'r', 'e', 'p', 'l', 'a', 'c', 'e')) {
                        r->type = MSG_REQ_REPLACE;
                        break;
                    }

                    if (str7cmp(m, 'v', 'e', 'r', 's', 'i', 'o', 'n')) {
                        r->type = MSG_REQ_VERSION;
                        break;
                    }

                    break;
                }

                if (memcache_key(r)) {
                    if (ch == CR) {
                        goto error;
                    }
                    state = SW_SPACES_BEFORE_KEY;
                } else if (memcache_quit(r) || memcache_version(r)) {
                    p = p - 1; /* go back by 1 byte */
                    state = SW_CRLF;
                } else {
                    goto error;
                }
            } else if (!islower(ch)) {
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_KEY:
            if (ch != ' ') {
                p = p - 1; /* go back by 1 byte */
                state = SW_KEY;
            }

            break;

        case SW_KEY:
            if (r->token == NULL) {
                r->token = p;
                r->key_start = p;
            }

            if (ch == ' ' || ch == CR) {
                if ((p - r->key_start) > MEMCACHE_MAX_KEY_LENGTH) {
                    log_error("parsed bad req %"PRIu64" of type %d with key "
                              "prefix '%.*s...' and length %d that exceeds "
                              "maximum key length", r->id, r->type, 16,
                              r->key_start, p - r->key_start);
                    goto error;
                }
                r->key_end = p;
                r->token = NULL;

                /* get next state */
                if (memcache_storage(r)) {
                    state = SW_SPACES_BEFORE_FLAGS;
                } else if (memcache_arithmetic(r)) {
                    state = SW_SPACES_BEFORE_NUM;
                } else if (memcache_delete(r)) {
                    state = SW_RUNTO_CRLF;
                } else if (memcache_retrieval(r)) {
                    state = SW_SPACES_BEFORE_KEYS;
                } else {
                    state = SW_RUNTO_CRLF;
                }

                if (ch == CR) {
                    if (memcache_storage(r) || memcache_arithmetic(r)) {
                        goto error;
                    }
                    p = p - 1; /* go back by 1 byte */
                }
            }

            break;

        case SW_SPACES_BEFORE_KEYS:
            ASSERT(memcache_retrieval(r));
            switch (ch) {
            case ' ':
                break;

            case CR:
                state = SW_ALMOST_DONE;
                break;

            default:
                r->token = p;
                goto fragment;
            }

            break;

        case SW_SPACES_BEFORE_FLAGS:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                p = p - 1; /* go back by 1 byte */
                state = SW_FLAGS;
            }

            break;

        case SW_FLAGS:
            if (r->token == NULL) {
                /* flags_start <- p */
                r->token = p;
                r->flags = 0;
            }

            if (isdigit(ch)) {
                r->flags = r->flags * 10 + (uint32_t)(ch - '0');
            } else if (ch == ' ') {
                /* flags_end <- p - 1 */
                r->token = NULL;
                state = SW_SPACES_BEFORE_EXPIRY;
            } else {
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_EXPIRY:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                p = p - 1; /* go back by 1 byte */
                state = SW_EXPIRY;
            }

            break;

        case SW_EXPIRY:
            if (r->token == NULL) {
                /* expiry_start <- p */
                r->token = p;
                r->expiry = 0;
            }

            if (isdigit(ch)) {
                r->expiry = r->expiry * 10 + (uint32_t)(ch - '0');
            } else if (ch == ' ') {
                /* expiry_end <- p - 1 */
                r->token = NULL;
                state = SW_SPACES_BEFORE_VLEN;
            } else {
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_VLEN:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                p = p - 1; /* go back by 1 byte */
                state = SW_VLEN;
            }

            break;

        case SW_VLEN:
            if (r->token == NULL) {
                /* vlen_start <- p */
                r->token = p;
                r->vlen = 0;
            }

            if (isdigit(ch)) {
                r->vlen = r->vlen * 10 + (uint32_t)(ch - '0');
            } else if (memcache_cas(r)) {
                if (ch != ' ') {
                    goto error;
                }
                /* vlen_end <- p - 1 */
                r->rvlen = r->vlen;
                p = p - 1; /* go back by 1 byte */
                r->token = NULL;
                state = SW_SPACES_BEFORE_CAS;
            } else if (ch == ' ' || ch == CR) {
                /* vlen_end <- p - 1 */
                r->rvlen = r->vlen;
                p = p - 1; /* go back by 1 byte */
                r->token = NULL;
                state = SW_RUNTO_CRLF;
            } else {
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_CAS:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                p = p - 1; /* go back by 1 byte */
                state = SW_CAS;
            }

            break;

        case SW_CAS:
            if (r->token == NULL) {
                /* cas_start <- p */
                r->token = p;
                r->cas = 0;
            }

            if (isdigit(ch)) {
                r->cas = r->cas * 10ULL + (uint64_t)(ch - '0');
            } else if (ch == ' ' || ch == CR) {
                /* cas_end <- p - 1 */
                p = p - 1; /* go back by 1 byte */
                r->token = NULL;
                state = SW_RUNTO_CRLF;
            } else {
                goto error;
            }

            break;

        case SW_RUNTO_VAL:
            switch (ch) {
            case LF:
                /* val_start <- p + 1 */
                state = SW_VAL;
                break;

            default:
                goto error;
            }

            break;

        case SW_VAL:
            if (r->value == NULL) {
                r->value = p;
            }
            m = p + r->rvlen;
            if (m >= b->last) {
                ASSERT(r->rvlen >= (uint32_t)(b->last - p));
                r->rvlen -= (uint32_t)(b->last - p);
                m = b->last - 1;
                p = m; /* move forward by vlen bytes */
                break;
            }
            switch (*m) {
            case CR:
                /* val_end <- p - 1 */
                p = m; /* move forward by vlen bytes */
                state = SW_ALMOST_DONE;
                break;

            default:
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_NUM:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                p = p - 1; /* go back by 1 byte */
                state = SW_NUM;
            }

            break;

        case SW_NUM:
            if (r->token == NULL) {
                /* num_start <- p */
                r->token = p;
                r->num = 0;
            }

            if (isdigit(ch)) {
                r->num = r->num * 10ULL + (uint64_t)(ch - '0');
            } else if (ch == ' ' || ch == CR) {
                r->token = NULL;
                /* num_end <- p - 1 */
                p = p - 1; /* go back by 1 byte */
                state = SW_RUNTO_CRLF;
            } else {
                goto error;
            }

            break;

        case SW_RUNTO_CRLF:
            switch (ch) {
            case ' ':
                break;

            case 'n':
                if (memcache_storage(r) || memcache_arithmetic(r) || memcache_delete(r)) {
                    p = p - 1; /* go back by 1 byte */
                    state = SW_NOREPLY;
                } else {
                    goto error;
                }

                break;

            case CR:
                if (memcache_storage(r)) {
                    state = SW_RUNTO_VAL;
                } else {
                    state = SW_ALMOST_DONE;
                }

                break;

            default:
                goto error;
            }

            break;

        case SW_NOREPLY:
            if (r->token == NULL) {
                /* noreply_start <- p */
                r->token = p;
            }

            switch (ch) {
            case ' ':
            case CR:
                m = r->token;
                if (((p - m) == 7) && str7cmp(m, 'n', 'o', 'r', 'e', 'p', 'l', 'y')) {
                    ASSERT(memcache_storage(r) || memcache_arithmetic(r) || memcache_delete(r));
                    r->token = NULL;
                    /* noreply_end <- p - 1 */
                    r->noreply = 1;
                    state = SW_AFTER_NOREPLY;
                    p = p - 1; /* go back by 1 byte */
                } else {
                    goto error;
                }
            }

            break;

        case SW_AFTER_NOREPLY:
            switch (ch) {
            case ' ':
                break;

            case CR:
                if (memcache_storage(r)) {
                    state = SW_RUNTO_VAL;
                } else {
                    state = SW_ALMOST_DONE;
                }
                break;

            default:
                goto error;
            }

            break;

        case SW_CRLF:
            switch (ch) {
            case ' ':
                break;

            case CR:
                state = SW_ALMOST_DONE;
                break;

            default:
                goto error;
            }

            break;

        case SW_ALMOST_DONE:
            switch (ch) {
            case LF:
                /* req_end <- p */
                goto done;

            default:
                goto error;
            }

            break;

        case SW_SENTINEL:
        default:
            NOT_REACHED();
            break;

        }
    }

    /*
     * At this point, buffer from b->pos to b->last has been parsed completely
     * but we haven't been able to reach to any conclusion. Normally, this
     * means that we have to parse again starting from the state we are in
     * after more data has been read. The newly read data is either read into
     * a new mbuf, if existing mbuf is full (b->last == b->end) or into the
     * existing mbuf.
     *
     * The only exception to this is when the existing mbuf is full (b->last
     * is at b->end) and token marker is set, which means that we have to
     * copy the partial token into a new mbuf and parse again with more data
     * read into new mbuf.
     */
    ASSERT(p == b->last);
    r->pos = p;
    r->state = state;

    if (b->last == b->end && r->token != NULL) {
        r->pos = r->token;
        r->token = NULL;
        r->result = MSG_PARSE_REPAIR;
    } else {
        r->result = MSG_PARSE_AGAIN;
    }

    log_hexdump(LOG_VERB, b->pos, mbuf_length(b), "parsed req %"PRIu64" res %d "
                "type %d state %d rpos %d of %d", r->id, r->result, r->type,
                r->state, r->pos - b->pos, b->last - b->pos);
    return;

fragment:
    ASSERT(p != b->last);
    ASSERT(r->token != NULL);
    r->pos = r->token;
    r->token = NULL;
    r->state = state;
    r->result = MSG_PARSE_FRAGMENT;

    log_hexdump(LOG_VERB, b->pos, mbuf_length(b), "parsed req %"PRIu64" res %d "
                "type %d state %d rpos %d of %d", r->id, r->result, r->type,
                r->state, r->pos - b->pos, b->last - b->pos);
    return;

done:
    ASSERT(r->type > MSG_UNKNOWN && r->type < MSG_SENTINEL);
    r->pos = p + 1;
    ASSERT(r->pos <= b->last);
    r->state = SW_START;
    r->result = MSG_PARSE_OK;

    log_hexdump(LOG_VERB, b->pos, mbuf_length(b), "parsed req %"PRIu64" res %d "
                "type %d state %d rpos %d of %d", r->id, r->result, r->type,
                r->state, r->pos - b->pos, b->last - b->pos);
    return;

error:
    r->result = MSG_PARSE_ERROR;
    r->state = state;
    errno = EINVAL;

    log_hexdump(LOG_INFO, b->pos, mbuf_length(b), "parsed bad req %"PRIu64" "
                "res %d type %d state %d", r->id, r->result, r->type,
                r->state);
}
Example #7
0
static ssize_t memcacheParseReq(struct memcacheProcData *r, struct slice *s)
{
    char *m;
    char ch;
    size_t command_len;

    size_t pos = 0;
    uint64_t left = 0;
    struct slice val_s;
    enum reqStage state = r->stage;
    r->token_pos = 0;
    while (pos < s->len) {
        ch = s->data[pos];

        switch (state) {
        case SW_START:
            if (!islower(ch)) {
                goto error;
            }

            r->token_pos = pos;
            state = SW_REQ_TYPE;
            break;

        case SW_REQ_TYPE:
            if (ch == ' ' || ch == CR) {
                r->type = UNKNOWN;
                if (wstrlen(r->command)) {
                    r->command = wstrCatLen(r->command, (char *)&s->data[r->token_pos], pos);
                    command_len = wstrlen(r->command);
                    m = (char*)&r->command;
                } else {
                    command_len = pos - r->token_pos;
                    m = (char*)&s->data[r->token_pos];
                }

                switch (command_len) {

                case 3:
                    if (str4icmp(m, 'g', 'e', 't', ' ')) {
                        r->type = REQ_MC_GET;
                        break;
                    }

                    if (str4icmp(m, 's', 'e', 't', ' ')) {
                        r->type = REQ_MC_SET;
                        break;
                    }

                    if (str4icmp(m, 'a', 'd', 'd', ' ')) {
                        r->type = REQ_MC_ADD;
                        break;
                    }

                    if (str4icmp(m, 'c', 'a', 's', ' ')) {
                        r->type = REQ_MC_CAS;
                        break;
                    }

                    break;

                case 4:
                    if (str4icmp(m, 'g', 'e', 't', 's')) {
                        r->type = REQ_MC_GETS;
                        break;
                    }

                    if (str4icmp(m, 'i', 'n', 'c', 'r')) {
                        r->type = REQ_MC_INCR;
                        break;
                    }

                    if (str4icmp(m, 'd', 'e', 'c', 'r')) {
                        r->type = REQ_MC_DECR;
                        break;
                    }

                    if (str4icmp(m, 'q', 'u', 'i', 't')) {
                        r->type = REQ_MC_QUIT;
                        r->quit = 1;
                        break;
                    }

                    break;

                case 6:
                    if (str6icmp(m, 'a', 'p', 'p', 'e', 'n', 'd')) {
                        r->type = REQ_MC_APPEND;
                        break;
                    }

                    if (str6icmp(m, 'd', 'e', 'l', 'e', 't', 'e')) {
                        r->type = REQ_MC_DELETE;
                        break;
                    }

                    break;

                case 7:
                    if (str7icmp(m, 'p', 'r', 'e', 'p', 'e', 'n', 'd')) {
                        r->type = REQ_MC_PREPEND;
                        break;
                    }

                    if (str7icmp(m, 'r', 'e', 'p', 'l', 'a', 'c', 'e')) {
                        r->type = REQ_MC_REPLACE;
                        break;
                    }

                    break;
                }

                switch (r->type) {
                case REQ_MC_GET:
                case REQ_MC_GETS:
                case REQ_MC_DELETE:
                case REQ_MC_CAS:
                case REQ_MC_SET:
                case REQ_MC_ADD:
                case REQ_MC_REPLACE:
                case REQ_MC_APPEND:
                case REQ_MC_PREPEND:
                case REQ_MC_INCR:
                case REQ_MC_DECR:
                    if (ch == CR) {
                        goto error;
                    }
                    state = SW_SPACES_BEFORE_KEY;
                    break;

                case REQ_MC_QUIT:
                    pos--; /* go back by 1 byte */
                    state = SW_CRLF;
                    break;

                case UNKNOWN:
                    goto error;

                default:
                    ASSERT(0);
                }
            } else if (!islower(ch)) {
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_KEY:
            if (ch != ' ') {
                pos--; /* go back by 1 byte */
                r->token_pos = -1;
                state = SW_KEY;
            }
            break;

        case SW_KEY:
            if (r->token_pos == -1) {
                r->token_pos = pos;
            }
            if (ch == ' ' || ch == CR) {
                if (wstrlen(r->key) + (pos - r->token_pos) > MEMCACHE_MAX_KEY_LENGTH) {
                    wheatLog(WHEAT_WARNING,
                             "parsed bad type %d with key prefix '%d' and length %d that exceeds "
                             "maximum key length", r->type, r->token_pos, pos);
                    goto error;
                }

                r->key = wstrCatLen(r->key, (char*)&s->data[r->token_pos], pos - r->token_pos);
                arrayPush(r->keys, &r->key);
                r->key = wstrNewLen(NULL, 64);

                r->token_pos = -1;

                /* get next state */
                if (memcache_storage(r)) {
                    state = SW_SPACES_BEFORE_FLAGS;
                } else if (memcache_arithmetic(r)) {
                    state = SW_SPACES_BEFORE_NUM;
                } else if (memcache_delete(r)) {
                    // whether exist delay time
                    if (ch == ' ')
                        state = SW_SPACES_BEFORE_NUM;
                    else
                        state = SW_RUNTO_CRLF;
                } else if (memcache_retrieval(r)) {
                    state = SW_SPACES_BEFORE_KEYS;
                } else {
                    state = SW_RUNTO_CRLF;
                }

                if (ch == CR) {
                    if (memcache_storage(r) || memcache_arithmetic(r)) {
                        goto error;
                    }
                    pos--; /* go back by 1 byte */
                }
            }

            break;

        case SW_SPACES_BEFORE_KEYS:
            ASSERT(memcache_retrieval(r));
            switch (ch) {
            case ' ':
                break;

            case CR:
                state = SW_ALMOST_DONE;
                break;

            default:
                r->token_pos = -1;
                pos--; /* go back by 1 byte */
                state = SW_KEY;
            }

            break;

        case SW_SPACES_BEFORE_FLAGS:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                r->flag = ch - '0';
                state = SW_FLAGS;
            }

            break;

        case SW_FLAGS:
            if (isdigit(ch)) {
                r->flag = r->flag * 10 + (ch - '0');
            } else if (ch == ' ') {
                state = SW_SPACES_BEFORE_EXPIRY;
            } else {
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_EXPIRY:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                /* expiry_start <- p; expiry <- ch - '0' */
                r->expire = ch - '0';
                state = SW_EXPIRY;
            }

            break;

        case SW_EXPIRY:
            if (isdigit(ch)) {
                r->expire = r->expire * 10 + (ch - '0');
            } else if (ch == ' ') {
                state = SW_SPACES_BEFORE_VLEN;
            } else {
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_VLEN:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                /* vlen_start <- p */
                r->vlen = ch - '0';
                state = SW_VLEN;
            }

            break;

        case SW_VLEN:
            if (isdigit(ch)) {
                r->vlen = r->vlen * 10 + (uint32_t)(ch - '0');
            } else if (memcache_cas(r)) {
                if (ch != ' ') {
                    goto error;
                }
                pos--; /* go back by 1 byte */
                state = SW_SPACES_BEFORE_CAS;
            } else if (ch == ' ' || ch == CR) {
                pos--; /* go back by 1 byte */
                state = SW_RUNTO_CRLF;
            } else {
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_CAS:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                /* cas_start <- p; cas <- ch - '0' */
                r->cas = ch - '0';
                state = SW_CAS;
            }

            break;

        case SW_CAS:
            if (isdigit(ch)) {
                r->cas = r->cas * 10 + (ch - '0');
            } else if (ch == ' ' || ch == CR) {
                pos--; /* go back by 1 byte */
                state = SW_RUNTO_CRLF;
            } else {
                goto error;
            }

            break;


        case SW_RUNTO_VAL:
            switch (ch) {
            case LF:
                /* val_start <- p + 1 */
                state = SW_VAL;
                r->vlen_left = r->vlen;
                break;

            default:
                goto error;
            }

            break;

        case SW_VAL:
            if (r->vlen_left) {
                left = (s->len - pos) >= r->vlen ? (r->vlen) : (s->len-pos);
                val_s.len = left;
                val_s.data = &s->data[pos];
                arrayPush(r->vals, &val_s);
                r->vlen_left -= left;
                pos += left;
            }
            switch (s->data[pos]) {
            case CR:
                state = SW_ALMOST_DONE;
                break;

            default:
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_NUM:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                r->num = ch - '0';
                state = SW_NUM;
            }

            break;

        case SW_NUM:
            if (isdigit(ch)) {
                r->num = r->num * 10 + ch - '0';
            } else if (ch == ' ' || ch == CR) {
                pos--; /* go back by 1 byte */
                state = SW_RUNTO_CRLF;
            } else {
                goto error;
            }

            break;

        case SW_RUNTO_CRLF:
            switch (ch) {
            case ' ':
                break;

            case 'n':
                if (memcache_storage(r) || memcache_arithmetic(r) || memcache_delete(r)) {
                    state = SW_NOREPLY;
                    r->noreply_banner = wstrNewLen(NULL, 8);
                    r->token_pos = pos;
                } else {
                    goto error;
                }

                break;

            case CR:
                if (memcache_storage(r)) {
                    state = SW_RUNTO_VAL;
                } else {
                    state = SW_ALMOST_DONE;
                }

                break;

            default:
                goto error;
            }

            break;

        case SW_NOREPLY:
            switch (ch) {
            case ' ':
            case CR:
                r->noreply_banner = wstrCatLen(r->noreply_banner, (char*)&s->data[r->token_pos], pos - r->token_pos);
                if (str7icmp(r->noreply_banner, 'n', 'o', 'r', 'e', 'p', 'l', 'y')) {
                    ASSERT(memcache_storage(r) || memcache_arithmetic(r) || memcache_delete(r));
                    /* noreply_end <- p - 1 */
                    r->noreply = 1;
                    state = SW_AFTER_NOREPLY;
                    pos--; /* go back by 1 byte */
                } else {
                    goto error;
                }
            }

            break;

        case SW_AFTER_NOREPLY:
            switch (ch) {
            case ' ':
                break;

            case CR:
                if (memcache_storage(r)) {
                    state = SW_RUNTO_VAL;
                } else {
                    state = SW_ALMOST_DONE;
                }
                break;

            default:
                goto error;
            }

            break;

        case SW_CRLF:
            switch (ch) {
            case ' ':
                break;

            case CR:
                state = SW_ALMOST_DONE;
                break;

            default:
                goto error;
            }

            break;

        case SW_ALMOST_DONE:
            switch (ch) {
            case LF:
                /* req_end <- p */
                pos++;
                goto done;

            default:
                goto error;
            }

            break;

        case SW_SENTINEL:
        default:
            ASSERT(0);
            break;

        }
        pos++;
    }

    if (state == SW_REQ_TYPE) {
        r->command = wstrCatLen(r->command, (char*)&s->data[r->token_pos], pos - r->token_pos);
    } else if (state == SW_KEY) {
        r->key = wstrCatLen(r->key, (char*)&s->data[r->token_pos], pos - r->token_pos);
    } else if (state == SW_NOREPLY) {
        r->noreply_banner = wstrCatLen(r->noreply_banner, (char*)&s->data[r->token_pos], pos - r->token_pos);
    }

done:
    r->stage = state;
    wheatLog(WHEAT_DEBUG, "parsed successfully type %d state %d", r->type, r->stage);
    return pos;

error:
    wheatLog(WHEAT_DEBUG, "parsed failed type %d state %d: %s", r->type, r->stage,
             s->data);
    return -1;
}
Example #8
0
bool stat_cache_lookup(connection_struct *conn,
			bool posix_paths,
			char **pp_name,
			char **pp_dirpath,
			char **pp_start,
			SMB_STRUCT_STAT *pst)
{
	char *chk_name;
	size_t namelen;
	bool sizechanged = False;
	unsigned int num_components = 0;
	char *translated_path;
	size_t translated_path_length;
	DATA_BLOB data_val;
	char *name;
	TALLOC_CTX *ctx = talloc_tos();
	struct smb_filename smb_fname;
	int ret;

	*pp_dirpath = NULL;
	*pp_start = *pp_name;

	if (!lp_stat_cache()) {
		return False;
	}

	name = *pp_name;
	namelen = strlen(name);

	DO_PROFILE_INC(statcache_lookups);

	/*
	 * Don't lookup trivial valid directory entries.
	 */
	if ((*name == '\0') || ISDOT(name) || ISDOTDOT(name)) {
		return False;
	}

	if (conn->case_sensitive) {
		chk_name = talloc_strdup(ctx,name);
		if (!chk_name) {
			DEBUG(0, ("stat_cache_lookup: strdup failed!\n"));
			return False;
		}

	} else {
		chk_name = talloc_strdup_upper(ctx,name);
		if (!chk_name) {
			DEBUG(0, ("stat_cache_lookup: talloc_strdup_upper failed!\n"));
			return False;
		}

		/*
		 * In some language encodings the length changes
		 * if we uppercase. We need to treat this differently
		 * below.
		 */
		if (strlen(chk_name) != namelen) {
			sizechanged = True;
		}
	}

	while (1) {
		char *sp;

		data_val = data_blob_null;

		if (memcache_lookup(
			    smbd_memcache(), STAT_CACHE,
			    data_blob_const(chk_name, strlen(chk_name)),
			    &data_val)) {
			break;
		}

		DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n",
				chk_name ));
		/*
		 * Didn't find it - remove last component for next try.
		 */
		if (!(sp = strrchr_m(chk_name, '/'))) {
			/*
			 * We reached the end of the name - no match.
			 */
			DO_PROFILE_INC(statcache_misses);
			TALLOC_FREE(chk_name);
			return False;
		}

		*sp = '\0';

		/*
		 * Count the number of times we have done this, we'll
		 * need it when reconstructing the string.
		 */

		if (sizechanged) {
			num_components++;
		}

		if ((*chk_name == '\0')
		    || ISDOT(chk_name) || ISDOTDOT(chk_name)) {
			DO_PROFILE_INC(statcache_misses);
			TALLOC_FREE(chk_name);
			return False;
		}
	}

	translated_path = talloc_strdup(ctx,(char *)data_val.data);
	if (!translated_path) {
		smb_panic("talloc failed");
	}
	translated_path_length = data_val.length - 1;

	DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] "
		  "-> [%s]\n", chk_name, translated_path ));
	DO_PROFILE_INC(statcache_hits);

	ZERO_STRUCT(smb_fname);
	smb_fname.base_name = translated_path;

	if (posix_paths) {
		ret = SMB_VFS_LSTAT(conn, &smb_fname);
	} else {
		ret = SMB_VFS_STAT(conn, &smb_fname);
	}

	if (ret != 0) {
		/* Discard this entry - it doesn't exist in the filesystem. */
		memcache_delete(smbd_memcache(), STAT_CACHE,
				data_blob_const(chk_name, strlen(chk_name)));
		TALLOC_FREE(chk_name);
		TALLOC_FREE(translated_path);
		return False;
	}
	*pst = smb_fname.st;

	if (!sizechanged) {
		memcpy(*pp_name, translated_path,
		       MIN(namelen, translated_path_length));
	} else {
		if (num_components == 0) {
			name = talloc_strndup(ctx, translated_path,
					   translated_path_length);
		} else {
			char *sp;

			sp = strnrchr_m(name, '/', num_components);
			if (sp) {
				name = talloc_asprintf(ctx,"%.*s%s",
					 (int)translated_path_length,
					 translated_path, sp);
			} else {
				name = talloc_strndup(ctx,
						translated_path,
						translated_path_length);
			}
		}
		if (name == NULL) {
			/*
			 * TODO: Get us out of here with a real error message
			 */
			smb_panic("talloc failed");
		}
		TALLOC_FREE(*pp_name);
		*pp_name = name;
	}


	/* set pointer for 'where to start' on fixing the rest of the name */
	*pp_start = &name[translated_path_length];
	if (**pp_start == '/') {
		++*pp_start;
	}

	*pp_dirpath = translated_path;
	TALLOC_FREE(chk_name);
	return (namelen == translated_path_length);
}
Example #9
0
static enum ndr_err_code get_blob_sequence_number(DATA_BLOB *blob,
						uint64_t *pseq)
{
	struct ndr_pull ndr = {.data = blob->data, .data_size = blob->length};
	NDR_CHECK(ndr_pull_hyper(&ndr, NDR_SCALARS, pseq));
	return NDR_ERR_SUCCESS;
}

static int share_mode_data_nofree_destructor(struct share_mode_data *d)
{
	return -1;
}

static struct share_mode_data *share_mode_memcache_fetch(TALLOC_CTX *mem_ctx,
					const TDB_DATA id_key,
					DATA_BLOB *blob)
{
	enum ndr_err_code ndr_err;
	struct share_mode_data *d;
	uint64_t sequence_number;
	void *ptr;
	struct file_id id;
	DATA_BLOB key;

	/* Ensure this is a locking_key record. */
	if (id_key.dsize != sizeof(id)) {
		return NULL;
	}

	memcpy(&id, id_key.dptr, id_key.dsize);
	key = memcache_key(&id);

	ptr = memcache_lookup_talloc(NULL,
			SHARE_MODE_LOCK_CACHE,
			key);
	if (ptr == NULL) {
		DEBUG(10,("failed to find entry for key %s\n",
			file_id_string(mem_ctx, &id)));
		return NULL;
	}
	/* sequence number key is at start of blob. */
	ndr_err = get_blob_sequence_number(blob, &sequence_number);
	if (ndr_err != NDR_ERR_SUCCESS) {
		/* Bad blob. Remove entry. */
		DEBUG(10,("bad blob %u key %s\n",
			(unsigned int)ndr_err,
			file_id_string(mem_ctx, &id)));
		memcache_delete(NULL,
			SHARE_MODE_LOCK_CACHE,
			key);
		return NULL;
	}

	d = (struct share_mode_data *)ptr;
	if (d->sequence_number != sequence_number) {
		DEBUG(10,("seq changed (cached 0x%llu) (new 0x%llu) "
			"for key %s\n",
			(unsigned long long)d->sequence_number,
			(unsigned long long)sequence_number,
			file_id_string(mem_ctx, &id)));
		/* Cache out of date. Remove entry. */
		memcache_delete(NULL,
			SHARE_MODE_LOCK_CACHE,
			key);
		return NULL;
	}

	/* Move onto mem_ctx. */
	d = talloc_move(mem_ctx, &ptr);

	/*
	 * Now we own d, prevent the cache from freeing it
	 * when we delete the entry.
	 */
	talloc_set_destructor(d, share_mode_data_nofree_destructor);

	/* Remove from the cache. We own it now. */
	memcache_delete(NULL,
			SHARE_MODE_LOCK_CACHE,
			key);

	/* And reset the destructor to none. */
	talloc_set_destructor(d, NULL);

	DEBUG(10,("fetched entry for file %s seq 0x%llu key %s\n",
		d->base_name,
		(unsigned long long)d->sequence_number,
		file_id_string(mem_ctx, &id)));

	return d;
}

/*******************************************************************
 Get all share mode entries for a dev/inode pair.
********************************************************************/

static struct share_mode_data *parse_share_modes(TALLOC_CTX *mem_ctx,
						const TDB_DATA key,
						const TDB_DATA dbuf)
{
	struct share_mode_data *d;
	enum ndr_err_code ndr_err;
	uint32_t i;
	DATA_BLOB blob;

	blob.data = dbuf.dptr;
	blob.length = dbuf.dsize;

	/* See if we already have a cached copy of this key. */
	d = share_mode_memcache_fetch(mem_ctx, key, &blob);
	if (d != NULL) {
		return d;
	}

	d = talloc(mem_ctx, struct share_mode_data);
	if (d == NULL) {
		DEBUG(0, ("talloc failed\n"));
		goto fail;
	}

	ndr_err = ndr_pull_struct_blob_all(
		&blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		DEBUG(1, ("ndr_pull_share_mode_lock failed: %s\n",
			  ndr_errstr(ndr_err)));
		goto fail;
	}

	/*
	 * Initialize the values that are [skip] in the idl. The NDR code does
	 * not initialize them.
	 */

	for (i=0; i<d->num_share_modes; i++) {
		struct share_mode_entry *e = &d->share_modes[i];

		e->stale = false;
		e->lease = NULL;
		if (e->op_type != LEASE_OPLOCK) {
			continue;
		}
		if (e->lease_idx >= d->num_leases) {
			continue;
		}
		e->lease = &d->leases[e->lease_idx];
	}
	d->modified = false;
	d->fresh = false;

	if (DEBUGLEVEL >= 10) {
		DEBUG(10, ("parse_share_modes:\n"));
		NDR_PRINT_DEBUG(share_mode_data, d);
	}

	return d;
fail:
	TALLOC_FREE(d);
	return NULL;
}

/*******************************************************************
 Create a storable data blob from a modified share_mode_data struct.
********************************************************************/

static TDB_DATA unparse_share_modes(struct share_mode_data *d)
{
	DATA_BLOB blob;
	enum ndr_err_code ndr_err;

	if (DEBUGLEVEL >= 10) {
		DEBUG(10, ("unparse_share_modes:\n"));
		NDR_PRINT_DEBUG(share_mode_data, d);
	}

	share_mode_memcache_delete(d);

	/* Update the sequence number. */
	d->sequence_number += 1;

	remove_stale_share_mode_entries(d);

	if (d->num_share_modes == 0) {
		DEBUG(10, ("No used share mode found\n"));
		return make_tdb_data(NULL, 0);
	}

	ndr_err = ndr_push_struct_blob(
		&blob, d, d, (ndr_push_flags_fn_t)ndr_push_share_mode_data);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		smb_panic("ndr_push_share_mode_lock failed");
	}

	return make_tdb_data(blob.data, blob.length);
}