Example #1
0
static void
kvp_send_key(struct work_struct *dummy)
{
    struct cn_msg *msg;
    struct hv_kvp_msg *message;
    struct hv_kvp_msg *in_msg;
    __u8 operation = kvp_transaction.kvp_msg->kvp_hdr.operation;
    __u8 pool = kvp_transaction.kvp_msg->kvp_hdr.pool;
    __u32 val32;
    __u64 val64;

    msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC);
    if (!msg)
        return;

    msg->id.idx =  CN_KVP_IDX;
    msg->id.val = CN_KVP_VAL;

    message = (struct hv_kvp_msg *)msg->data;
    message->kvp_hdr.operation = operation;
    message->kvp_hdr.pool = pool;
    in_msg = kvp_transaction.kvp_msg;

    /*
     * The key/value strings sent from the host are encoded in
     * in utf16; convert it to utf8 strings.
     * The host assures us that the utf16 strings will not exceed
     * the max lengths specified. We will however, reserve room
     * for the string terminating character - in the utf16s_utf8s()
     * function we limit the size of the buffer where the converted
     * string is placed to HV_KVP_EXCHANGE_MAX_*_SIZE -1 to gaurantee
     * that the strings can be properly terminated!
     */

    switch (message->kvp_hdr.operation) {
    case KVP_OP_SET_IP_INFO:
        process_ib_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO);
        break;
    case KVP_OP_GET_IP_INFO:
        process_ib_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO);
        break;
    case KVP_OP_SET:
        switch (in_msg->body.kvp_set.data.value_type) {
        case REG_SZ:
            /*
             * The value is a string - utf16 encoding.
             */
            message->body.kvp_set.data.value_size =
                utf16s_to_utf8s(
                    (wchar_t *)in_msg->body.kvp_set.data.value,
                    in_msg->body.kvp_set.data.value_size,
                    UTF16_LITTLE_ENDIAN,
                    message->body.kvp_set.data.value,
                    HV_KVP_EXCHANGE_MAX_VALUE_SIZE - 1) + 1;
            break;

        case REG_U32:
            /*
             * The value is a 32 bit scalar.
             * We save this as a utf8 string.
             */
            val32 = in_msg->body.kvp_set.data.value_u32;
            message->body.kvp_set.data.value_size =
                sprintf(message->body.kvp_set.data.value,
                        "%d", val32) + 1;
            break;

        case REG_U64:
            /*
             * The value is a 64 bit scalar.
             * We save this as a utf8 string.
             */
            val64 = in_msg->body.kvp_set.data.value_u64;
            message->body.kvp_set.data.value_size =
                sprintf(message->body.kvp_set.data.value,
                        "%llu", val64) + 1;
            break;

        }
    case KVP_OP_GET:
        message->body.kvp_set.data.key_size =
            utf16s_to_utf8s(
                (wchar_t *)in_msg->body.kvp_set.data.key,
                in_msg->body.kvp_set.data.key_size,
                UTF16_LITTLE_ENDIAN,
                message->body.kvp_set.data.key,
                HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
        break;

    case KVP_OP_DELETE:
        message->body.kvp_delete.key_size =
            utf16s_to_utf8s(
                (wchar_t *)in_msg->body.kvp_delete.key,
                in_msg->body.kvp_delete.key_size,
                UTF16_LITTLE_ENDIAN,
                message->body.kvp_delete.key,
                HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
        break;

    case KVP_OP_ENUMERATE:
        message->body.kvp_enum_data.index =
            in_msg->body.kvp_enum_data.index;
        break;
    }

    msg->len = sizeof(struct hv_kvp_msg);
    cn_netlink_send(msg, 0, GFP_ATOMIC);
    kfree(msg);

    return;
}
Example #2
0
static void
kvp_send_key(struct work_struct *dummy)
{
	struct hv_kvp_msg *message;
	struct hv_kvp_msg *in_msg;
	__u8 operation = kvp_transaction.kvp_msg->kvp_hdr.operation;
	__u8 pool = kvp_transaction.kvp_msg->kvp_hdr.pool;
	__u32 val32;
	__u64 val64;
	int rc;

	/* The transaction state is wrong. */
	if (kvp_transaction.state != HVUTIL_HOSTMSG_RECEIVED)
		return;

	message = kzalloc(sizeof(*message), GFP_KERNEL);
	if (!message)
		return;

	message->kvp_hdr.operation = operation;
	message->kvp_hdr.pool = pool;
	in_msg = kvp_transaction.kvp_msg;

	/*
	 * The key/value strings sent from the host are encoded in
	 * in utf16; convert it to utf8 strings.
	 * The host assures us that the utf16 strings will not exceed
	 * the max lengths specified. We will however, reserve room
	 * for the string terminating character - in the utf16s_utf8s()
	 * function we limit the size of the buffer where the converted
	 * string is placed to HV_KVP_EXCHANGE_MAX_*_SIZE -1 to gaurantee
	 * that the strings can be properly terminated!
	 */

	switch (message->kvp_hdr.operation) {
	case KVP_OP_SET_IP_INFO:
		process_ib_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO);
		break;
	case KVP_OP_GET_IP_INFO:
		process_ib_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO);
		break;
	case KVP_OP_SET:
		switch (in_msg->body.kvp_set.data.value_type) {
		case REG_SZ:
			/*
			 * The value is a string - utf16 encoding.
			 */
			message->body.kvp_set.data.value_size =
				utf16s_to_utf8s(
				(wchar_t *)in_msg->body.kvp_set.data.value,
				in_msg->body.kvp_set.data.value_size,
				UTF16_LITTLE_ENDIAN,
				message->body.kvp_set.data.value,
				HV_KVP_EXCHANGE_MAX_VALUE_SIZE - 1) + 1;
				break;

		case REG_U32:
			/*
			 * The value is a 32 bit scalar.
			 * We save this as a utf8 string.
			 */
			val32 = in_msg->body.kvp_set.data.value_u32;
			message->body.kvp_set.data.value_size =
				sprintf(message->body.kvp_set.data.value,
					"%d", val32) + 1;
			break;

		case REG_U64:
			/*
			 * The value is a 64 bit scalar.
			 * We save this as a utf8 string.
			 */
			val64 = in_msg->body.kvp_set.data.value_u64;
			message->body.kvp_set.data.value_size =
				sprintf(message->body.kvp_set.data.value,
					"%llu", val64) + 1;
			break;

		}
	case KVP_OP_GET:
		message->body.kvp_set.data.key_size =
			utf16s_to_utf8s(
			(wchar_t *)in_msg->body.kvp_set.data.key,
			in_msg->body.kvp_set.data.key_size,
			UTF16_LITTLE_ENDIAN,
			message->body.kvp_set.data.key,
			HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
			break;

	case KVP_OP_DELETE:
		message->body.kvp_delete.key_size =
			utf16s_to_utf8s(
			(wchar_t *)in_msg->body.kvp_delete.key,
			in_msg->body.kvp_delete.key_size,
			UTF16_LITTLE_ENDIAN,
			message->body.kvp_delete.key,
			HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
			break;

	case KVP_OP_ENUMERATE:
		message->body.kvp_enum_data.index =
			in_msg->body.kvp_enum_data.index;
			break;
	}

	kvp_transaction.state = HVUTIL_USERSPACE_REQ;
	rc = hvutil_transport_send(hvt, message, sizeof(*message));
	if (rc) {
		pr_debug("KVP: failed to communicate to the daemon: %d\n", rc);
		if (cancel_delayed_work_sync(&kvp_timeout_work)) {
			kvp_respond_to_host(message, HV_E_FAIL);
			kvp_transaction.state = HVUTIL_READY;
		}
	}

	kfree(message);

	return;
}