Ejemplo n.º 1
0
int
as_transaction_digest_validate(as_transaction *tr)
{
	cl_msg *msgp = tr->msgp;
	as_msg *m = &msgp->msg;

	cf_info(AS_PROTO, "digest compare succeeded");

	// Can only validate if we have two things to compare.
	as_msg_field *dfp = as_msg_field_get(m, AS_MSG_FIELD_TYPE_DIGEST_RIPE);
	if (dfp == 0) {
		cf_info(AS_PROTO, "no incoming protocol digest to validate");
		return(0);
	}
	if (as_msg_field_get_value_sz(dfp) != sizeof(cf_digest)) {
		cf_info(AS_PROTO, "sent bad digest size %d, can't validate",as_msg_field_get_value_sz(dfp));
		return(-1);
	}

	// Pull out the key and do the computation the same way as above.
	cf_digest computed;
	memset(&computed, 0, sizeof(cf_digest) );

	as_msg_field *kfp = as_msg_field_get(m, AS_MSG_FIELD_TYPE_KEY);
	if (!kfp) {
		cf_info(AS_PROTO, "received request with no key and no digest, validation failed");
		return(-1);
	}

	as_msg_field *sfp = as_msg_field_get(m, AS_MSG_FIELD_TYPE_SET);
	if (sfp == 0 || as_msg_field_get_value_sz(sfp) == 0) {
		cf_digest_compute(kfp->data, as_msg_field_get_value_sz(kfp), &tr->keyd);
	}
	else {
		cf_digest_compute2(sfp->data, as_msg_field_get_value_sz(sfp),
					kfp->data, as_msg_field_get_value_sz(kfp),
					&computed);
	}

	if (0 == memcmp(&computed, &tr->keyd, sizeof(computed))) {
		cf_info(AS_PROTO, "digest compare failed. wire: %"PRIx64" computed: %"PRIx64,
			*(uint64_t *)&tr->keyd, *(uint64_t *) &computed );
		return(-1);
	}

	cf_info(AS_PROTO, "digest compare succeeded");

	return(0);
}
Ejemplo n.º 2
0
void
as_msg_peek( cl_msg *msgp, proto_peek *peek )
{
	memset(peek, 0, sizeof(proto_peek));

	if (msgp == 0) return;

	if (msgp->proto.version != PROTO_VERSION ||
			msgp->proto.type != PROTO_TYPE_AS_MSG) {
		return;
	}

	as_msg *m = &msgp->msg;
	peek->info1 = m->info1;
	peek->info2 = m->info2;

	if (m->n_fields == 0) {
		return;
	}

	int n_fields = m->n_fields;
	bool swap = n_fields < 10 ? false : true;
	if (swap) n_fields = ntohs(n_fields);

	as_msg_field *kdfp = 0;
	as_msg_field *sfp = 0;
	as_msg_field *kfp = 0;
	as_msg_field *nfp = 0;

	// over all the fields
	as_msg_field *mf = (as_msg_field *) m->data;
	uint i = 0;
	for (; i < n_fields ; i++) {
		switch (mf->type) {
			case AS_MSG_FIELD_TYPE_DIGEST_RIPE:
				kdfp = mf;
				break;
			case AS_MSG_FIELD_TYPE_SET:
				sfp = mf;
				break;
			case AS_MSG_FIELD_TYPE_KEY:
				kfp = mf;
				break;
			case AS_MSG_FIELD_TYPE_NAMESPACE:
				nfp = mf;
				break;
		}
		if (swap)
			mf = as_msg_field_get_next_unswap(mf);
		else
			mf = as_msg_field_get_next(mf);
	}

	// find the key
	if (kdfp) {
		peek->keyd = *(cf_digest *)kdfp->data;
	}
	else {
		if (kfp) {
			if (sfp == 0 || as_msg_field_get_value_sz(sfp) == 0) {
				int ksz = swap ? as_msg_field_get_value_sz_unswap(kfp) : as_msg_field_get_value_sz(kfp);
				cf_digest_compute(kfp->data, ksz, &peek->keyd);
			}
			else {
				int ksz = swap ? as_msg_field_get_value_sz_unswap(kfp) : as_msg_field_get_value_sz(kfp);
				int ssz = swap ? as_msg_field_get_value_sz_unswap(sfp) : as_msg_field_get_value_sz(sfp);
				cf_digest_compute2(sfp->data, ssz, kfp->data, ksz, &peek->keyd);
			}
		}
	}

	// find the namespace
	if (nfp) {
		int nsz = swap ? as_msg_field_get_value_sz_unswap(nfp) : as_msg_field_get_value_sz(nfp);
		if (nsz > AS_ID_NAMESPACE_SZ) goto no_ns; // this should be illegal
		for (int i = 0; i < g_config.namespaces; i++) {
			tsvc_namespace_devices *ndev = &g_tsvc_devices_a[i];
			if (ndev->n_sz != nsz) continue;
			if (0 == memcmp(ndev->n_name, nfp->data, nsz)) {
				peek->ns_queue_offset = ndev->queue_offset;
				peek->ns_n_devices = ndev->n_devices;
				/*
				if (peek->info1 & AS_MSG_INFO1_READ) {
					cf_info(AS_PROTO, "read peek %s gives ofst %d n_dev %d",ndev->n_name,peek->ns_queue_offset,peek->ns_n_devices);
				} else {
					cf_info(AS_PROTO, "write peek %s gives ofst %d n_dev %d",ndev->n_name,peek->ns_queue_offset,peek->ns_n_devices);
				}
				*/
				break;
			}
		}
	}
no_ns:

	return;
}
Ejemplo n.º 3
0
/*
  The transaction prepare function fills out the fields of the tr structure,
  using the information in the msg structure. It also swaps the fields in the
  message header (which are originally in network byte order).

  Once the prepare function has been called on the transaction, the
  'preprocessed' flag is set and the transaction cannot be prepared again.
  Returns:
  0:  OK
  -1: General Error
  -2: Request received with no key
  -3: Request received with digest array
*/
int as_transaction_prepare(as_transaction *tr) {
	cl_msg *msgp = tr->msgp;
	as_msg *m = &msgp->msg;

#if defined(USE_SYSTEMTAP)
	uint64_t nodeid = g_config.self_node;
#endif

//	cf_assert(tr, AS_PROTO, CF_CRITICAL, "invalid transaction");

	void *limit = ((void *)m) + msgp->proto.sz;

	// Check processed flag.  It's a non-fatal error to call this function again.
	if( tr->preprocessed )
		return(0);

	if (0 != cf_digest_compare(&tr->keyd, &cf_digest_zero)) {
		cf_warning(AS_RW, "Internal inconsistency: transaction has keyd, but marked not swizzled");
	}

	as_msg_swap_header(m);
	if (0 != as_msg_swap_fields_and_ops(m, limit)) {
		cf_info(AS_PROTO, "msg swap field and ops returned error");
		return(-1);
	}

	if (m->n_fields>PROTO_NFIELDS_MAX_WARNING) {
		cf_info(AS_PROTO, "received too many n_fields! %d",m->n_fields);
    }

	// Set the transaction end time if available.
	if (m->transaction_ttl) {
//		cf_debug(AS_PROTO, "received non-zero transaction ttl: %d",m->transaction_ttl);
		tr->end_time = tr->start_time + ((uint64_t)m->transaction_ttl * 1000000);
	}

	// Set the preprocessed flag. All exits from here on out are considered
	// processed since the msg header has been swapped and the transaction
	// end time has been set.
	tr->preprocessed = true;
	tr->flag         = 0;
	UREQ_DATA_INIT(&tr->udata);
	as_msg_field *sfp = as_msg_field_get(m, AS_MSG_FIELD_TYPE_DIGEST_RIPE_ARRAY);
	if (sfp) {
		cf_debug(AS_PROTO, "received request with digest array, batch");
		return(-3);
	}

	// It's tempting to move this to the final return, but queries
	// actually escape in the if clause below ...
	ASD_TRANS_PREPARE(nodeid, (uint64_t) msgp, tr->trid);

	// Sent digest? Use!
	as_msg_field *dfp = as_msg_field_get(m, AS_MSG_FIELD_TYPE_DIGEST_RIPE);
	if (dfp) {
//		cf_detail(AS_PROTO, "transaction prepare: received sent digest\n");
		if (as_msg_field_get_value_sz(dfp) != sizeof(cf_digest)) {
			cf_info(AS_PROTO, "sent bad digest size %d, recomputing digest",as_msg_field_get_value_sz(dfp));
			goto Compute;
		}
		memcpy(&tr->keyd, dfp->data, sizeof(cf_digest));
	}
	// Not sent, so compute.
	else {
Compute:		;
		as_msg_field *kfp = as_msg_field_get(m, AS_MSG_FIELD_TYPE_KEY);
		if (!kfp) {
			cf_detail(AS_PROTO, "received request with no key, scan");
			return(-2);
		}
        if (as_msg_field_get_value_sz(kfp)> PROTO_FIELD_LENGTH_MAX) {
	        cf_info(AS_PROTO, "key field too big %d. Is it for real?",as_msg_field_get_value_sz(kfp));
        }

		as_msg_field *sfp = as_msg_field_get(m, AS_MSG_FIELD_TYPE_SET);
		if (sfp == 0 || as_msg_field_get_value_sz(sfp) == 0) {
			cf_digest_compute(kfp->data, as_msg_field_get_value_sz(kfp), &tr->keyd);
			// cf_info(AS_PROTO, "computing key for sz %d %"PRIx64" bytes %d %d %d %d",as_msg_field_get_value_sz(kfp),*(uint64_t *)&tr->keyd,kfp->data[0],kfp->data[1],kfp->data[2],kfp->data[3]);
		}
		else {
            if (as_msg_field_get_value_sz(sfp)> PROTO_FIELD_LENGTH_MAX) {
		        cf_info(AS_PROTO, "set field too big %d. Is this for real?",as_msg_field_get_value_sz(sfp));
            }
			cf_digest_compute2(sfp->data, as_msg_field_get_value_sz(sfp),
						kfp->data, as_msg_field_get_value_sz(kfp),
						&tr->keyd);
			// cf_info(AS_PROTO, "computing set with key for sz %d %"PRIx64" bytes %d %d",as_msg_field_get_value_sz(kfp),*(uint64_t *)&tr->keyd,kfp->data[0],kfp->data[1],kfp->data[2],kfp->data[3]);
		}
	}

	return(0);
}