Ci8qCiAqIElCTSBBU00gU2VydmljZSBQcm9jZXNzb3IgRGV2aWNlIERyaXZlcgogKgogKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeQogKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieQogKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXIgdmVyc2lvbiAyIG9mIHRoZSBMaWNlbnNlLCBvcgogKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZQogKiBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgogKgogKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZQogKiBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQogKiBGb3VuZGF0aW9uLCBJbmMuLCA1OSBUZW1wbGUgUGxhY2UgLSBTdWl0ZSAzMzAsIEJvc3RvbiwgTUEgMDIxMTEtMTMwNywgVVNBLgogKgogKiBDb3B5cmlnaHQgKEMpIElCTSBDb3Jwb3JhdGlvbiwgMjAwNAogKgogKiBBdXRob3I6IE1heCBBc2L2Y2sgPGFtYXhAdXMuaWJtLmNvbT4KICoKICovCgojaW5jbHVkZSAiaWJtYXNtLmgiCiNpbmNsdWRlICJsb3dsZXZlbC5oIgoKc3RhdGljIHZvaWQgZXhlY19uZXh0X2NvbW1hbmQoc3RydWN0IHNlcnZpY2VfcHJvY2Vzc29yICpzcCk7CgpzdGF0aWMgYXRvbWljX3QgY29tbWFuZF9jb3VudCA9IEFUT01JQ19JTklUKDApOwoKc3RydWN0IGNvbW1hbmQgKmlibWFzbV9uZXdfY29tbWFuZChzdHJ1Y3Qgc2VydmljZV9wcm9jZXNzb3IgKnNwLCBzaXplX3QgYnVmZmVyX3NpemUpCnsKCXN0cnVjdCBjb21tYW5kICpjbWQ7CgoJaWYgKGJ1ZmZlcl9zaXplID4gSUJNQVNNX0NNRF9NQVhfQlVGRkVSX1NJWkUpCgkJcmV0dXJuIE5VTEw7CgoJY21kID0ga3phbGxvYyhzaXplb2Yoc3RydWN0IGNvbW1hbmQpLCBHRlBfS0VSTkVMKTsKCWlmIChjbWQgPT0gTlVMTCkKCQlyZXR1cm4gTlVMTDsKCgoJY21kLT5idWZmZXIgPSBremFsbG9jKGJ1ZmZlcl9zaXplLCBHRlBfS0VSTkVMKTsKCWlmIChjbWQtPmJ1ZmZlciA9PSBOVUxMKSB7CgkJa2ZyZWUoY21kKTsKCQlyZXR1cm4gTlVMTDsKCX0KCWNtZC0+YnVmZmVyX3NpemUgPSBidWZmZXJfc2l6ZTsKCglrcmVmX2luaXQoJmNtZC0+a3JlZik7CgljbWQtPmxvY2sgPSAmc3AtPmxvY2s7CgoJY21kLT5zdGF0dXMgPSBJQk1BU01fQ01EX1BFTkRJTkc7Cglpbml0X3dhaXRxdWV1ZV9oZWFkKCZjbWQtPndhaXQpOwoJSU5JVF9MSVNUX0hFQUQoJmNtZC0+cXVldWVfbm9kZSk7CgoJYXRvbWljX2luYygmY29tbWFuZF9jb3VudCk7CglkYmcoImNvbW1hbmQgY291bnQ6ICVkXG4iLCBhdG9taWNfcmVhZCgmY29tbWFuZF9jb3VudCkpOwoKCXJldHVybiBjbWQ7Cn0KCnZvaWQgaWJtYXNtX2ZyZWVfY29tbWFuZChzdHJ1Y3Qga3JlZiAqa3JlZikKewoJc3RydWN0IGNvbW1hbmQgKmNtZCA9IHRvX2NvbW1hbmQoa3JlZik7CgoJbGlzdF9kZWwoJmNtZC0+cXVldWVfbm9kZSk7CglhdG9taWNfZGVjKCZjb21tYW5kX2NvdW50KTsKCWRiZygiY29tbWFuZCBjb3VudDogJWRcbiIsIGF0b21pY19yZWFkKCZjb21tYW5kX2NvdW50KSk7CglrZnJlZShjbWQtPmJ1ZmZlcik7CglrZnJlZShjbWQpOwp9CgpzdGF0aWMgdm9pZCBlbnF1ZXVlX2NvbW1hbmQoc3RydWN0IHNlcnZpY2VfcHJvY2Vzc29yICpzcCwgc3RydWN0IGNvbW1hbmQgKmNtZCkKewoJbGlzdF9hZGRfdGFpbCgmY21kLT5xdWV1ZV9ub2RlLCAmc3AtPmNvbW1hbmRfcXVldWUpOwp9CgpzdGF0aWMgc3RydWN0IGNvbW1hbmQgKmRlcXVldWVfY29tbWFuZChzdHJ1Y3Qgc2VydmljZV9wcm9jZXNzb3IgKnNwKQp7CglzdHJ1Y3QgY29tbWFuZCAqY21kOwoJc3RydWN0IGxpc3RfaGVhZCAqbmV4dDsKCglpZiAobGlzdF9lbXB0eSgmc3AtPmNvbW1hbmRfcXVldWUpKQoJCXJldHVybiBOVUxMOwoKCW5leHQgPSBzcC0+Y29tbWFuZF9xdWV1ZS5uZXh0OwoJbGlzdF9kZWxfaW5pdChuZXh0KTsKCWNtZCA9IGxpc3RfZW50cnkobmV4dCwgc3RydWN0IGNvbW1hbmQsIHF1ZXVlX25vZGUpOwoKCXJldHVybiBjbWQ7Cn0KCnN0YXRpYyBpbmxpbmUgdm9pZCBkb19leGVjX2NvbW1hbmQoc3RydWN0IHNlcnZpY2VfcHJvY2Vzc29yICpzcCkKewoJY2hhciB0c2J1ZlszMl07CgoJZGJnKCIlczolZCBhdCAlc1xuIiwgX19mdW5jX18sIF9fTElORV9fLCBnZXRfdGltZXN0YW1wKHRzYnVmKSk7CgoJaWYgKGlibWFzbV9zZW5kX2kyb19tZXNzYWdlKHNwKSkgewoJCXNwLT5jdXJyZW50X2NvbW1hbmQtPnN0YXR1cyA9IElCTUFTTV9DTURfRkFJTEVEOwoJCXdha2VfdXAoJnNwLT5jdXJyZW50X2NvbW1hbmQtPndhaXQpOwoJCWNvbW1hbmRfcHV0KHNwLT5jdXJyZW50X2NvbW1hbmQpOwoJCWV4ZWNfbmV4dF9jb21tYW5kKHNwKTsKCX0KfQoKLyoqCiAqIGV4ZWNfY29tbWFuZAogKiBzZW5kIGEgY29tbWFuZCB0byBhIHNlcnZpY2UgcHJvY2Vzc29yCiAqIENvbW1hbmRzIGFyZSBleGVjdXRlZCBzZXF1ZW50aWFsbHkuIE9uZSBjb21tYW5kIChzcC0+Y3VycmVudF9jb21tYW5kKQogKiBpcyBzZW50IHRvIHRoZSBzZXJ2aWNlIHByb2Nlc3Nvci4gT25jZSB0aGUgaW50ZXJydXB0IGhhbmRsZXIgZ2V0cyBhCiAqIG1lc3NhZ2Ugb2YgdHlwZSBjb21tYW5kX3Jlc3BvbnNlLCB0aGUgbWVzc2FnZSBpcyBjb3BpZWQgaW50bwogKiB0aGUgY3VycmVudCBjb21tYW5kcyBidWZmZXIsCiAqLwp2b2lkIGlibWFzbV9leGVjX2NvbW1hbmQoc3RydWN0IHNlcnZpY2VfcHJvY2Vzc29yICpzcCwgc3RydWN0IGNvbW1hbmQgKmNtZCkKewoJdW5zaWduZWQgbG9uZyBmbGFnczsKCWNoYXIgdHNidWZbMzJdOwoKCWRiZygiJXM6JWQgYXQgJXNcbiIsIF9fZnVuY19fLCBfX0xJTkVfXywgZ2V0X3RpbWVzdGFtcCh0c2J1ZikpOwoKCXNwaW5fbG9ja19pcnFzYXZlKCZzcC0+bG9jaywgZmxhZ3MpOwoKCWlmICghc3AtPmN1cnJlbnRfY29tbWFuZCkgewoJCXNwLT5jdXJyZW50X2NvbW1hbmQgPSBjbWQ7CgkJY29tbWFuZF9nZXQoc3AtPmN1cnJlbnRfY29tbWFuZCk7CgkJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmc3AtPmxvY2ssIGZsYWdzKTsKCQlkb19leGVjX2NvbW1hbmQoc3ApOwoJfSBlbHNlIHsKCQllbnF1ZXVlX2NvbW1hbmQoc3AsIGNtZCk7CgkJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmc3AtPmxvY2ssIGZsYWdzKTsKCX0KfQoKc3RhdGljIHZvaWQgZXhlY19uZXh0X2NvbW1hbmQoc3RydWN0IHNlcnZpY2VfcHJvY2Vzc29yICpzcCkKewoJdW5zaWduZWQgbG9uZyBmbGFnczsKCWNoYXIgdHNidWZbMzJdOwoKCWRiZygiJXM6JWQgYXQgJXNcbiIsIF9fZnVuY19fLCBfX0xJTkVfXywgZ2V0X3RpbWVzdGFtcCh0c2J1ZikpOwoKCXNwaW5fbG9ja19pcnFzYXZlKCZzcC0+bG9jaywgZmxhZ3MpOwoJc3AtPmN1cnJlbnRfY29tbWFuZCA9IGRlcXVldWVfY29tbWFuZChzcCk7CglpZiAoc3AtPmN1cnJlbnRfY29tbWFuZCkgewoJCWNvbW1hbmRfZ2V0KHNwLT5jdXJyZW50X2NvbW1hbmQpOwoJCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJnNwLT5sb2NrLCBmbGFncyk7CgkJZG9fZXhlY19jb21tYW5kKHNwKTsKCX0gZWxzZSB7CgkJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmc3AtPmxvY2ssIGZsYWdzKTsKCX0KfQoKLyoqCiAqIFNsZWVwIHVudGlsIGEgY29tbWFuZCBoYXMgZmFpbGVkIG9yIGEgcmVzcG9uc2UgaGFzIGJlZW4gcmVjZWl2ZWQKICogYW5kIHRoZSBjb21tYW5kIHN0YXR1cyBiZWVuIHVwZGF0ZWQgYnkgdGhlIGludGVycnVwdCBoYW5kbGVyLgogKiAoc2VlIHJlY2VpdmVfcmVzcG9uc2UpLgogKi8Kdm9pZCBpYm1hc21fd2FpdF9mb3JfcmVzcG9uc2Uoc3RydWN0IGNvbW1hbmQgKmNtZCwgaW50IHRpbWVvdXQpCnsKCXdhaXRfZXZlbnRfaW50ZXJydXB0aWJsZV90aW1lb3V0KGNtZC0+d2FpdCwKCQkJCWNtZC0+c3RhdHVzID09IElCTUFTTV9DTURfQ09NUExFVEUgfHwKCQkJCWNtZC0+c3RhdHVzID09IElCTUFTTV9DTURfRkFJTEVELAoJCQkJdGltZW91dCAqIEhaKTsKfQoKLyoqCiAqIHJlY2VpdmVfY29tbWFuZF9yZXNwb25zZQogKiBjYWxsZWQgYnkgdGhlIGludGVycnVwdCBoYW5kbGVyIHdoZW4gYSBkb3QgY29tbWFuZCBvZiB0eXBlIGNvbW1hbmRfcmVzcG9uc2UKICogd2FzIHJlY2VpdmVkLgogKi8Kdm9pZCBpYm1hc21fcmVjZWl2ZV9jb21tYW5kX3Jlc3BvbnNlKHN0cnVjdCBzZXJ2aWNlX3Byb2Nlc3NvciAqc3AsIHZvaWQgKnJlc3BvbnNlLCBzaXplX3Qgc2l6ZSkKewoJc3RydWN0IGNvbW1hbmQgKmNtZCA9IHNwLT5jdXJyZW50X2NvbW1hbmQ7CgoJaWYgKCFzcC0+Y3VycmVudF9jb21tYW5kKQoJCXJldHVybjsKCgltZW1jcHlfZnJvbWlvKGNtZC0+YnVmZmVyLCByZXNwb25zZSwgbWluKHNpemUsIGNtZC0+YnVmZmVyX3NpemUpKTsKCWNtZC0+c3RhdHVzID0gSUJNQVNNX0NNRF9DT01QTEVURTsKCXdha2VfdXAoJnNwLT5jdXJyZW50X2NvbW1hbmQtPndhaXQpOwoJY29tbWFuZF9wdXQoc3AtPmN1cnJlbnRfY29tbWFuZCk7CglleGVjX25leHRfY29tbWFuZChzcCk7Cn0K