Ci8qCiAqIElCTSBBU00gU2VydmljZSBQcm9jZXNzb3IgRGV2aWNlIERyaXZlcgogKgogKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeQogKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieQogKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXIgdmVyc2lvbiAyIG9mIHRoZSBMaWNlbnNlLCBvcgogKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZQogKiBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgogKgogKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZQogKiBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQogKiBGb3VuZGF0aW9uLCBJbmMuLCA1OSBUZW1wbGUgUGxhY2UgLSBTdWl0ZSAzMzAsIEJvc3RvbiwgTUEgMDIxMTEtMTMwNywgVVNBLgogKgogKiBDb3B5cmlnaHQgKEMpIElCTSBDb3Jwb3JhdGlvbiwgMjAwNAogKgogKiBBdXRob3I6IE1heCBBc2L2Y2sgPGFtYXhAdXMuaWJtLmNvbT4KICoKICovCgojaW5jbHVkZSAiaWJtYXNtLmgiCiNpbmNsdWRlICJsb3dsZXZlbC5oIgoKLyoKICogQVNNIHNlcnZpY2UgcHJvY2Vzc29yIGV2ZW50IGhhbmRsaW5nIHJvdXRpbmVzLgogKgogKiBFdmVudHMgYXJlIHNpZ25hbGxlZCB0byB0aGUgZGV2aWNlIGRyaXZlcnMgdGhyb3VnaCBpbnRlcnJ1cHRzLgogKiBUaGV5IGhhdmUgdGhlIGZvcm1hdCBvZiBkb3QgY29tbWFuZHMsIHdpdGggdGhlIHR5cGUgZmllbGQgc2V0IHRvCiAqIHNwX2V2ZW50LgogKiBUaGUgZHJpdmVyIGRvZXMgbm90IGludGVycHJldCB0aGUgZXZlbnRzLCBpdCBzaW1wbHkgc3RvcmVzIHRoZW0gaW4gYQogKiBjaXJjdWxhciBidWZmZXIuCiAqLwoKc3RhdGljIHZvaWQgd2FrZV91cF9ldmVudF9yZWFkZXJzKHN0cnVjdCBzZXJ2aWNlX3Byb2Nlc3NvciAqc3ApCnsKCXN0cnVjdCBldmVudF9yZWFkZXIgKnJlYWRlcjsKCglsaXN0X2Zvcl9lYWNoX2VudHJ5KHJlYWRlciwgJnNwLT5ldmVudF9idWZmZXItPnJlYWRlcnMsIG5vZGUpCiAgICAgICAgICAgICAgICB3YWtlX3VwX2ludGVycnVwdGlibGUoJnJlYWRlci0+d2FpdCk7Cn0KCi8qKgogKiByZWNlaXZlX2V2ZW50CiAqIENhbGxlZCBieSB0aGUgaW50ZXJydXB0IGhhbmRsZXIgd2hlbiBhIGRvdCBjb21tYW5kIG9mIHR5cGUgc3BfZXZlbnQgaXMKICogcmVjZWl2ZWQuCiAqIFN0b3JlIHRoZSBldmVudCBpbiB0aGUgY2lyY3VsYXIgZXZlbnQgYnVmZmVyLCB3YWtlIHVwIGFueSBzbGVlcGluZwogKiBldmVudCByZWFkZXJzLgogKiBUaGVyZSBpcyBubyByZWFkZXIgbWFya2VyIGluIHRoZSBidWZmZXIsIHRoZXJlZm9yZSByZWFkZXJzIGFyZQogKiByZXNwb25zaWJsZSBmb3Iga2VlcGluZyB1cCB3aXRoIHRoZSB3cml0ZXIsIG9yIHRoZXkgd2lsbCBsb3NlIGV2ZW50cy4KICovCnZvaWQgaWJtYXNtX3JlY2VpdmVfZXZlbnQoc3RydWN0IHNlcnZpY2VfcHJvY2Vzc29yICpzcCwgdm9pZCAqZGF0YSwgdW5zaWduZWQgaW50IGRhdGFfc2l6ZSkKewoJc3RydWN0IGV2ZW50X2J1ZmZlciAqYnVmZmVyID0gc3AtPmV2ZW50X2J1ZmZlcjsKCXN0cnVjdCBpYm1hc21fZXZlbnQgKmV2ZW50OwoJdW5zaWduZWQgbG9uZyBmbGFnczsKCglkYXRhX3NpemUgPSBtaW4oZGF0YV9zaXplLCBJQk1BU01fRVZFTlRfTUFYX1NJWkUpOwoKCXNwaW5fbG9ja19pcnFzYXZlKCZzcC0+bG9jaywgZmxhZ3MpOwoJLyogY29weSB0aGUgZXZlbnQgaW50byB0aGUgbmV4dCBzbG90IGluIHRoZSBjaXJjdWxhciBidWZmZXIgKi8KCWV2ZW50ID0gJmJ1ZmZlci0+ZXZlbnRzW2J1ZmZlci0+bmV4dF9pbmRleF07CgltZW1jcHlfZnJvbWlvKGV2ZW50LT5kYXRhLCBkYXRhLCBkYXRhX3NpemUpOwoJZXZlbnQtPmRhdGFfc2l6ZSA9IGRhdGFfc2l6ZTsKCWV2ZW50LT5zZXJpYWxfbnVtYmVyID0gYnVmZmVyLT5uZXh0X3NlcmlhbF9udW1iZXI7CgoJLyogYWR2YW5jZSBpbmRpY2VzIGluIHRoZSBidWZmZXIgKi8KCWJ1ZmZlci0+bmV4dF9pbmRleCA9IChidWZmZXItPm5leHRfaW5kZXggKyAxKSAlIElCTUFTTV9OVU1fRVZFTlRTOwoJYnVmZmVyLT5uZXh0X3NlcmlhbF9udW1iZXIrKzsKCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJnNwLT5sb2NrLCBmbGFncyk7CgoJd2FrZV91cF9ldmVudF9yZWFkZXJzKHNwKTsKfQoKc3RhdGljIGlubGluZSBpbnQgZXZlbnRfYXZhaWxhYmxlKHN0cnVjdCBldmVudF9idWZmZXIgKmIsIHN0cnVjdCBldmVudF9yZWFkZXIgKnIpCnsKCXJldHVybiAoci0+bmV4dF9zZXJpYWxfbnVtYmVyIDwgYi0+bmV4dF9zZXJpYWxfbnVtYmVyKTsKfQoKLyoqCiAqIGdldF9uZXh0X2V2ZW50CiAqIENhbGxlZCBieSBldmVudCByZWFkZXJzIChpbml0aWF0ZWQgZnJvbSB1c2VyIHNwYWNlIHRocm91Z2ggdGhlIGZpbGUKICogc3lzdGVtKS4KICogU2xlZXBzIHVudGlsIGEgbmV3IGV2ZW50IGlzIGF2YWlsYWJsZS4KICovCmludCBpYm1hc21fZ2V0X25leHRfZXZlbnQoc3RydWN0IHNlcnZpY2VfcHJvY2Vzc29yICpzcCwgc3RydWN0IGV2ZW50X3JlYWRlciAqcmVhZGVyKQp7CglzdHJ1Y3QgZXZlbnRfYnVmZmVyICpidWZmZXIgPSBzcC0+ZXZlbnRfYnVmZmVyOwoJc3RydWN0IGlibWFzbV9ldmVudCAqZXZlbnQ7Cgl1bnNpZ25lZCBpbnQgaW5kZXg7Cgl1bnNpZ25lZCBsb25nIGZsYWdzOwoKCXJlYWRlci0+Y2FuY2VsbGVkID0gMDsKCglpZiAod2FpdF9ldmVudF9pbnRlcnJ1cHRpYmxlKHJlYWRlci0+d2FpdCwKCQkJZXZlbnRfYXZhaWxhYmxlKGJ1ZmZlciwgcmVhZGVyKSB8fCByZWFkZXItPmNhbmNlbGxlZCkpCgkJcmV0dXJuIC1FUkVTVEFSVFNZUzsKCglpZiAoIWV2ZW50X2F2YWlsYWJsZShidWZmZXIsIHJlYWRlcikpCgkJcmV0dXJuIDA7CgoJc3Bpbl9sb2NrX2lycXNhdmUoJnNwLT5sb2NrLCBmbGFncyk7CgoJaW5kZXggPSBidWZmZXItPm5leHRfaW5kZXg7CglldmVudCA9ICZidWZmZXItPmV2ZW50c1tpbmRleF07Cgl3aGlsZSAoZXZlbnQtPnNlcmlhbF9udW1iZXIgPCByZWFkZXItPm5leHRfc2VyaWFsX251bWJlcikgewoJCWluZGV4ID0gKGluZGV4ICsgMSkgJSBJQk1BU01fTlVNX0VWRU5UUzsKCQlldmVudCA9ICZidWZmZXItPmV2ZW50c1tpbmRleF07Cgl9CgltZW1jcHkocmVhZGVyLT5kYXRhLCBldmVudC0+ZGF0YSwgZXZlbnQtPmRhdGFfc2l6ZSk7CglyZWFkZXItPmRhdGFfc2l6ZSA9IGV2ZW50LT5kYXRhX3NpemU7CglyZWFkZXItPm5leHRfc2VyaWFsX251bWJlciA9IGV2ZW50LT5zZXJpYWxfbnVtYmVyICsgMTsKCglzcGluX3VubG9ja19pcnFyZXN0b3JlKCZzcC0+bG9jaywgZmxhZ3MpOwoKCXJldHVybiBldmVudC0+ZGF0YV9zaXplOwp9Cgp2b2lkIGlibWFzbV9jYW5jZWxfbmV4dF9ldmVudChzdHJ1Y3QgZXZlbnRfcmVhZGVyICpyZWFkZXIpCnsKICAgICAgICByZWFkZXItPmNhbmNlbGxlZCA9IDE7CiAgICAgICAgd2FrZV91cF9pbnRlcnJ1cHRpYmxlKCZyZWFkZXItPndhaXQpOwp9Cgp2b2lkIGlibWFzbV9ldmVudF9yZWFkZXJfcmVnaXN0ZXIoc3RydWN0IHNlcnZpY2VfcHJvY2Vzc29yICpzcCwgc3RydWN0IGV2ZW50X3JlYWRlciAqcmVhZGVyKQp7Cgl1bnNpZ25lZCBsb25nIGZsYWdzOwoKCXJlYWRlci0+bmV4dF9zZXJpYWxfbnVtYmVyID0gc3AtPmV2ZW50X2J1ZmZlci0+bmV4dF9zZXJpYWxfbnVtYmVyOwoJaW5pdF93YWl0cXVldWVfaGVhZCgmcmVhZGVyLT53YWl0KTsKCXNwaW5fbG9ja19pcnFzYXZlKCZzcC0+bG9jaywgZmxhZ3MpOwoJbGlzdF9hZGQoJnJlYWRlci0+bm9kZSwgJnNwLT5ldmVudF9idWZmZXItPnJlYWRlcnMpOwoJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmc3AtPmxvY2ssIGZsYWdzKTsKfQoKdm9pZCBpYm1hc21fZXZlbnRfcmVhZGVyX3VucmVnaXN0ZXIoc3RydWN0IHNlcnZpY2VfcHJvY2Vzc29yICpzcCwgc3RydWN0IGV2ZW50X3JlYWRlciAqcmVhZGVyKQp7Cgl1bnNpZ25lZCBsb25nIGZsYWdzOwoKCXNwaW5fbG9ja19pcnFzYXZlKCZzcC0+bG9jaywgZmxhZ3MpOwoJbGlzdF9kZWwoJnJlYWRlci0+bm9kZSk7CglzcGluX3VubG9ja19pcnFyZXN0b3JlKCZzcC0+bG9jaywgZmxhZ3MpOwp9CgppbnQgaWJtYXNtX2V2ZW50X2J1ZmZlcl9pbml0KHN0cnVjdCBzZXJ2aWNlX3Byb2Nlc3NvciAqc3ApCnsKCXN0cnVjdCBldmVudF9idWZmZXIgKmJ1ZmZlcjsKCXN0cnVjdCBpYm1hc21fZXZlbnQgKmV2ZW50OwoJaW50IGk7CgoJYnVmZmVyID0ga21hbGxvYyhzaXplb2Yoc3RydWN0IGV2ZW50X2J1ZmZlciksIEdGUF9LRVJORUwpOwoJaWYgKCFidWZmZXIpCgkJcmV0dXJuIDE7CgoJYnVmZmVyLT5uZXh0X2luZGV4ID0gMDsKCWJ1ZmZlci0+bmV4dF9zZXJpYWxfbnVtYmVyID0gMTsKCglldmVudCA9IGJ1ZmZlci0+ZXZlbnRzOwoJZm9yIChpPTA7IGk8SUJNQVNNX05VTV9FVkVOVFM7IGkrKywgZXZlbnQrKykKCQlldmVudC0+c2VyaWFsX251bWJlciA9IDA7CgoJSU5JVF9MSVNUX0hFQUQoJmJ1ZmZlci0+cmVhZGVycyk7CgoJc3AtPmV2ZW50X2J1ZmZlciA9IGJ1ZmZlcjsKCglyZXR1cm4gMDsKfQoKdm9pZCBpYm1hc21fZXZlbnRfYnVmZmVyX2V4aXQoc3RydWN0IHNlcnZpY2VfcHJvY2Vzc29yICpzcCkKewoJa2ZyZWUoc3AtPmV2ZW50X2J1ZmZlcik7Cn0K