From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dor Laor Subject: Fwd: [PATCH]: An implementation of HyperV KVP functionality Date: Sun, 14 Nov 2010 12:54:36 +0200 Message-ID: <4CDFBFEC.4080209@redhat.com> Reply-To: dlaor@redhat.com Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------080305010405040308070308" To: kvm-devel Return-path: Received: from mx1.redhat.com ([209.132.183.28]:26829 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755000Ab0KNKym (ORCPT ); Sun, 14 Nov 2010 05:54:42 -0500 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id oAEAsgRJ029403 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Sun, 14 Nov 2010 05:54:42 -0500 Received: from [10.35.6.176] (vpn-6-176.tlv.redhat.com [10.35.6.176]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id oAEAsauF001922 for ; Sun, 14 Nov 2010 05:54:37 -0500 Sender: kvm-owner@vger.kernel.org List-ID: This is a multi-part message in MIME format. --------------080305010405040308070308 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit FYI. Long ago we discussed key value approach on top of virtio-serial. -------- Original Message -------- Subject: [PATCH]: An implementation of HyperV KVP functionality Date: Thu, 11 Nov 2010 13:03:10 -0700 From: Ky Srinivasan To: , CC: Haiyang Zhang , Greg KH I am enclosing a patch that implements the KVP (Key Value Pair) functionality for Linux guests on HyperV. This functionality allows Microsoft Management stack to query information from the guest. This functionality is implemented in two parts: (a) A kernel component that communicates with the host and (b) A user level daemon that implements data gathering. The attached patch (kvp.patch) implements the kernel component. I am also attaching the code for the user-level daemon (kvp_daemon.c) for reference. Regards, K. Y --------------080305010405040308070308 Content-Type: text/plain; name="kvp.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="kvp.patch" From: K. Y. Srinivasan Subject: An implementation of key/value pair feature (KVP) for Linux on HyperV. Signed-off-by: K. Y. Srinivasan Index: linux.trees.git/drivers/staging/hv/kvp.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux.trees.git/drivers/staging/hv/kvp.c 2010-11-11 13:45:17.000000000 -0500 @@ -0,0 +1,404 @@ +/* + * An implementation of key value pair (KVP) functionality for Linux. + * + * + * Copyright (C) 2010, Novell, Inc. + * Author : K. Y. Srinivasan + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + + +#include +#include +#include + +#include "logging.h" +#include "osd.h" +#include "vmbus.h" +#include "vmbus_packet_format.h" +#include "vmbus_channel_interface.h" +#include "version_info.h" +#include "channel.h" +#include "vmbus_private.h" +#include "vmbus_api.h" +#include "utils.h" +#include "kvp.h" + + +/* + * + * The following definitions are shared with the user-mode component; do not + * change any of this without making the corresponding changes in + * the KVP user-mode component. + */ + +#define CN_KVP_VAL 0x1 /* This supports queries from the kernel */ +#define CN_KVP_USER_VAL 0x2 /* This supports queries from the user */ + + +/* + * KVP protocol: The user mode component first registers with the + * the kernel component. Subsequently, the kernel component requests, data + * for the specified keys. In response to this message the user mode component + * fills in the value corresponding to the specified key. We overload the + * sequence field in the cn_msg header to define our KVP message types. + * + * XXXKYS: Have a shared header file between the user and kernel (TODO) + */ + +enum kvp_op { + KVP_REGISTER = 0, /* Register the user mode component */ + KVP_KERNEL_GET,/*Kernel is requesting the value for the specified key*/ + KVP_KERNEL_SET, /*Kernel is providing the value for the specified key*/ + KVP_USER_GET, /*User is requesting the value for the specified key*/ + KVP_USER_SET /*User is providing the value for the specified key*/ +}; + + + +#define KVP_KEY_SIZE 512 +#define KVP_VALUE_SIZE 2048 + + +typedef struct kvp_msg { + __u32 kvp_key; /* Key */ + __u8 kvp_value[0]; /* Corresponding value */ +} kvp_msg_t; + +/* + * End of shared definitions. + */ + +/* + * Registry value types. + */ + +#define REG_SZ 1 + +/* + * Array of keys we support in Linux. + * + */ +#define KVP_MAX_KEY 10 +#define KVP_LIC_VERSION 1 + + +static char *kvp_keys[KVP_MAX_KEY] = {"FullyQualifiedDomainName", + "IntegrationServicesVersion", + "NetworkAddressIPv4", + "NetworkAddressIPv6", + "OSBuildNumber", + "OSName", + "OSMajorVersion", + "OSMinorVersion", + "OSVersion", + "ProcessorArchitecture", + }; + +/* + * Global state maintained for transaction that is being processed. + * Note that only one transaction can be active at any point in time. + * + * This state is set when we receive a request from the host; we + * cleanup this state when the transaction is completed - when we respond + * to the host with the key value. + */ + +static u8 *recv_buffer; /* the receive buffer that we allocated */ +static int recv_len; /* number of bytes received. */ +static struct vmbus_channel *recv_channel; /*chn on which we got the request*/ +static u64 recv_req_id; /* request ID. */ +static int kvp_current_index; + +static int +kvp_send_key(int index); + +static +void kvp_respond_to_host(int key, char *value); + +static struct cb_id kvp_id = { CN_KVP_IDX, CN_KVP_VAL }; +static char kvp_name[] = "kvp_kernel_module"; + +static bool kvp_transaction_active; + +static struct timer_list kvp_timer; + +static void kvp_timer_func(unsigned long __data) +{ + u32 key = *((u32 *)__data); + /* + * If the timer fires, the user-mode component has not responded; + * process the pending transaction. + */ + kvp_respond_to_host(key, "Guest timed out"); +} + +/* + * Callback when data is received from user mode. + */ + +static void +kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) +{ + struct kvp_msg *message; + + message = (struct kvp_msg *)msg->data; + if (msg->seq == KVP_REGISTER) + printk(KERN_WARNING "KVP: user-mode registering done.\n"); + + if (msg->seq == KVP_USER_SET) { + /* + * Complete the transaction by forwarding the key value + * to the host. But first, cancel the timeout. + */ + if (del_timer_sync(&kvp_timer)) + kvp_respond_to_host(message->kvp_key, + message->kvp_value); + } +} + +static int +kvp_send_key(int index) +{ + struct cn_msg *msg; + + msg = kzalloc(sizeof(*msg) + sizeof(kvp_msg_t) , GFP_ATOMIC); + + if (msg) { + msg->id.idx = CN_KVP_IDX; + msg->id.val = CN_KVP_VAL; + msg->seq = KVP_KERNEL_GET; + ((kvp_msg_t *)msg->data)->kvp_key = index; + msg->len = sizeof(kvp_msg_t); + cn_netlink_send(msg, 0, GFP_ATOMIC); + kfree(msg); + return 0; + } + return 1; +} + +/* + * Send a response back to the host. + * key specifies the key for which the value is being returned. + */ + +static +void kvp_respond_to_host(int key, char *value) +{ + ic_kvp_msg_t *kvp_msg; + ic_kvp_msg_enumerate_t *kvp_data; + char *key_name; + struct icmsg_hdr *icmsghdrp; + int keylen, valuelen; + u8 *buf; + u32 buf_len; + struct vmbus_channel *channel; + u64 req_id; + + /* + * If a transaction is not active; log and return. + */ + + if (!kvp_transaction_active) { + /* + * This is a spurious call! + */ + printk(KERN_WARNING "KVP: Transaction not active\n"); + return; + } + /* + * Copy the global state for completing the transaction. Note that + * only one transaction can be active at a time. + */ + + buf = recv_buffer; + buf_len = recv_len; + channel = recv_channel; + req_id = recv_req_id; + + kvp_transaction_active = false; + + icmsghdrp = (struct icmsg_hdr *)&buf[sizeof(struct vmbuspipe_hdr)]; + kvp_msg = (ic_kvp_msg_t *)&buf[sizeof(struct vmbuspipe_hdr) + + sizeof(struct icmsg_hdr)]; + kvp_data = &kvp_msg->kvp_data; + key_name = kvp_keys[key]; + + /* + * The windows host expects the key/value pair to be encoded + * in utf16. + */ + keylen = utf8s_to_utf16s(key_name, strlen(key_name), + (wchar_t *)kvp_data->data.key); + kvp_data->data.key_size = 2*(keylen + 1); /* utf16 encoding */ + valuelen = utf8s_to_utf16s(value, strlen(value), + (wchar_t *)kvp_data->data.value); + kvp_data->data.value_size = 2*(valuelen + 1); /* utf16 encoding */ + + kvp_data->data.value_type = REG_SZ; /* all our values are strings */ + icmsghdrp->status = HV_S_OK; + + icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; + + vmbus_sendpacket(channel, buf, buf_len, req_id, + VmbusPacketTypeDataInBand, 0); + + /* + * Free up the buffer that was allocatted when we received a message + * from the host. + */ + kfree(buf); +} + +/* + * This callback is invoked when we get a KVP message from the host. + * The host ensures that only one KVP transaction can be active at a time. + * KVP implementation in Linux needs to forward the key to a user-mde + * component to retrive the corresponding value. Consequently, we cannot + * respond to the host in the conext of this callback. Since the host + * guarantees that at most only one transaction can be active at a time, + * we stash away the transaction state in a set of global variables. + */ + +void kvp_onchannelcallback(void *context) +{ + struct vmbus_channel *channel = context; + u8 *buf; + u32 buflen, recvlen; + u64 requestid; + + ic_kvp_msg_t *kvp_msg; + ic_kvp_msg_enumerate_t *kvp_data; + + struct icmsg_hdr *icmsghdrp; + struct icmsg_negotiate *negop = NULL; + + + buflen = PAGE_SIZE; + buf = kmalloc(buflen, GFP_ATOMIC); + + vmbus_recvpacket(channel, buf, buflen, &recvlen, &requestid); + + if (recvlen > 0) { + DPRINT_DBG(VMBUS, "KVP packet: len=%d, requestid=%lld", + recvlen, requestid); + + icmsghdrp = (struct icmsg_hdr *)&buf[ + sizeof(struct vmbuspipe_hdr)]; + + if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { + prep_negotiate_resp(icmsghdrp, negop, buf); + } else { + kvp_msg = (ic_kvp_msg_t *)&buf[ + sizeof(struct vmbuspipe_hdr) + + sizeof(struct icmsg_hdr)]; + + kvp_data = &kvp_msg->kvp_data; + + /* + * We only support the "get" operation on + * "ICKvpExchangePoolAuto" pool. + */ + + if ((kvp_msg->kvp_hdr.pool != ICKvpExchangePoolAuto) || + (kvp_msg->kvp_hdr.operation != + ICKvpExchangeOperationEnumerate) || + kvp_transaction_active) { + if (kvp_transaction_active) + printk(KERN_WARNING + "KVP: Invalid call\n"); + icmsghdrp->status = HV_E_FAIL; + goto callback_done; + } + + /* + * Stash away this global state for completing the + * transaction; note transactions are serialized. + */ + recv_buffer = buf; + recv_len = recvlen; + recv_channel = channel; + recv_req_id = requestid; + + switch (kvp_data->index) { + case (KVP_MAX_KEY): + /* + * We don't support this key + * and any key beyond this. + */ + icmsghdrp->status = HV_E_FAIL; + goto callback_done; + + case (KVP_LIC_VERSION): + kvp_transaction_active = true; + kvp_respond_to_host(kvp_data->index, + HV_DRV_VERSION); + return; + default: + /* + * Get the information from the + * user-mode component. + * component. This transaction will be + * completed when we get the value from + * the user-mode component. + * Set a timeout to deal with + * user-mode not responding. + */ + kvp_current_index = kvp_data->index; + mod_timer(&kvp_timer, jiffies+75); + kvp_transaction_active = true; + kvp_send_key(kvp_data->index); + return; + } + + } + +callback_done: + + icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION + | ICMSGHDRFLAG_RESPONSE; + + vmbus_sendpacket(channel, buf, + recvlen, requestid, + VmbusPacketTypeDataInBand, 0); + } + + kfree(buf); + + +} + +int +kvp_init(void) +{ + int err; + + err = cn_add_callback(&kvp_id, kvp_name, kvp_cn_callback); + if (err) + return err; + + setup_timer(&kvp_timer, kvp_timer_func, + (unsigned long)&kvp_current_index); + return 0; +} + +void kvp_deinit(void) +{ + cn_del_callback(&kvp_id); + del_timer_sync(&kvp_timer); +} + Index: linux.trees.git/drivers/staging/hv/Makefile =================================================================== --- linux.trees.git.orig/drivers/staging/hv/Makefile 2010-11-10 14:01:55.000000000 -0500 +++ linux.trees.git/drivers/staging/hv/Makefile 2010-11-11 11:24:54.000000000 -0500 @@ -2,7 +2,7 @@ obj-$(CONFIG_HYPERV) += hv_vmbus.o hv_t obj-$(CONFIG_HYPERV_STORAGE) += hv_storvsc.o obj-$(CONFIG_HYPERV_BLOCK) += hv_blkvsc.o obj-$(CONFIG_HYPERV_NET) += hv_netvsc.o -obj-$(CONFIG_HYPERV_UTILS) += hv_utils.o +obj-$(CONFIG_HYPERV_UTILS) += hv_util.o hv_vmbus-y := vmbus_drv.o osd.o \ vmbus.o hv.o connection.o channel.o \ @@ -10,3 +10,4 @@ hv_vmbus-y := vmbus_drv.o osd.o \ hv_storvsc-y := storvsc_drv.o storvsc.o hv_blkvsc-y := blkvsc_drv.o blkvsc.o hv_netvsc-y := netvsc_drv.o netvsc.o rndis_filter.o +hv_util-y := hv_utils.o kvp.o Index: linux.trees.git/drivers/staging/hv/kvp.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux.trees.git/drivers/staging/hv/kvp.h 2010-11-10 14:03:47.000000000 -0500 @@ -0,0 +1,101 @@ +/* + * An implementation of key value pair (KVP) functionality for Linux. + * + * + * Copyright (C) 2010, Novell, Inc. + * Author : K. Y. Srinivasan + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#ifndef _KVP_H +#define _KVP_H_ + +/* + * Maximum value size - used for both key names and value data, and includes + * any applicable NULL terminators. + * + * Note: This limit is somewhat arbitrary, but falls easily within what is + * supported for all native guests (back to Win 2000) and what is reasonable + * for the IC KVP exchange functionality. Note that Windows Me/98/95 are + * limited to 255 character key names. + * + * MSDN recommends not storing data values larger than 2048 bytes in the + * registry. + * + * Note: This value is used in defining the KVP exchange message - this value + * cannot be modified without affecting the message size and compatability. + */ + +/* + * bytes, including any null terminators + */ +#define IC_KVP_EXCHANGE_MAX_VALUE_SIZE (2048) + + +/* + * Maximum key size - the registry limit for the length of an entry name + * is 256 characters, including the null terminator + */ + +#define IC_KVP_EXCHANGE_MAX_KEY_SIZE (512) + + +typedef enum { + ICKvpExchangeOperationGet = 0, + ICKvpExchangeOperationSet, + ICKvpExchangeOperationDelete, + ICKvpExchangeOperationEnumerate, + ICKvpExchangeOperationCount /* Number of operations, must be last. */ +} IC_KVP_EXCHANGE_OPERATION; + +typedef enum { + ICKvpExchangePoolExternal = 0, + ICKvpExchangePoolGuest, + ICKvpExchangePoolAuto, + ICKvpExchangePoolAutoExternal, + ICKvpExchangePoolInternal, + ICKvpExchangePoolCount /* Number of pools, must be last. */ +} IC_KVP_EXCHANGE_POOL; + +typedef struct ic_kvp_hdr { + u8 operation; + u8 pool; +} ic_kvp_hdr_t; + +typedef struct ic_kvp_exchg_msg_value { + u32 value_type; + u32 key_size; + u32 value_size; + u8 key[IC_KVP_EXCHANGE_MAX_KEY_SIZE]; + u8 value[IC_KVP_EXCHANGE_MAX_VALUE_SIZE]; +} ic_kvp_exchg_msg_value_t; + +typedef struct ic_kvp__msg_enumerate { + u32 index; + ic_kvp_exchg_msg_value_t data; +} ic_kvp_msg_enumerate_t; + +typedef struct ic_kvp_msg { + ic_kvp_hdr_t kvp_hdr; + ic_kvp_msg_enumerate_t kvp_data; +} ic_kvp_msg_t; + +int kvp_init(void); +void kvp_deinit(void); +void kvp_onchannelcallback(void *); + +#endif /* _KVP_H */ + Index: linux.trees.git/drivers/staging/hv/utils.h =================================================================== --- linux.trees.git.orig/drivers/staging/hv/utils.h 2010-11-10 10:30:23.000000000 -0500 +++ linux.trees.git/drivers/staging/hv/utils.h 2010-11-10 14:03:47.000000000 -0500 @@ -102,6 +102,7 @@ struct ictimesync_data{ #define HV_SHUTDOWN_MSG 0 #define HV_TIMESYNC_MSG 1 #define HV_HEARTBEAT_MSG 2 +#define HV_KVP_MSG 3 struct hyperv_service_callback { u8 msg_type; Index: linux.trees.git/drivers/staging/hv/hv_utils.c =================================================================== --- linux.trees.git.orig/drivers/staging/hv/hv_utils.c 2010-11-10 14:02:40.000000000 -0500 +++ linux.trees.git/drivers/staging/hv/hv_utils.c 2010-11-11 13:42:38.000000000 -0500 @@ -37,6 +37,7 @@ #include "vmbus_private.h" #include "vmbus_api.h" #include "utils.h" +#include "kvp.h" static void shutdown_onchannelcallback(void *context) @@ -268,6 +269,9 @@ static int __init init_hyperv_utils(void { printk(KERN_INFO "Registering HyperV Utility Driver\n"); + if (kvp_init()) + return -ENODEV; + if (!dmi_check_system(hv_utils_dmi_table)) return -ENODEV; @@ -283,6 +287,10 @@ static int __init init_hyperv_utils(void &heartbeat_onchannelcallback; hv_cb_utils[HV_HEARTBEAT_MSG].callback = &heartbeat_onchannelcallback; + hv_cb_utils[HV_KVP_MSG].channel->OnChannelCallback = + &kvp_onchannelcallback; + + return 0; } @@ -301,6 +309,12 @@ static void exit_hyperv_utils(void) hv_cb_utils[HV_HEARTBEAT_MSG].channel->OnChannelCallback = &chn_cb_negotiate; hv_cb_utils[HV_HEARTBEAT_MSG].callback = &chn_cb_negotiate; + + hv_cb_utils[HV_KVP_MSG].channel->OnChannelCallback = + &chn_cb_negotiate; + + kvp_deinit(); + } module_init(init_hyperv_utils); Index: linux.trees.git/include/linux/connector.h =================================================================== --- linux.trees.git.orig/include/linux/connector.h 2010-11-09 17:22:15.000000000 -0500 +++ linux.trees.git/include/linux/connector.h 2010-11-11 13:14:52.000000000 -0500 @@ -42,8 +42,9 @@ #define CN_VAL_DM_USERSPACE_LOG 0x1 #define CN_IDX_DRBD 0x8 #define CN_VAL_DRBD 0x1 +#define CN_KVP_IDX 0x9 /* MSFT KVP functionality */ -#define CN_NETLINK_USERS 8 +#define CN_NETLINK_USERS 10 /* * Maximum connector's message size. --------------080305010405040308070308 Content-Type: application/octet-stream; name="kvp_daemon.c" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="kvp_daemon.c" LyoKICogQW4gaW1wbGVtZW50YXRpb24gb2Yga2V5IHZhbHVlIHBhaXIgKEtWUCkgZnVuY3Rp b25hbGl0eSBmb3IgTGludXguCiAqCiAqCiAqIENvcHlyaWdodCAoQykgMjAxMCwgTm92ZWxs LCBJbmMuCiAqIEF1dGhvciA6IEsuIFkuIFNyaW5pdmFzYW4gPGtzcmluaXZhc2FuQG5vdmVs bC5jb20+CiAqCiAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJl ZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0CiAqIHVuZGVyIHRoZSB0ZXJtcyBvZiB0 aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgdmVyc2lvbiAyIGFzIHB1Ymxpc2hlZAog KiBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLgogKgogKiBUaGlzIHByb2dyYW0g aXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0 CiAqIFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2Fy cmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIE9SIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxB UiBQVVJQT1NFLCBHT09EIFRJVExFIG9yCiAqIE5PTiBJTkZSSU5HRU1FTlQuICBTZWUgdGhl IEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlCiAqIGRldGFpbHMuCiAqCiAq IFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1 YmxpYyBMaWNlbnNlCiAqIGFsb25nIHdpdGggdGhpcyBwcm9ncmFtOyBpZiBub3QsIHdyaXRl IHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGlu IFN0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAwMjExMC0xMzAxIFVTQS4KICoKICovCgoK I2luY2x1ZGUgPHN5cy90eXBlcy5oPgojaW5jbHVkZSA8c3lzL3NvY2tldC5oPgojaW5jbHVk ZSA8c3lzL3BvbGwuaD4KI2luY2x1ZGUgPHN5cy91dHNuYW1lLmg+CiNpbmNsdWRlIDxhc20v dHlwZXMuaD4KI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1 ZGUgPHVuaXN0ZC5oPgojaW5jbHVkZSA8c3RyaW5nLmg+CiNpbmNsdWRlIDxlcnJuby5oPgoj aW5jbHVkZSA8YXJwYS9pbmV0Lmg+CiNpbmNsdWRlIDxsaW51eC9jb25uZWN0b3IuaD4KI2lu Y2x1ZGUgPGxpbnV4L25ldGxpbmsuaD4KI2luY2x1ZGUgPHN5cy9zb2NrZXQuaD4KI2luY2x1 ZGUgPGlmYWRkcnMuaD4KI2luY2x1ZGUgPG5ldGRiLmg+CiNpbmNsdWRlIDxzeXNsb2cuaD4K Ci8qCiAqIEtZUzogVE9ETy4gTmVlZCB0byByZWdpc3RlciB0aGVzZSBpbiB0aGUga2VybmVs LgogKgogKiBUaGUgZm9sbG93aW5nIGRlZmluaXRpb25zIGFyZSBzaGFyZWQgd2l0aCB0aGUg aW4ta2VybmVsIGNvbXBvbmVudDsgZG8gbm90CiAqIGNoYW5nZSBhbnkgb2YgdGhpcyB3aXRo b3V0IG1ha2luZyB0aGUgY29ycmVzcG9uZGluZyBjaGFuZ2VzIGluIAogKiB0aGUgS1ZQIGtl cm5lbCBjb21wb25lbnQuCiAqLwojZGVmaW5lIENOX0tWUF9JRFgJCTB4OSAgICAgLyogTVNG VCBLVlAgZnVuY3Rpb25hbGl0eSAqLwojZGVmaW5lIENOX0tWUF9WQUwJCTB4MSAvKiBUaGlz IHN1cHBvcnRzIHF1ZXJpZXMgZnJvbSB0aGUga2VybmVsICovCiNkZWZpbmUgQ05fS1ZQX1VT RVJfVkFMCQkweDIgLyogVGhpcyBzdXBwb3J0cyBxdWVyaWVzIGZyb20gdGhlIHVzZXIgICov CgovKgogKiBLVlAgcHJvdG9jb2w6IFRoZSB1c2VyIG1vZGUgY29tcG9uZW50IGZpcnN0IHJl Z2lzdGVycyB3aXRoIHRoZSAKICogdGhlIGtlcm5lbCBjb21wb25lbnQuIFN1YnNlcXVlbnRs eSwgdGhlIGtlcm5lbCBjb21wb25lbnQgcmVxdWVzdHMsIGRhdGEKICogZm9yIHRoZSBzcGVj aWZpZWQga2V5cy4gSW4gcmVzcG9uc2UgdG8gdGhpcyBtZXNzYWdlIHRoZSB1c2VyIG1vZGUg Y29tcG9uZW50CiAqIGZpbGxzIGluIHRoZSB2YWx1ZSBjb3JyZXNwb25kaW5nIHRvIHRoZSBz cGVjaWZpZWQga2V5LiBXZSBvdmVybG9hZCB0aGUgCiAqIHNlcXVlbmNlIGZpZWxkIGluIHRo ZSBjbl9tc2cgaGVhZGVyIHRvIGRlZmluZSBvdXIgS1ZQIG1lc3NhZ2UgdHlwZXMuCiAqCiAq IFdlIHVzZSB0aGlzIGluZnJhc3RydWN0dXJlIGZvciBhbHNvIHN1cHBvcnRpbmcgcXVlcmll cyBmcm9tIHVzZXIgbW9kZQogKiBhcHBsaWNhdGlvbiBmb3Igc3RhdGUgdGhhdCBtYXkgYmUg bWFpbnRhaW5lZCBpbiB0aGUgS1ZQIGtlcm5lbCBjb21wb25lbnQuCiAqCiAqIFhYWEtZUzog SGF2ZSBhIHNoYXJlZCBoZWFkZXIgZmlsZSBiZXR3ZWVuIHRoZSB1c2VyIGFuZCBrZXJuZWwg KFRPRE8pCiAqLwoKZW51bSBrdnBfb3AgewoJS1ZQX1JFR0lTVEVSID0gMCwgLyogUmVnaXN0 ZXIgdGhlIHVzZXIgbW9kZSBjb21wb25lbnQqLwoJS1ZQX0tFUk5FTF9HRVQsIC8qS2VybmVs IGlzIHJlcXVlc3RpbmcgdGhlIHZhbHVlIGZvciB0aGUgc3BlY2lmaWVkIGtleSovCglLVlBf S0VSTkVMX1NFVCwgLypLZXJuZWwgaXMgcHJvdmlkaW5nIHRoZSB2YWx1ZSBmb3IgdGhlIHNw ZWNpZmllZCBrZXkqLwoJS1ZQX1VTRVJfR0VULCAvKlVzZXIgaXMgcmVxdWVzdGluZyB0aGUg dmFsdWUgZm9yIHRoZSBzcGVjaWZpZWQga2V5Ki8KCUtWUF9VU0VSX1NFVCAvKlVzZXIgaXMg cHJvdmlkaW5nIHRoZSB2YWx1ZSBmb3IgdGhlIHNwZWNpZmllZCBrZXkqLwp9OwoKI2RlZmlu ZSBLVlBfS0VZX1NJWkUJNTEyCiNkZWZpbmUgS1ZQX1ZBTFVFX1NJWkUJMjA0OAoJCnR5cGVk ZWYgc3RydWN0IGt2cF9tc2cgewoJX191MzIJa3ZwX2tleTsKCV9fdTgJa3ZwX3ZhbHVlW0tW UF9WQUxVRV9TSVpFXTsKfSBrdnBfbXNnX3Q7Cgp0eXBlZGVmIGVudW0gewoJRnVsbHlRdWFs aWZpZWREb21haW5OYW1lID0gMCwKCUludGVncmF0aW9uU2VydmljZXNWZXJzaW9uLCAvKlRo aXMga2V5IGlzIHNlcnZpY2VkIGluIHRoZSBrZXJuZWwqLwoJTmV0d29ya0FkZHJlc3NJUHY0 LAoJTmV0d29ya0FkZHJlc3NJUHY2LAoJT1NCdWlsZE51bWJlciwKCU9TTmFtZSwKCU9TTWFq b3JWZXJzaW9uLAoJT1NNaW5vclZlcnNpb24sCglPU1ZlcnNpb24sCglQcm9jZXNzb3JBcmNo aXRlY3R1cmUKfSBrdnBfa2V5X25hbWVfdDsKIAovKgogKiBFbmQgb2Ygc2hhcmVkIGRlZmlu aXRpb25zLgogKi8KCnN0YXRpYyBjaGFyIGt2cF9zZW5kX2J1ZmZlcls0MDk2XTsKc3RhdGlj IGNoYXIga3ZwX3JlY3ZfYnVmZmVyWzQwOTZdOwpzdGF0aWMgc3RydWN0IHNvY2thZGRyX25s IGFkZHI7CgpzdGF0aWMgY2hhciBvc19uYW1lWzEwMF07CnN0YXRpYyBjaGFyIG9zX21ham9y WzUwXTsKc3RhdGljIGNoYXIgb3NfbWlub3JbNTBdOwpzdGF0aWMgY2hhciBwcm9jZXNzb3Jf YXJjaFs1MF07CnN0YXRpYyBjaGFyIG9zX2J1aWxkWzEwMF07Cgp2b2lkIGt2cF9nZXRfb3Nf aW5mbyh2b2lkKQp7CglGSUxFCSpmaWxlOwoJY2hhcgkqZW9sOwoJc3RydWN0IHV0c25hbWUg YnVmOwoKCXVuYW1lKCZidWYpOwoJc3RyY3B5KG9zX2J1aWxkLCBidWYucmVsZWFzZSk7Cglz dHJjcHkocHJvY2Vzc29yX2FyY2gsIGJ1Zi5tYWNoaW5lKTsKCglpZiAoKGZpbGUgPSBmb3Bl bigiL2V0Yy9TdVNFLXJlbGVhc2UiLCAiciIpKSAhPSBOVUxMKQoJCWdvdG8ga3ZwX29zaW5m b19mb3VuZDsKCWlmICgoZmlsZSAgPSBmb3BlbigiL2V0Yy9TdVNFLXJlbGVhc2UiLCAiciIp KSAhPSBOVUxMKQoJCWdvdG8ga3ZwX29zaW5mb19mb3VuZDsKCS8qCgkgKiBBZGQgY29kZSBm b3Igb3RoZXIgc3VwcG9ydGVkIHBsYXRmb3Jtcy4KCSAqLwoKCS8qCgkgKiBXZSBkb24ndCBo YXZlIGluZm9ybWF0aW9uIGFib3V0IHRoZSBvcy4KCSAqLwoJc3RyY3B5KG9zX25hbWUsICJM aW51eCIpOwoJc3RyY3B5KG9zX21ham9yLCAiMCIpOwoJc3RyY3B5KG9zX21pbm9yLCAiMCIp OwoJcmV0dXJuOwoKa3ZwX29zaW5mb19mb3VuZDoKCWZnZXRzKG9zX25hbWUsIDk5LCBmaWxl KTsKCWVvbCA9IGluZGV4KG9zX25hbWUsICdcbicpOwoJKmVvbCA9ICdcMCc7CglmZ2V0cyhv c19tYWpvciwgNDksIGZpbGUpOwoJZW9sID0gaW5kZXgob3NfbWFqb3IsICdcbicpOwoJKmVv bCA9ICdcMCc7CglmZ2V0cyhvc19taW5vciwgNDksIGZpbGUpOwoJZW9sID0gaW5kZXgob3Nf bWlub3IsICdcbicpOwoJKmVvbCA9ICdcMCc7CglmY2xvc2UoZmlsZSk7CglyZXR1cm47Cn0K CQpzdGF0aWMgaW50Cmt2cF9nZXRfaXBfYWRkcmVzcyhpbnQgZmFtaWx5LCBjaGFyICpidWZm ZXIsIGludCBsZW5ndGgpCnsKCXN0cnVjdCBpZmFkZHJzICppZmFwOwoJc3RydWN0IGlmYWRk cnMgKmN1cnA7CglpbnQgaXB2NF9sZW4gPSBzdHJsZW4oIjI1NS4yNTUuMjU1LjI1NSIpICsg MTsKCWludCBpcHY2X2xlbiA9IHN0cmxlbigiZmZmZjpmZmZmOmZmZmY6ZmZmZjpmZmZmOmZm ZmY6ZmZmZjpmZmZmIikrMTsgCglpbnQgb2Zmc2V0ID0gMDsKCWNvbnN0IGNoYXIgKnN0cjsK CWNoYXIgdG1wWzUwXTsKCWludCBlcnJvciA9IDA7CgoJLyoKCSAqIE9uIGVudHJ5IGludG8g dGhpcyBmdW5jdGlvbiwgdGhlIGJ1ZmZlciBpcyBjYXBhYmxlIG9mIGhvbGRpbmcgdGhlCgkg KiBtYXhpbXVtIGtleSB2YWx1ZSAoMjA0OCBieXRlcykuCgkgKi8KCQoJaWYgKGdldGlmYWRk cnMoJmlmYXApKSB7CgkJc3RyY3B5KGJ1ZmZlciwgImdldGlmYWRkcnMgZmFpbGVkXG4iKTsK CQlyZXR1cm4gMTsKCX0KCgljdXJwID0gaWZhcDsKCXdoaWxlIChjdXJwICE9IE5VTEwpIHsK CQlpZiAoKGN1cnAtPmlmYV9hZGRyICE9IE5VTEwpICYmICAKCQkgICAoY3VycC0+aWZhX2Fk ZHItPnNhX2ZhbWlseSA9PSBmYW1pbHkpKSB7CgkJCWlmIChmYW1pbHkgPT0gQUZfSU5FVCkg ewoJCQkJc3RydWN0IHNvY2thZGRyX2luICphZGRyID0gCgkJCQkoc3RydWN0IHNvY2thZGRy X2luICopIGN1cnAtPmlmYV9hZGRyOwoKCQkJCWlmICghKHN0ciA9IGluZXRfbnRvcChmYW1p bHksICZhZGRyLT5zaW5fYWRkciwgCgkJCQkJdG1wLCA1MCkpKSB7CgkJCQkJc3RyY3B5KGJ1 ZmZlciwgImluZXRfbnRvcCBmYWlsZWRcbiIpOwoJCQkJCWVycm9yID0gMTsKCQkJCQlnb3Rv IGdldGFkZHJfZG9uZTsKCQkJCX0KCQkJCWlmIChvZmZzZXQgPT0gMCkgCgkJCQkJc3RyY3B5 KGJ1ZmZlciwgdG1wKTsKCQkJCWVsc2UgCgkJCQkJc3RyY2F0KGJ1ZmZlciwgdG1wKTsKCQkJ CXN0cmNhdChidWZmZXIsICI7Iik7CgkJCQkKCQkJCW9mZnNldCArPSBzdHJsZW4oc3RyKSAr MTsKCQkJCWlmICgobGVuZ3RoIC0gb2Zmc2V0KSA8IChpcHY0X2xlbiArIDEpKSB7CgkJCQkJ Z290byBnZXRhZGRyX2RvbmU7CgkJCQl9CgkJCX0gZWxzZSB7CgkJCS8qCgkJIAkgKiBXZSBv bmx5IHN1cHBvcnQgQUZfSU5FVCBhbmQgQUZfSU5FVDYKCQkJICogYW5kIHRoZSBsaXN0IG9m IGFkZHJlc3NlcyBpcyBzZXBlcmF0ZWQgYnkgYSAiOyIuCgkJCSAqLwoJCQkJc3RydWN0IHNv Y2thZGRyX2luNiAqYWRkciA9IAoJCQkJKHN0cnVjdCBzb2NrYWRkcl9pbjYgKikgY3VycC0+ aWZhX2FkZHI7CgoJCQkJaWYgKCEoc3RyID0gaW5ldF9udG9wKGZhbWlseSwKCQkJCQkmYWRk ci0+c2luNl9hZGRyLnM2X2FkZHIsCgkJCQkJdG1wLCA1MCkpKSB7CgkJCQkJc3RyY3B5KGJ1 ZmZlciwgImluZXRfbnRvcCBmYWlsZWRcbiIpOwoJCQkJCWVycm9yID0gMTsKCQkJCQlnb3Rv IGdldGFkZHJfZG9uZTsKCQkJCX0KCQkJCWlmIChvZmZzZXQgPT0gMCkgCgkJCQkJc3RyY3B5 KGJ1ZmZlciwgdG1wKTsKCQkJCWVsc2UgCgkJCQkJc3RyY2F0KGJ1ZmZlciwgdG1wKTsKCQkJ CXN0cmNhdChidWZmZXIsICI7Iik7CgkJCQlvZmZzZXQgKz0gc3RybGVuKHN0cikgKzE7CgkJ CQlpZiAoKGxlbmd0aCAtIG9mZnNldCkgPCAoaXB2Nl9sZW4gKzEpKSB7CgkJCQkJZ290byBn ZXRhZGRyX2RvbmU7CgkJCQl9CgkJCX0KCQkJCQoJCX0KCQljdXJwID0gY3VycC0+aWZhX25l eHQ7Cgl9CgpnZXRhZGRyX2RvbmU6CglmcmVlaWZhZGRycyhpZmFwKTsKCXJldHVybiBlcnJv cjsKfQoKCnN0YXRpYyBpbnQKa3ZwX2dldF9kb21haW5fbmFtZShjaGFyICpidWZmZXIsIGlu dCBsZW5ndGgpCnsKCXN0cnVjdCBhZGRyaW5mbwloaW50cywgKmluZm8gOwoJZ2V0aG9zdG5h bWUoYnVmZmVyLCBsZW5ndGgpOwoJaW50IGVycm9yID0wOwoKCW1lbXNldCgmaGludHMsIDAs IHNpemVvZihoaW50cykpOwoJaGludHMuYWlfZmFtaWx5ID0gQUZfSU5FVDsgLypHZXQgb25s eSBpcHY0IGFkZHJpbmZvLiAqLwoJaGludHMuYWlfc29ja3R5cGUgPSBTT0NLX1NUUkVBTTsK CWhpbnRzLmFpX2ZsYWdzID0gQUlfQ0FOT05OQU1FOwoJCglpZiAoKGVycm9yID0gZ2V0YWRk cmluZm8oYnVmZmVyLCAiaHR0cCIsICZoaW50cywgJmluZm8pKSAhPTApIHsKCQlzdHJjcHko YnVmZmVyLCAiZ2V0YWRkcmluZm8gZmFpbGVkXG4iKTsKCQllcnJvciA9IDE7CgkJZ290byBn ZXRfZG9tYWluX2RvbmU7Cgl9CglzdHJjcHkoYnVmZmVyLCBpbmZvLT5haV9jYW5vbm5hbWUp OwpnZXRfZG9tYWluX2RvbmU6CglmcmVlYWRkcmluZm8oaW5mbyk7CglyZXR1cm4gKGVycm9y KTsKfQoKc3RhdGljIGludCAKbmV0bGlua19zZW5kKGludCBmZCwgc3RydWN0IGNuX21zZyAq bXNnKQp7CglzdHJ1Y3Qgbmxtc2doZHIgKm5saDsKCXVuc2lnbmVkIGludCBzaXplOwoJc3Ry dWN0IG1zZ2hkciBtZXNzYWdlOwoJY2hhciBidWZmZXJbNjRdOwoJc3RydWN0IGlvdmVjIGlv dlsyXTsKCglzaXplID0gTkxNU0dfU1BBQ0Uoc2l6ZW9mKHN0cnVjdCBjbl9tc2cpICsgbXNn LT5sZW4pOwoKCW5saCA9IChzdHJ1Y3Qgbmxtc2doZHIgKilidWZmZXI7CglubGgtPm5sbXNn X3NlcSA9IDA7CglubGgtPm5sbXNnX3BpZCA9IGdldHBpZCgpOwoJbmxoLT5ubG1zZ190eXBl ID0gTkxNU0dfRE9ORTsKCW5saC0+bmxtc2dfbGVuID0gTkxNU0dfTEVOR1RIKHNpemUgLSBz aXplb2YoKm5saCkpOwoJbmxoLT5ubG1zZ19mbGFncyA9IDA7CgkKCWlvdlswXS5pb3ZfYmFz ZSA9IG5saDsKCWlvdlswXS5pb3ZfbGVuID0gc2l6ZW9mKCpubGgpOwoKCWlvdlsxXS5pb3Zf YmFzZSA9IG1zZzsKCWlvdlsxXS5pb3ZfbGVuID0gc2l6ZTsKCgltZW1zZXQoJm1lc3NhZ2Us IDAsIHNpemVvZihtZXNzYWdlKSk7CgltZXNzYWdlLm1zZ19uYW1lID0gJmFkZHI7CgltZXNz YWdlLm1zZ19uYW1lbGVuID0gc2l6ZW9mKGFkZHIpOyAKCW1lc3NhZ2UubXNnX2lvdiA9IGlv djsKCW1lc3NhZ2UubXNnX2lvdmxlbiA9IDI7CgoJcmV0dXJuIChzZW5kbXNnKGZkLCAmbWVz c2FnZSwgMCkpOwp9CgptYWluKHZvaWQpCnsKCWludCBmZCwgbGVuLCBzb2NrX29wdDsKCWlu dCBlcnJvcjsKCXN0cnVjdCBjbl9tc2cgKm1lc3NhZ2U7CglzdHJ1Y3QgcG9sbGZkIHBmZDsK CXN0cnVjdCBubG1zZ2hkciAqaW5jb21pbmdfbXNnOwoJc3RydWN0IGNuX21zZwkqaW5jb21p bmdfY25fbXNnOwoJY2hhcgkqa2V5X3ZhbHVlOwoJa3ZwX2tleV9uYW1lX3Qga2V5X25hbWU7 CgoJZGFlbW9uKDEsIDApOwoJb3BlbmxvZygiS1ZQIiwgMCwgTE9HX1VTRVIpOwoJc3lzbG9n KExPR19JTkZPLCAiS1ZQIHN0YXJ0aW5nOyBwaWQgaXM6JWQiLCBnZXRwaWQoKSk7CgkvKgoJ ICogUmV0cmlldmUgT1MgcmVsZWFzZSBpbmZvcm1hdGlvbi4KCSAqLwoJa3ZwX2dldF9vc19p bmZvKCk7CgoJZmQgPSBzb2NrZXQoQUZfTkVUTElOSywgU09DS19ER1JBTSwgTkVUTElOS19D T05ORUNUT1IpOwoJaWYgKGZkIDwgMCkgewoJCXN5c2xvZyhMT0dfRVJSLCAibmV0bGluayBz b2NrZXQgY3JlYXRpb24gZmFpbGVkOyBlcnJvcjolZCIsZmQpOwoJCWV4aXQgLTE7Cgl9Cglh ZGRyLm5sX2ZhbWlseSA9IEFGX05FVExJTks7CglhZGRyLm5sX3BhZCA9IDA7CglhZGRyLm5s X3BpZCA9IDA7CglhZGRyLm5sX2dyb3VwcyA9IENOX0tWUF9JRFg7CgoKCWlmICgoZXJyb3Ig PSBiaW5kKGZkLCAoc3RydWN0IHNvY2thZGRyICopJmFkZHIsIHNpemVvZihhZGRyKSkpIDwg MCkgewoJCXN5c2xvZyhMT0dfRVJSLCAiYmluZCBmYWlsZWQ7IGVycm9yOiVkIixlcnJvcik7 CgkJY2xvc2UoZmQpOwoJCWV4aXQgLTE7Cgl9Cglzb2NrX29wdCA9IGFkZHIubmxfZ3JvdXBz OwoJc2V0c29ja29wdChmZCwgMjcwLCAxLCAmc29ja19vcHQsIHNpemVvZihzb2NrX29wdCkp OwoJLyoKCSAqIFJlZ2lzdGVyIG91cnNlbHZlcyB3aXRoIHRoZSBrZXJuZWwuCgkgKi8KCW1l c3NhZ2UgPSAoc3RydWN0IGNuX21zZyAqKWt2cF9zZW5kX2J1ZmZlcjsKCW1lc3NhZ2UtPmlk LmlkeCA9IENOX0tWUF9JRFg7CgltZXNzYWdlLT5pZC52YWwgPSBDTl9LVlBfVkFMOwoJbWVz c2FnZS0+c2VxID0gS1ZQX1JFR0lTVEVSOwoJbWVzc2FnZS0+YWNrID0gMDsKCW1lc3NhZ2Ut PmxlbiA9IDA7CgoJbGVuID0gbmV0bGlua19zZW5kKGZkLCBtZXNzYWdlKTsKCWlmIChsZW4g PCAwKSB7CgkJc3lzbG9nKExPR19FUlIsICJuZXRsaW5rX3NlbmQgZmFpbGVkOyBlcnJvcjol ZCIsIGxlbik7CgkJY2xvc2UoZmQpOwoJCWV4aXQgLTE7Cgl9CgkKCXBmZC5mZCA9IGZkOwoJ Cgl3aGlsZSAoMSkgewoJCXBmZC5ldmVudHMgPSBQT0xMSU47CgkJcGZkLnJldmVudHMgPSAw OwoJCXBvbGwoJnBmZCwgMSwgLTEpOwoKCQlsZW4gPSByZWN2KGZkLCBrdnBfcmVjdl9idWZm ZXIsIHNpemVvZihrdnBfcmVjdl9idWZmZXIpLCAwKTsKCgkJaWYgKGxlbiA8IDApIHsKCQkJ c3lzbG9nKExPR19FUlIsICJyZWN2IGZhaWxlZDsgZXJyb3I6JWQiLCBsZW4pOwoJCQljbG9z ZShmZCk7CgkJCXJldHVybiAtMTsKCQl9CgkKCQlpbmNvbWluZ19tc2cgPSAoc3RydWN0IG5s bXNnaGRyICopa3ZwX3JlY3ZfYnVmZmVyOwoJCWluY29taW5nX2NuX21zZyA9IChzdHJ1Y3Qg Y25fbXNnICopTkxNU0dfREFUQShpbmNvbWluZ19tc2cpOwoKCQlpZiAoaW5jb21pbmdfY25f bXNnLT5zZXEgIT0gS1ZQX0tFUk5FTF9HRVQpIHsKCQkJY29udGludWU7CgkJfQoKCQlrZXlf bmFtZSA9IAoJCSgoc3RydWN0IGt2cF9tc2cgKilpbmNvbWluZ19jbl9tc2ctPmRhdGEpLT5r dnBfa2V5OwoJCWtleV92YWx1ZSA9CgkJKChzdHJ1Y3Qga3ZwX21zZyAqKWluY29taW5nX2Nu X21zZy0+ZGF0YSktPmt2cF92YWx1ZTsKCgkJc3dpdGNoIChrZXlfbmFtZSkgewoJCQljYXNl IEZ1bGx5UXVhbGlmaWVkRG9tYWluTmFtZToKCQkJCWt2cF9nZXRfZG9tYWluX25hbWUoa2V5 X3ZhbHVlLCBLVlBfVkFMVUVfU0laRSk7CgkJCQlicmVhazsKCQkJY2FzZSBOZXR3b3JrQWRk cmVzc0lQdjQ6CgkJCQlrdnBfZ2V0X2lwX2FkZHJlc3MoQUZfSU5FVCwga2V5X3ZhbHVlLCAK CQkJCQkJS1ZQX1ZBTFVFX1NJWkUpOwoJCQkJYnJlYWs7CgkJCWNhc2UgTmV0d29ya0FkZHJl c3NJUHY2OgoJCQkJa3ZwX2dldF9pcF9hZGRyZXNzKEFGX0lORVQ2LCBrZXlfdmFsdWUsIAoJ CQkJCQlLVlBfVkFMVUVfU0laRSk7CgkJCQlicmVhazsKCQkJY2FzZSBPU0J1aWxkTnVtYmVy OgoJCQkJc3RyY3B5KGtleV92YWx1ZSwgb3NfYnVpbGQpOwoJCQkJYnJlYWs7CgkJCWNhc2Ug T1NOYW1lOgoJCQkJc3RyY3B5KGtleV92YWx1ZSwgb3NfbmFtZSk7CgkJCQlicmVhazsKCQkJ Y2FzZSBPU01ham9yVmVyc2lvbjoKCQkJCXN0cmNweShrZXlfdmFsdWUsIG9zX21ham9yKTsK CQkJCWJyZWFrOwoJCQljYXNlIE9TTWlub3JWZXJzaW9uOgoJCQkJc3RyY3B5KGtleV92YWx1 ZSwgb3NfbWlub3IpOwoJCQkJYnJlYWs7CgkJCWNhc2UgT1NWZXJzaW9uOgoJCQkJc3RyY3B5 KGtleV92YWx1ZSwgb3NfYnVpbGQpOwoJCQkJYnJlYWs7CgkJCWNhc2UgUHJvY2Vzc29yQXJj aGl0ZWN0dXJlOgoJCQkJc3RyY3B5KGtleV92YWx1ZSwgcHJvY2Vzc29yX2FyY2gpOwoJCQkJ YnJlYWs7CgkJCWRlZmF1bHQ6CQoJCQkJc3RyY3B5KGtleV92YWx1ZSwgIlVua25vd24gS2V5 Iik7CgkJCQlicmVhazsKCQl9CgkJLyoKCQkgKiBTZW5kIHRoZSB2YWx1ZSBiYWNrIHRvIHRo ZSBrZXJuZWwuIFRoZSByZXNwb25zZSBpcyAKCQkgKiBhbHJlYWR5IGluIHRoZSByZWNlaXZl IGJ1ZmZlci4gVXBkYXRlIHRoZSBjbl9tc2cgaGVhZGVyIHRvIAoJCSAqIHJlZmxlY3QgdGhl IGtleSB2YWx1ZSB0aGF0IGhhcyBiZWVuIGFkZGVkIHRvIHRoZSBtZXNzYWdlCgkJICovCgoJ CWluY29taW5nX2NuX21zZy0+aWQuaWR4ID0gQ05fS1ZQX0lEWDsKCQlpbmNvbWluZ19jbl9t c2ctPmlkLnZhbCA9IENOX0tWUF9WQUw7CgkJaW5jb21pbmdfY25fbXNnLT5zZXEgPSBLVlBf VVNFUl9TRVQ7IAoJCWluY29taW5nX2NuX21zZy0+YWNrID0gMDsKCQlpbmNvbWluZ19jbl9t c2ctPmxlbiA9IEtWUF9LRVlfU0laRSArIHN0cmxlbihrZXlfdmFsdWUpOwoKCQlsZW4gPSBu ZXRsaW5rX3NlbmQoZmQsIGluY29taW5nX2NuX21zZyk7CgkJaWYgKGxlbiA8IDApIHsKCQkJ c3lzbG9nKExPR19FUlIsICJuZXRfbGluayBzZW5kIGZhaWxlZDsgZXJyb3I6JWQiLCBsZW4p OwoJCQlleGl0IC0xOwoJCX0KCX0KCn0K --------------080305010405040308070308 Content-Type: text/plain; name="Attached Message Part" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="Attached Message Part" _______________________________________________ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linux-foundation.org/mailman/listinfo/virtualization --------------080305010405040308070308--