From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=0.2 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, NICE_REPLY_A,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.4 Received: (qmail 10446 invoked from network); 29 Jun 2022 17:53:07 -0000 Received: from 9front.inri.net (168.235.81.73) by inbox.vuxu.org with ESMTPUTF8; 29 Jun 2022 17:53:07 -0000 Received: from mail.posixcafe.org ([45.76.19.58]) by 9front; Wed Jun 29 13:50:54 -0400 2022 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=posixcafe.org; s=20200506; t=1656525050; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=Fqtykf9YM00zXNp07eV+QHhdP5rixs73nvCQBCyckTk=; b=BCBVZdLpQDnFLSiucK/aZDVxSF4DG6YD9lRawh3odaQoaLITLOYSHS1Gad8DleszIfcpx/ v/UK/pAX+E5PR4gzLKWGNxAhYcaptuOtYE+D/2pxROd4ZjIbbiij0QeKu/UnRHxm4HWikP f6/BLXevsrV21a1H4PmbbZzIaiID8O4= Received: from [192.168.168.200] (161-97-228-135.lpcnextlight.net [161.97.228.135]) by mail.posixcafe.org (OpenSMTPD) with ESMTPSA id 6e62f56c (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO) for <9front@9front.org>; Wed, 29 Jun 2022 12:50:49 -0500 (CDT) Content-Type: multipart/mixed; boundary="------------EVmRT7AVLMLBltOkPMklqYR3" Message-ID: <88b93657-5d28-2309-4e43-0cba952fdf20@posixcafe.org> Date: Wed, 29 Jun 2022 11:50:42 -0600 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.10.0 Content-Language: en-US To: 9front@9front.org References: <24C7FAF56B76BEDB07410AED72ADD298@felloff.net> From: Jacob Moody In-Reply-To: <24C7FAF56B76BEDB07410AED72ADD298@felloff.net> List-ID: <9front.9front.org> List-Help: X-Glyph: ➈ X-Bullshit: self-healing immutable polling-aware firewall-oriented generator Subject: Re: [9front] [PATCH] Permissions for child boards in /srv Reply-To: 9front@9front.org Precedence: bulk This is a multi-part message in MIME format. --------------EVmRT7AVLMLBltOkPMklqYR3 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit On 6/29/22 11:20, cinap_lenrek@felloff.net wrote: >> It's disheartening you feel this way. > > sorry, but this code runs on all our computers. > You're correct, I am being disrespectful to others. >> I will begin the process of reverting all of my commits >> from the past month or so. > > no. its just devsrv.c. reverted. I had incorrectly assumed you wanted all the stuff I'd been working on teared out. > > the reason i lost faith is that the patch changes > alot more than you said in the message. My apologies, the message was only intended to cover the delta from the previous post. This wasn't clear so I understand your lose of faith. The 'other bits' of that code are doing what the subject, and first couple of posts detail. Which is allowing permissions to be set on to child service directories to restrict access. Here's the patch in total now against the now reverted version in tree, happy to provide more context. Since this is more or less a full rewrite, I've included the full devsrv.c as an attachment if that is easier to dig through. Thanks, moody diff cac03f355caa29a6bd5cafd7d0d6ca362149cb27 uncommitted --- a//sys/man/3/srv +++ b//sys/man/3/srv @@ -5,6 +5,8 @@ .nf .B bind #s /srv +.BI #s/ clone +.BI #s/ n .BI #s/ service1 .BI #s/ service2 ... @@ -12,7 +14,7 @@ .SH DESCRIPTION The .I srv -device provides a one-level directory holding +device provides a tree of directories holding already-open channels to services. In effect, .I srv @@ -40,6 +42,18 @@ .PP It is an error to write more than one number into a server file, or to create a file with a name that is already being used. +.PP +Opening the +.I clone +file allocates a new service directory. Reading +.I clone +returns the id of the new directory. This new service +directory can then be accessed at +.BR /srv/id . +Directories are recursable; each new service directory +contains its own +.I clone +file. .SH EXAMPLE To drop one end of a pipe into .BR /srv , --- a//sys/src/9/port/devsrv.c +++ b//sys/src/9/port/devsrv.c @@ -5,61 +5,220 @@ #include "fns.h" #include "../port/error.h" +#include "netif.h" -typedef struct Srv Srv; -struct Srv +typedef struct Link Link; +struct Link { - char *name; + void *link; + char *name; + ulong path; char *owner; ulong perm; +}; + +typedef struct Srv Srv; +struct Srv +{ + Link; Chan *chan; - Srv *link; - ulong path; }; -static QLock srvlk; -static Srv *srv; -static int qidpath; +typedef struct Board Board; +struct Board +{ + Link; + RWlock; + Ref; -static Srv* -srvlookup(char *name, ulong qidpath) + Board *parent; + Board *child; + Srv *srv; + long id; + int qidpath; + int closed; +}; + +struct{ + QLock; + long path; +} boards; + +enum{ + Qroot, + Qclone, + Qlease, + + Qend, +}; + +Board root; + +static char Eexpired[] = "expired lease"; + +static void* +lookup(Link *l, char *name, ulong qidpath) { - Srv *sp; + Link *lp; - for(sp = srv; sp != nil; sp = sp->link) { - if(sp->path == qidpath || (name != nil && strcmp(sp->name, name) == 0)) - return sp; + if(qidpath != ~0UL) + qidpath = NETTYPE(qidpath); + for(lp = l; lp != nil; lp = lp->link){ + if(qidpath != ~0UL && lp->path == qidpath) + return lp; + if(name != nil && strcmp(lp->name, name) == 0) + return lp; } return nil; } +static void* +remove(Link **l, char *name, ulong qidpath) +{ + Link *lp; + Link **last; + + if(qidpath != ~0UL) + qidpath = NETTYPE(qidpath); + last = l; + for(lp = *l; lp != nil; lp = lp->link){ + if(qidpath != ~0UL && lp->path == qidpath) + break; + if(name != nil && strcmp(lp->name, name) == 0) + break; + last = &lp->link; + } + if(lp == nil) + return nil; + + *last = lp->link; + lp->link = nil; + return lp; +} + +static void +boardclunk(Board *b, int close) +{ + Srv *sp, *prv; + Board *ch; + long ref; + + /* caller holds a wlock */ + if(b == &root){ + wunlock(b); + return; + } + + if(close){ + assert(b->closed == 0); + b->closed++; + for(sp = b->srv; sp != nil; sp = prv){ + prv = sp->link; + free(sp->owner); + free(sp->name); + if(sp->chan != nil) + cclose(sp->chan); + free(sp); + } + b->srv = nil; + } + ref = decref(b); + + /* + * All boards must be walkable from root. So a board + * is allowed to sit at zero references as long as it + * still has active children. For leaf nodes we then + * have to walk up the tree to clear now empty parents. + */ + while(b->closed && b->child == nil && ref == 0){ + //Root should never be closed + assert(b->parent != nil); + wlock(b->parent); + ch = remove((Link**)&b->parent->child, b->name, b->path); + assert(ch == b); + + b = ch->parent; + free(ch->name); + free(ch->owner); + wunlock(ch); + free(ch); + } + wunlock(b); +} + static int srvgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp) { Srv *sp; + Board *b, *ch; Qid q; - if(s == DEVDOTDOT){ - devdir(c, c->qid, "#s", 0, eve, 0555, dp); - return 1; + if(name != nil && strlen(name) >= sizeof(up->genbuf)) + return -1; + + b = c->aux; + ch = nil; + mkqid(&q, ~0L, 0, QTFILE); + rlock(b); + if(waserror()){ + runlock(b); + nexterror(); } + switch(s){ + case -2: /* dot */ + ch = b; + goto Child; + case DEVDOTDOT: + ch = b->parent; + if(ch == nil) + ch = &root; + goto Child; + } + if(name != nil){ + if(strcmp("clone", name) == 0) + goto Clone; - qlock(&srvlk); - if(name != nil) - sp = srvlookup(name, -1); - else { - for(sp = srv; sp != nil && s > 0; sp = sp->link) + sp = lookup(b->srv, name, ~0UL); + if(sp == nil) + ch = lookup(b->child, name, ~0UL); + } else { + if(s == 0) + goto Clone; + s--; + for(sp = b->srv; sp != nil && s > 0; sp = sp->link) s--; + for(ch = b->child; ch != nil && s > 0; ch = ch->link) + s--; } - if(sp == nil || (name != nil && (strlen(sp->name) >= sizeof(up->genbuf)))) { - qunlock(&srvlk); + if(sp != nil){ + kstrcpy(up->genbuf, sp->name, sizeof up->genbuf); + q.vers = NETID(c->qid.path); + q.path = NETQID(q.vers, sp->path); + devdir(c, q, up->genbuf, 0, sp->owner, sp->perm, dp); + } else if(ch != nil){ +Child: + if(name != nil || s == DEVDOTDOT){ + devpermcheck(ch->owner, ch->perm, OEXEC); + c->aux = ch; + } + kstrcpy(up->genbuf, ch->name, sizeof up->genbuf); + q.vers = ch->id; + q.path = NETQID(q.vers, ch->path); + q.type = QTDIR; + devdir(c, q, up->genbuf, 0, ch->owner, ch->perm|DMDIR, dp); + } else if(0){ +Clone: + q.vers = NETID(c->qid.path); + q.path = NETQID(q.vers, Qclone); + devdir(c, q, "clone", 0, eve, 0444, dp); + } else { + runlock(b); + poperror(); return -1; } - mkqid(&q, sp->path, 0, QTFILE); - /* make sure name string continues to exist after we release lock */ - kstrcpy(up->genbuf, sp->name, sizeof up->genbuf); - devdir(c, q, up->genbuf, 0, sp->owner, sp->perm, dp); - qunlock(&srvlk); + + runlock(b); + poperror(); return 1; } @@ -66,24 +225,54 @@ static void srvinit(void) { - qidpath = 1; + root.qidpath = Qend; + root.name = "#s"; + root.perm = 0777; + kstrdup(&root.owner, eve); } static Chan* srvattach(char *spec) { - return devattach('s', spec); + Chan *c; + + c = devattach('s', spec); + c->aux = &root; + return c; } static Walkqid* srvwalk(Chan *c, Chan *nc, char **name, int nname) { - return devwalk(c, nc, name, nname, 0, 0, srvgen); + Board *b; + Walkqid *wq; + + wq = devwalk(c, nc, name, nname, 0, 0, srvgen); + if(wq == nil || wq->clone == nil) + return wq; + + b = wq->clone->aux; + if(b == &root) + return wq; + + incref(b); + return wq; } static int srvstat(Chan *c, uchar *db, int n) { + Dir d; + + /* devstat cheats for dir stats, we care about our dir perms */ + if(c->qid.type == QTDIR){ + srvgen(c, nil, nil, 0, -2, &d); + n = convD2M(&d, db, n); + if(n == 0) + error(Ebadarg); + return n; + } + return devstat(c, db, n, 0, 0, srvgen); } @@ -90,12 +279,14 @@ char* srvname(Chan *c) { + Board *b; Srv *sp; char *s; s = nil; - qlock(&srvlk); - for(sp = srv; sp != nil; sp = sp->link) { + b = &root; + rlock(b); + for(sp = b->srv; sp != nil; sp = sp->link) { if(sp->chan == c){ s = malloc(3+strlen(sp->name)+1); if(s != nil) @@ -103,7 +294,7 @@ break; } } - qunlock(&srvlk); + runlock(b); return s; } @@ -110,33 +301,73 @@ static Chan* srvopen(Chan *c, int omode) { + Board *b, *ch; Srv *sp; Chan *nc; + char buf[64]; + if(omode&OTRUNC) + error(Eexist); + if(omode&ORCLOSE) + error(Eperm); + + b = c->aux; + if(NETTYPE(c->qid.path) == Qclone){; + wlock(b); + if(b->closed){ + wunlock(b); + error(Eexpired); + } + ch = smalloc(sizeof *ch); + ch->qidpath = Qend; + ch->ref = 1; + ch->perm = 0770; + kstrdup(&ch->owner, up->user); + do { + qlock(&boards); + ch->id = ++boards.path; + qunlock(&boards); + snprint(buf, sizeof buf, "%ld", ch->id); + } while(lookup(b->srv, buf, ~0UL) != nil); + + ch->parent = b; + ch->path = b->qidpath++; + kstrdup(&ch->name, buf); + + ch->link = b->child; + b->child = ch; + c->aux = ch; + c->qid.vers = ch->id; + c->qid.path = NETQID(ch->id, Qlease); + boardclunk(b, 0); //unlock + return c; + } + + rlock(b); + if(waserror()){ + runlock(b); + nexterror(); + } if(c->qid.type == QTDIR){ if(omode & ORCLOSE) error(Eperm); if(omode != OREAD) error(Eisdir); + devpermcheck(b->owner, b->perm, omode); c->mode = omode; c->flag |= COPEN; c->offset = 0; + runlock(b); + poperror(); return c; } - qlock(&srvlk); - if(waserror()){ - qunlock(&srvlk); - nexterror(); - } + if(b->closed) + error(Eexpired); - sp = srvlookup(nil, c->qid.path); + sp = lookup(b->srv, nil, c->qid.path); if(sp == nil || sp->chan == nil) error(Eshutdown); - if(omode&OTRUNC) - error(Eexist); - if(omode&ORCLOSE) - error(Eperm); if(openmode(omode)!=sp->chan->mode && sp->chan->mode!=ORDWR) error(Eperm); devpermcheck(sp->owner, sp->perm, omode); @@ -144,7 +375,7 @@ nc = sp->chan; incref(nc); - qunlock(&srvlk); + runlock(b); poperror(); cclose(c); @@ -154,6 +385,7 @@ static Chan* srvcreate(Chan *c, char *name, int omode, ulong perm) { + Board *b; Srv *sp; if(openmode(omode) != OWRITE) @@ -162,31 +394,41 @@ if(strlen(name) >= sizeof(up->genbuf)) error(Etoolong); + if(strcmp("clone", name) == 0) + error("reserved name"); + sp = smalloc(sizeof *sp); kstrdup(&sp->name, name); kstrdup(&sp->owner, up->user); - qlock(&srvlk); + b = c->aux; + wlock(b); if(waserror()){ - qunlock(&srvlk); + wunlock(b); free(sp->owner); free(sp->name); free(sp); nexterror(); } - if(srvlookup(name, -1) != nil) + if(b->closed) + error(Eexpired); + devpermcheck(b->owner, b->perm, OWRITE); + if(lookup(b->srv, name, ~0UL) != nil) error(Eexist); + if(lookup(b->child, name, ~0UL) != nil) + error(Eexist); sp->perm = perm&0777; - sp->path = qidpath++; + sp->path = b->qidpath++; - c->qid.path = sp->path; + c->qid.path = NETQID(b->id, sp->path); + c->qid.vers = b->id; c->qid.type = QTFILE; - sp->link = srv; - srv = sp; + sp->link = b->srv; + b->srv = sp; - qunlock(&srvlk); + wunlock(b); poperror(); c->flag |= COPEN; @@ -198,41 +440,33 @@ static void srvremove(Chan *c) { - Srv *sp, **l; + Board *b; + Srv *sp; - if(c->qid.type == QTDIR) - error(Eperm); - - qlock(&srvlk); + b = c->aux; + wlock(b); if(waserror()){ - qunlock(&srvlk); + boardclunk(b, 0); //unlock nexterror(); } - l = &srv; - for(sp = *l; sp != nil; sp = *l) { - if(sp->path == c->qid.path) - break; - l = &sp->link; + if(c->qid.type == QTDIR) + error(Eperm); + switch(NETTYPE(c->qid.path)){ + case Qlease: + case Qclone: + error(Eperm); } + + sp = lookup(b->srv, nil, c->qid.path); if(sp == nil) error(Enonexist); - /* - * Only eve can remove system services. - */ - if(strcmp(sp->owner, eve) == 0 && !iseve()) + if(strcmp(sp->owner, up->user) != 0 && !iseve()) error(Eperm); - /* - * No removing personal services. - */ - if((sp->perm&7) != 7 && strcmp(sp->owner, up->user) && !iseve()) - error(Eperm); + remove((Link**)&b->srv, nil, c->qid.path); - *l = sp->link; - sp->link = nil; - - qunlock(&srvlk); + boardclunk(b, 0); //unlock poperror(); if(sp->chan != nil) @@ -245,12 +479,18 @@ static int srvwstat(Chan *c, uchar *dp, int n) { + Board *b, *s; char *strs; - Srv *sp; Dir d; + Link *lp; - if(c->qid.type & QTDIR) + switch(NETTYPE(c->qid.path)){ + case Qlease: + case Qclone: error(Eperm); + } + if(c->qid.type == QTDIR && c->aux == &root) + error(Eperm); strs = smalloc(n); if(waserror()){ @@ -261,32 +501,60 @@ if(n == 0) error(Eshortstat); - qlock(&srvlk); + b = c->aux; + wlock(b); if(waserror()){ - qunlock(&srvlk); + wunlock(b); nexterror(); } + if(b->closed) + error(Eexpired); - sp = srvlookup(nil, c->qid.path); - if(sp == nil) + if(c->qid.type == QTDIR){ + lp = b; + /* we share ownership of our stats with our parent */ + assert(b->parent != nil); + wlock(b->parent); + if(waserror()){ + wunlock(b->parent); + nexterror(); + } + } else + lp = lookup(b->srv, nil, c->qid.path); + if(lp == nil) error(Enonexist); - if(strcmp(sp->owner, up->user) != 0 && !iseve()) + if(strcmp(lp->owner, up->user) != 0 && !iseve()) error(Eperm); - if(d.name != nil && *d.name && strcmp(sp->name, d.name) != 0) { + if(d.name != nil && *d.name && strcmp(lp->name, d.name) != 0) { if(strchr(d.name, '/') != nil) error(Ebadchar); if(strlen(d.name) >= sizeof(up->genbuf)) error(Etoolong); - kstrdup(&sp->name, d.name); + + //Ensure new name doesn't conflict with old names + if(c->qid.type == QTDIR) + s = b->parent; + else + s = b; + if(lookup(s->srv, d.name, ~0UL) != nil) + error(Eexist); + if(lookup(s->child, d.name, ~0UL) != nil) + error(Eexist); + kstrdup(&lp->name, d.name); } if(d.uid != nil && *d.uid) - kstrdup(&sp->owner, d.uid); + kstrdup(&lp->owner, d.uid); if(d.mode != ~0UL) - sp->perm = d.mode & 0777; + lp->perm = d.mode & 0777; - qunlock(&srvlk); + if(c->qid.type == QTDIR){ + wunlock(b->parent); + poperror(); + } + + wunlock(b); poperror(); free(strs); @@ -298,22 +566,47 @@ static void srvclose(Chan *c) { - /* - * in theory we need to override any changes in removability - * since open, but since all that's checked is the owner, - * which is immutable, all is well. - */ - if(c->flag & CRCLOSE){ + Board *b; + int expired; + + expired = 0; + if(NETTYPE(c->qid.path) == Qlease) + expired++; + else if(c->flag & CRCLOSE){ + /* + * in theory we need to override any changes in removability + * since open, but since all that's checked is the owner, + * which is immutable, all is well. + */ if(waserror()) return; srvremove(c); poperror(); + return; } + + b = c->aux; + wlock(b); + boardclunk(b, expired); //unlock } static long -srvread(Chan *c, void *va, long n, vlong) +srvread(Chan *c, void *va, long n, vlong off) { + Board *b; + + if(NETTYPE(c->qid.path) == Qlease){ + b = c->aux; + rlock(b); + if(waserror()){ + runlock(b); + nexterror(); + } + n = readstr((ulong)off, va, n, b->name); + runlock(b); + poperror(); + return n; + } isdir(c); return devdirread(c, va, n, 0, 0, srvgen); } @@ -321,11 +614,15 @@ static long srvwrite(Chan *c, void *va, long n, vlong) { + Board *b; Srv *sp; Chan *c1; int fd; char buf[32]; + if(NETTYPE(c->qid.path) == Qlease) + error(Eperm); + if(n >= sizeof buf) error(Etoobig); memmove(buf, va, n); /* so we can NUL-terminate */ @@ -334,15 +631,18 @@ c1 = fdtochan(fd, -1, 0, 1); /* error check and inc ref */ - qlock(&srvlk); + b = c->aux; + wlock(b); if(waserror()) { - qunlock(&srvlk); + wunlock(b); cclose(c1); nexterror(); } + if(b->closed) + error(Eexpired); if(c1->qid.type & QTAUTH) error("cannot post auth file in srv"); - sp = srvlookup(nil, c->qid.path); + sp = lookup(b->srv, nil, c->qid.path); if(sp == nil) error(Enonexist); @@ -351,7 +651,7 @@ sp->chan = c1; - qunlock(&srvlk); + wunlock(b); poperror(); return n; } @@ -380,12 +680,15 @@ void srvrenameuser(char *old, char *new) { + Board *b; Srv *sp; - qlock(&srvlk); - for(sp = srv; sp != nil; sp = sp->link) { + b = &root; + wlock(b); + kstrdup(&b->owner, new); + for(sp = b->srv; sp != nil; sp = sp->link) { if(sp->owner != nil && strcmp(old, sp->owner) == 0) kstrdup(&sp->owner, new); } - qunlock(&srvlk); + wunlock(b); } --------------EVmRT7AVLMLBltOkPMklqYR3 Content-Type: multipart/mixed; boundary="upas-mqdzvdyaqpywwsvvpzbhbyfzds" Content-Disposition: inline This is a multi-part message in MIME format. --upas-mqdzvdyaqpywwsvvpzbhbyfzds Content-Disposition: inline Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit from postmaster@9front: The following attachment had content that we can't prove to be harmless. To avoid possible automatic execution, we changed the content headers. The original header was: Content-Type: text/x-csrc; charset=UTF-8; name="devsrv.c" Content-Disposition: attachment; filename="devsrv.c" Content-Transfer-Encoding: base64 --upas-mqdzvdyaqpywwsvvpzbhbyfzds Content-Type: application/octet-stream Content-Disposition: attachment; filename="devsrv.c.suspect" Content-Transfer-Encoding: base64 I2luY2x1ZGUJInUuaCIKI2luY2x1ZGUJIi4uL3BvcnQvbGliLmgiCiNpbmNsdWRlCSJtZW0u aCIKI2luY2x1ZGUJImRhdC5oIgojaW5jbHVkZQkiZm5zLmgiCiNpbmNsdWRlCSIuLi9wb3J0 L2Vycm9yLmgiCgojaW5jbHVkZQkibmV0aWYuaCIKCnR5cGVkZWYgc3RydWN0IExpbmsgTGlu azsKc3RydWN0IExpbmsKewoJdm9pZCAJKmxpbms7CgljaGFyIAkqbmFtZTsKCXVsb25nIAlw YXRoOwoJY2hhcgkqb3duZXI7Cgl1bG9uZwlwZXJtOwp9OwoKdHlwZWRlZiBzdHJ1Y3QgU3J2 IFNydjsKc3RydWN0IFNydgp7CglMaW5rOwoJQ2hhbgkqY2hhbjsKfTsKCnR5cGVkZWYgc3Ry dWN0IEJvYXJkIEJvYXJkOwpzdHJ1Y3QgQm9hcmQKewoJTGluazsKCVJXbG9jazsKCVJlZjsK CglCb2FyZCAJKnBhcmVudDsKCUJvYXJkIAkqY2hpbGQ7CglTcnYgCSpzcnY7Cglsb25nCWlk OwoJaW50CXFpZHBhdGg7CglpbnQgCWNsb3NlZDsJCn07CgpzdHJ1Y3R7CglRTG9jazsKCWxv bmcgcGF0aDsKfSBib2FyZHM7CgplbnVtewoJUXJvb3QsCglRY2xvbmUsCglRbGVhc2UsCgoJ UWVuZCwKfTsKCkJvYXJkIHJvb3Q7CgpzdGF0aWMgY2hhciBFZXhwaXJlZFtdID0gImV4cGly ZWQgbGVhc2UiOwoKc3RhdGljIHZvaWQqCmxvb2t1cChMaW5rICpsLCBjaGFyICpuYW1lLCB1 bG9uZyBxaWRwYXRoKQp7CglMaW5rICpscDsKCglpZihxaWRwYXRoICE9IH4wVUwpCgkJcWlk cGF0aCA9IE5FVFRZUEUocWlkcGF0aCk7Cglmb3IobHAgPSBsOyBscCAhPSBuaWw7IGxwID0g bHAtPmxpbmspewoJCWlmKHFpZHBhdGggIT0gfjBVTCAmJiBscC0+cGF0aCA9PSBxaWRwYXRo KQoJCQlyZXR1cm4gbHA7CgkJaWYobmFtZSAhPSBuaWwgJiYgc3RyY21wKGxwLT5uYW1lLCBu YW1lKSA9PSAwKQoJCQlyZXR1cm4gbHA7Cgl9CglyZXR1cm4gbmlsOwp9CgpzdGF0aWMgdm9p ZCoKcmVtb3ZlKExpbmsgKipsLCBjaGFyICpuYW1lLCB1bG9uZyBxaWRwYXRoKQp7CglMaW5r ICpscDsKCUxpbmsgKipsYXN0OwoKCWlmKHFpZHBhdGggIT0gfjBVTCkKCQlxaWRwYXRoID0g TkVUVFlQRShxaWRwYXRoKTsKCWxhc3QgPSBsOwoJZm9yKGxwID0gKmw7IGxwICE9IG5pbDsg bHAgPSBscC0+bGluayl7CgkJaWYocWlkcGF0aCAhPSB+MFVMICYmIGxwLT5wYXRoID09IHFp ZHBhdGgpCgkJCWJyZWFrOwoJCWlmKG5hbWUgIT0gbmlsICYmIHN0cmNtcChscC0+bmFtZSwg bmFtZSkgPT0gMCkKCQkJYnJlYWs7CgkJbGFzdCA9ICZscC0+bGluazsKCX0KCWlmKGxwID09 IG5pbCkKCQlyZXR1cm4gbmlsOwoKCSpsYXN0ID0gbHAtPmxpbms7CglscC0+bGluayA9IG5p bDsKCXJldHVybiBscDsKfQoKc3RhdGljIHZvaWQKYm9hcmRjbHVuayhCb2FyZCAqYiwgaW50 IGNsb3NlKQp7CglTcnYgKnNwLCAqcHJ2OwoJQm9hcmQgKmNoOwoJbG9uZyByZWY7CgoJLyog Y2FsbGVyIGhvbGRzIGEgd2xvY2sgKi8KCWlmKGIgPT0gJnJvb3QpewoJCXd1bmxvY2soYik7 CgkJcmV0dXJuOwoJfQoKCWlmKGNsb3NlKXsKCQlhc3NlcnQoYi0+Y2xvc2VkID09IDApOwoJ CWItPmNsb3NlZCsrOwoJCWZvcihzcCA9IGItPnNydjsgc3AgIT0gbmlsOyBzcCA9IHBydil7 CgkJCXBydiA9IHNwLT5saW5rOwoJCQlmcmVlKHNwLT5vd25lcik7CgkJCWZyZWUoc3AtPm5h bWUpOwoJCQlpZihzcC0+Y2hhbiAhPSBuaWwpCgkJCQljY2xvc2Uoc3AtPmNoYW4pOwoJCQlm cmVlKHNwKTsKCQl9CgkJYi0+c3J2ID0gbmlsOwoJfQoJcmVmID0gZGVjcmVmKGIpOwoKCS8q CgkgKiBBbGwgYm9hcmRzIG11c3QgYmUgd2Fsa2FibGUgZnJvbSByb290LiBTbyBhIGJvYXJk CgkgKiBpcyBhbGxvd2VkIHRvIHNpdCBhdCB6ZXJvIHJlZmVyZW5jZXMgYXMgbG9uZyBhcyBp dAoJICogc3RpbGwgaGFzIGFjdGl2ZSBjaGlsZHJlbi4gRm9yIGxlYWYgbm9kZXMgd2UgdGhl bgoJICogaGF2ZSB0byB3YWxrIHVwIHRoZSB0cmVlIHRvIGNsZWFyIG5vdyBlbXB0eSBwYXJl bnRzLgoJICovCgl3aGlsZShiLT5jbG9zZWQgJiYgYi0+Y2hpbGQgPT0gbmlsICYmIHJlZiA9 PSAwKXsKCQkvL1Jvb3Qgc2hvdWxkIG5ldmVyIGJlIGNsb3NlZAoJCWFzc2VydChiLT5wYXJl bnQgIT0gbmlsKTsKCQl3bG9jayhiLT5wYXJlbnQpOwoJCWNoID0gcmVtb3ZlKChMaW5rKiop JmItPnBhcmVudC0+Y2hpbGQsIGItPm5hbWUsIGItPnBhdGgpOwoJCWFzc2VydChjaCA9PSBi KTsKCgkJYiA9IGNoLT5wYXJlbnQ7CgkJZnJlZShjaC0+bmFtZSk7CgkJZnJlZShjaC0+b3du ZXIpOwoJCXd1bmxvY2soY2gpOwoJCWZyZWUoY2gpOwoJfQoJd3VubG9jayhiKTsKfQoKc3Rh dGljIGludApzcnZnZW4oQ2hhbiAqYywgY2hhciAqbmFtZSwgRGlydGFiKiwgaW50LCBpbnQg cywgRGlyICpkcCkKewoJU3J2ICpzcDsKCUJvYXJkICpiLCAqY2g7CglRaWQgcTsKCglpZihu YW1lICE9IG5pbCAmJiBzdHJsZW4obmFtZSkgPj0gc2l6ZW9mKHVwLT5nZW5idWYpKQoJCXJl dHVybiAtMTsKCgliID0gYy0+YXV4OwoJY2ggPSBuaWw7Cglta3FpZCgmcSwgfjBMLCAwLCBR VEZJTEUpOwoJcmxvY2soYik7CglpZih3YXNlcnJvcigpKXsKCQlydW5sb2NrKGIpOwoJCW5l eHRlcnJvcigpOwoJfQoJc3dpdGNoKHMpewoJY2FzZSAtMjogLyogZG90ICovCgkJY2ggPSBi OwoJCWdvdG8gQ2hpbGQ7CgljYXNlIERFVkRPVERPVDoKCQljaCA9IGItPnBhcmVudDsKCQlp ZihjaCA9PSBuaWwpCgkJCWNoID0gJnJvb3Q7CgkJZ290byBDaGlsZDsKCX0KCWlmKG5hbWUg IT0gbmlsKXsKCQlpZihzdHJjbXAoImNsb25lIiwgbmFtZSkgPT0gMCkKCQkJZ290byBDbG9u ZTsKCgkJc3AgPSBsb29rdXAoYi0+c3J2LCBuYW1lLCB+MFVMKTsKCQlpZihzcCA9PSBuaWwp CgkJCWNoID0gbG9va3VwKGItPmNoaWxkLCBuYW1lLCB+MFVMKTsKCX0gZWxzZSB7CgkJaWYo cyA9PSAwKQoJCQlnb3RvIENsb25lOwoJCXMtLTsKCQlmb3Ioc3AgPSBiLT5zcnY7IHNwICE9 IG5pbCAmJiBzID4gMDsgc3AgPSBzcC0+bGluaykKCQkJcy0tOwoJCWZvcihjaCA9IGItPmNo aWxkOyBjaCAhPSBuaWwgJiYgcyA+IDA7IGNoID0gY2gtPmxpbmspCgkJCXMtLTsKCX0KCWlm KHNwICE9IG5pbCl7CgkJa3N0cmNweSh1cC0+Z2VuYnVmLCBzcC0+bmFtZSwgc2l6ZW9mIHVw LT5nZW5idWYpOwoJCXEudmVycyA9IE5FVElEKGMtPnFpZC5wYXRoKTsKCQlxLnBhdGggPSBO RVRRSUQocS52ZXJzLCBzcC0+cGF0aCk7CgkJZGV2ZGlyKGMsIHEsIHVwLT5nZW5idWYsIDAs IHNwLT5vd25lciwgc3AtPnBlcm0sIGRwKTsKCX0gZWxzZSBpZihjaCAhPSBuaWwpewpDaGls ZDoKCQlpZihuYW1lICE9IG5pbCB8fCBzID09IERFVkRPVERPVCl7CgkJCWRldnBlcm1jaGVj ayhjaC0+b3duZXIsIGNoLT5wZXJtLCBPRVhFQyk7CgkJCWMtPmF1eCA9IGNoOwoJCX0KCQlr c3RyY3B5KHVwLT5nZW5idWYsIGNoLT5uYW1lLCBzaXplb2YgdXAtPmdlbmJ1Zik7CgkJcS52 ZXJzID0gY2gtPmlkOwoJCXEucGF0aCA9IE5FVFFJRChxLnZlcnMsIGNoLT5wYXRoKTsKCQlx LnR5cGUgPSBRVERJUjsKCQlkZXZkaXIoYywgcSwgdXAtPmdlbmJ1ZiwgMCwgY2gtPm93bmVy LCBjaC0+cGVybXxETURJUiwgZHApOwoJfSBlbHNlIGlmKDApewpDbG9uZToKCQlxLnZlcnMg PSBORVRJRChjLT5xaWQucGF0aCk7CgkJcS5wYXRoID0gTkVUUUlEKHEudmVycywgUWNsb25l KTsKCQlkZXZkaXIoYywgcSwgImNsb25lIiwgMCwgZXZlLCAwNDQ0LCBkcCk7Cgl9IGVsc2Ug ewoJCXJ1bmxvY2soYik7CgkJcG9wZXJyb3IoKTsKCQlyZXR1cm4gLTE7Cgl9CgoJcnVubG9j ayhiKTsKCXBvcGVycm9yKCk7CglyZXR1cm4gMTsKfQoKc3RhdGljIHZvaWQKc3J2aW5pdCh2 b2lkKQp7Cglyb290LnFpZHBhdGggPSBRZW5kOwoJcm9vdC5uYW1lID0gIiNzIjsKCXJvb3Qu cGVybSA9IDA3Nzc7Cglrc3RyZHVwKCZyb290Lm93bmVyLCBldmUpOwp9CgpzdGF0aWMgQ2hh bioKc3J2YXR0YWNoKGNoYXIgKnNwZWMpCnsKCUNoYW4gKmM7CgoJYyA9IGRldmF0dGFjaCgn cycsIHNwZWMpOwoJYy0+YXV4ID0gJnJvb3Q7CglyZXR1cm4gYzsKfQoKc3RhdGljIFdhbGtx aWQqCnNydndhbGsoQ2hhbiAqYywgQ2hhbiAqbmMsIGNoYXIgKipuYW1lLCBpbnQgbm5hbWUp CnsKCUJvYXJkICpiOwoJV2Fsa3FpZCAqd3E7CgoJd3EgPSBkZXZ3YWxrKGMsIG5jLCBuYW1l LCBubmFtZSwgMCwgMCwgc3J2Z2VuKTsKCWlmKHdxID09IG5pbCB8fCB3cS0+Y2xvbmUgPT0g bmlsKQoJCXJldHVybiB3cTsKCgliID0gd3EtPmNsb25lLT5hdXg7CglpZihiID09ICZyb290 KQoJCXJldHVybiB3cTsKCglpbmNyZWYoYik7CglyZXR1cm4gd3E7Cn0KCnN0YXRpYyBpbnQK c3J2c3RhdChDaGFuICpjLCB1Y2hhciAqZGIsIGludCBuKQp7CglEaXIgZDsKCgkvKiBkZXZz dGF0IGNoZWF0cyBmb3IgZGlyIHN0YXRzLCB3ZSBjYXJlIGFib3V0IG91ciBkaXIgcGVybXMg Ki8KCWlmKGMtPnFpZC50eXBlID09IFFURElSKXsKCQlzcnZnZW4oYywgbmlsLCBuaWwsIDAs IC0yLCAmZCk7CgkJbiA9IGNvbnZEMk0oJmQsIGRiLCBuKTsKCQlpZihuID09IDApCgkJCWVy cm9yKEViYWRhcmcpOwoJCXJldHVybiBuOwoJfQoKCXJldHVybiBkZXZzdGF0KGMsIGRiLCBu LCAwLCAwLCBzcnZnZW4pOwp9CgpjaGFyKgpzcnZuYW1lKENoYW4gKmMpCnsKCUJvYXJkICpi OwoJU3J2ICpzcDsKCWNoYXIgKnM7CgoJcyA9IG5pbDsKCWIgPSAmcm9vdDsKCXJsb2NrKGIp OwoJZm9yKHNwID0gYi0+c3J2OyBzcCAhPSBuaWw7IHNwID0gc3AtPmxpbmspIHsKCQlpZihz cC0+Y2hhbiA9PSBjKXsKCQkJcyA9IG1hbGxvYygzK3N0cmxlbihzcC0+bmFtZSkrMSk7CgkJ CWlmKHMgIT0gbmlsKQoJCQkJc3ByaW50KHMsICIjcy8lcyIsIHNwLT5uYW1lKTsKCQkJYnJl YWs7CgkJfQoJfQoJcnVubG9jayhiKTsKCXJldHVybiBzOwp9CgpzdGF0aWMgQ2hhbioKc3J2 b3BlbihDaGFuICpjLCBpbnQgb21vZGUpCnsKCUJvYXJkICpiLCAqY2g7CglTcnYgKnNwOwoJ Q2hhbiAqbmM7CgljaGFyIGJ1Zls2NF07CgoJaWYob21vZGUmT1RSVU5DKQoJCWVycm9yKEVl eGlzdCk7CglpZihvbW9kZSZPUkNMT1NFKQoJCWVycm9yKEVwZXJtKTsKCgliID0gYy0+YXV4 OwoJaWYoTkVUVFlQRShjLT5xaWQucGF0aCkgPT0gUWNsb25lKXs7CgkJd2xvY2soYik7CgkJ aWYoYi0+Y2xvc2VkKXsKCQkJd3VubG9jayhiKTsKCQkJZXJyb3IoRWV4cGlyZWQpOwoJCX0K CQljaCA9IHNtYWxsb2Moc2l6ZW9mICpjaCk7CgkJY2gtPnFpZHBhdGggPSBRZW5kOwoJCWNo LT5yZWYgPSAxOwoJCWNoLT5wZXJtID0gMDc3MDsKCQlrc3RyZHVwKCZjaC0+b3duZXIsIHVw LT51c2VyKTsKCQlkbyB7CgkJCXFsb2NrKCZib2FyZHMpOwoJCQljaC0+aWQgPSArK2JvYXJk cy5wYXRoOwoJCQlxdW5sb2NrKCZib2FyZHMpOwoJCQlzbnByaW50KGJ1Ziwgc2l6ZW9mIGJ1 ZiwgIiVsZCIsIGNoLT5pZCk7CgkJfSB3aGlsZShsb29rdXAoYi0+c3J2LCBidWYsIH4wVUwp ICE9IG5pbCk7CgoJCWNoLT5wYXJlbnQgPSBiOwoJCWNoLT5wYXRoID0gYi0+cWlkcGF0aCsr OwoJCWtzdHJkdXAoJmNoLT5uYW1lLCBidWYpOwoKCQljaC0+bGluayA9IGItPmNoaWxkOwoJ CWItPmNoaWxkID0gY2g7CgkJYy0+YXV4ID0gY2g7CgkJYy0+cWlkLnZlcnMgPSBjaC0+aWQ7 CgkJYy0+cWlkLnBhdGggPSBORVRRSUQoY2gtPmlkLCBRbGVhc2UpOwoJCWJvYXJkY2x1bmso YiwgMCk7IC8vdW5sb2NrCgkJcmV0dXJuIGM7Cgl9CgoJcmxvY2soYik7CglpZih3YXNlcnJv cigpKXsKCQlydW5sb2NrKGIpOwoJCW5leHRlcnJvcigpOwoJfQoJaWYoYy0+cWlkLnR5cGUg PT0gUVRESVIpewoJCWlmKG9tb2RlICYgT1JDTE9TRSkKCQkJZXJyb3IoRXBlcm0pOwoJCWlm KG9tb2RlICE9IE9SRUFEKQoJCQllcnJvcihFaXNkaXIpOwoJCWRldnBlcm1jaGVjayhiLT5v d25lciwgYi0+cGVybSwgb21vZGUpOwoJCWMtPm1vZGUgPSBvbW9kZTsKCQljLT5mbGFnIHw9 IENPUEVOOwoJCWMtPm9mZnNldCA9IDA7CgkJcnVubG9jayhiKTsKCQlwb3BlcnJvcigpOwoJ CXJldHVybiBjOwoJfQoJaWYoYi0+Y2xvc2VkKQoJCWVycm9yKEVleHBpcmVkKTsKCglzcCA9 IGxvb2t1cChiLT5zcnYsIG5pbCwgYy0+cWlkLnBhdGgpOwoJaWYoc3AgPT0gbmlsIHx8IHNw LT5jaGFuID09IG5pbCkKCQllcnJvcihFc2h1dGRvd24pOwoKCWlmKG9wZW5tb2RlKG9tb2Rl KSE9c3AtPmNoYW4tPm1vZGUgJiYgc3AtPmNoYW4tPm1vZGUhPU9SRFdSKQoJCWVycm9yKEVw ZXJtKTsKCWRldnBlcm1jaGVjayhzcC0+b3duZXIsIHNwLT5wZXJtLCBvbW9kZSk7CgoJbmMg PSBzcC0+Y2hhbjsKCWluY3JlZihuYyk7CgoJcnVubG9jayhiKTsKCXBvcGVycm9yKCk7CgoJ Y2Nsb3NlKGMpOwoJcmV0dXJuIG5jOwp9CgpzdGF0aWMgQ2hhbioKc3J2Y3JlYXRlKENoYW4g KmMsIGNoYXIgKm5hbWUsIGludCBvbW9kZSwgdWxvbmcgcGVybSkKewoJQm9hcmQgKmI7CglT cnYgKnNwOwoKCWlmKG9wZW5tb2RlKG9tb2RlKSAhPSBPV1JJVEUpCgkJZXJyb3IoRXBlcm0p OwoKCWlmKHN0cmxlbihuYW1lKSA+PSBzaXplb2YodXAtPmdlbmJ1ZikpCgkJZXJyb3IoRXRv b2xvbmcpOwoKCWlmKHN0cmNtcCgiY2xvbmUiLCBuYW1lKSA9PSAwKQoJCWVycm9yKCJyZXNl cnZlZCBuYW1lIik7CgoJc3AgPSBzbWFsbG9jKHNpemVvZiAqc3ApOwoJa3N0cmR1cCgmc3At Pm5hbWUsIG5hbWUpOwoJa3N0cmR1cCgmc3AtPm93bmVyLCB1cC0+dXNlcik7CgoJYiA9IGMt PmF1eDsKCXdsb2NrKGIpOwoJaWYod2FzZXJyb3IoKSl7CgkJd3VubG9jayhiKTsKCQlmcmVl KHNwLT5vd25lcik7CgkJZnJlZShzcC0+bmFtZSk7CgkJZnJlZShzcCk7CgkJbmV4dGVycm9y KCk7Cgl9CglpZihiLT5jbG9zZWQpCgkJZXJyb3IoRWV4cGlyZWQpOwoJZGV2cGVybWNoZWNr KGItPm93bmVyLCBiLT5wZXJtLCBPV1JJVEUpOwoJaWYobG9va3VwKGItPnNydiwgbmFtZSwg fjBVTCkgIT0gbmlsKQoJCWVycm9yKEVleGlzdCk7CglpZihsb29rdXAoYi0+Y2hpbGQsIG5h bWUsIH4wVUwpICE9IG5pbCkKCQllcnJvcihFZXhpc3QpOwoKCXNwLT5wZXJtID0gcGVybSYw Nzc3OwoJc3AtPnBhdGggPSBiLT5xaWRwYXRoKys7CgoJYy0+cWlkLnBhdGggPSBORVRRSUQo Yi0+aWQsIHNwLT5wYXRoKTsKCWMtPnFpZC52ZXJzID0gYi0+aWQ7CgljLT5xaWQudHlwZSA9 IFFURklMRTsKCglzcC0+bGluayA9IGItPnNydjsKCWItPnNydiA9IHNwOwoKCXd1bmxvY2so Yik7Cglwb3BlcnJvcigpOwoKCWMtPmZsYWcgfD0gQ09QRU47CgljLT5tb2RlID0gT1dSSVRF OwoKCXJldHVybiBjOwp9CgpzdGF0aWMgdm9pZApzcnZyZW1vdmUoQ2hhbiAqYykKewoJQm9h cmQgKmI7CglTcnYgKnNwOwoKCWIgPSBjLT5hdXg7Cgl3bG9jayhiKTsKCWlmKHdhc2Vycm9y KCkpewoJCWJvYXJkY2x1bmsoYiwgMCk7IC8vdW5sb2NrCgkJbmV4dGVycm9yKCk7Cgl9Cglp ZihjLT5xaWQudHlwZSA9PSBRVERJUikKCQllcnJvcihFcGVybSk7Cglzd2l0Y2goTkVUVFlQ RShjLT5xaWQucGF0aCkpewoJY2FzZSBRbGVhc2U6CgljYXNlIFFjbG9uZToKCQllcnJvcihF cGVybSk7Cgl9CgoJc3AgPSBsb29rdXAoYi0+c3J2LCBuaWwsIGMtPnFpZC5wYXRoKTsKCWlm KHNwID09IG5pbCkKCQllcnJvcihFbm9uZXhpc3QpOwoKCWlmKHN0cmNtcChzcC0+b3duZXIs IHVwLT51c2VyKSAhPSAwICYmICFpc2V2ZSgpKQoJCWVycm9yKEVwZXJtKTsKCglyZW1vdmUo KExpbmsqKikmYi0+c3J2LCBuaWwsIGMtPnFpZC5wYXRoKTsKCglib2FyZGNsdW5rKGIsIDAp OyAvL3VubG9jawoJcG9wZXJyb3IoKTsKCglpZihzcC0+Y2hhbiAhPSBuaWwpCgkJY2Nsb3Nl KHNwLT5jaGFuKTsKCWZyZWUoc3AtPm93bmVyKTsKCWZyZWUoc3AtPm5hbWUpOwoJZnJlZShz cCk7Cn0KCnN0YXRpYyBpbnQKc3J2d3N0YXQoQ2hhbiAqYywgdWNoYXIgKmRwLCBpbnQgbikK ewoJQm9hcmQgKmIsICpzOwoJY2hhciAqc3RyczsKCURpciBkOwoJTGluayAqbHA7CgoJc3dp dGNoKE5FVFRZUEUoYy0+cWlkLnBhdGgpKXsKCWNhc2UgUWxlYXNlOgoJY2FzZSBRY2xvbmU6 CgkJZXJyb3IoRXBlcm0pOwoJfQoJaWYoYy0+cWlkLnR5cGUgPT0gUVRESVIgJiYgYy0+YXV4 ID09ICZyb290KQoJCWVycm9yKEVwZXJtKTsKCglzdHJzID0gc21hbGxvYyhuKTsKCWlmKHdh c2Vycm9yKCkpewoJCWZyZWUoc3Rycyk7CgkJbmV4dGVycm9yKCk7Cgl9CgluID0gY29udk0y RChkcCwgbiwgJmQsIHN0cnMpOwoJaWYobiA9PSAwKQoJCWVycm9yKEVzaG9ydHN0YXQpOwoK CWIgPSBjLT5hdXg7Cgl3bG9jayhiKTsKCWlmKHdhc2Vycm9yKCkpewoJCXd1bmxvY2soYik7 CgkJbmV4dGVycm9yKCk7Cgl9CglpZihiLT5jbG9zZWQpCgkJZXJyb3IoRWV4cGlyZWQpOwoK CWlmKGMtPnFpZC50eXBlID09IFFURElSKXsKCQlscCA9IGI7CgkJLyogd2Ugc2hhcmUgb3du ZXJzaGlwIG9mIG91ciBzdGF0cyB3aXRoIG91ciBwYXJlbnQgKi8KCQlhc3NlcnQoYi0+cGFy ZW50ICE9IG5pbCk7CgkJd2xvY2soYi0+cGFyZW50KTsKCQlpZih3YXNlcnJvcigpKXsKCQkJ d3VubG9jayhiLT5wYXJlbnQpOwoJCQluZXh0ZXJyb3IoKTsKCQl9Cgl9IGVsc2UKCQlscCA9 IGxvb2t1cChiLT5zcnYsIG5pbCwgYy0+cWlkLnBhdGgpOwoJaWYobHAgPT0gbmlsKQoJCWVy cm9yKEVub25leGlzdCk7CgoJaWYoc3RyY21wKGxwLT5vd25lciwgdXAtPnVzZXIpICE9IDAg JiYgIWlzZXZlKCkpCgkJZXJyb3IoRXBlcm0pOwoKCWlmKGQubmFtZSAhPSBuaWwgJiYgKmQu bmFtZSAmJiBzdHJjbXAobHAtPm5hbWUsIGQubmFtZSkgIT0gMCkgewoJCWlmKHN0cmNocihk Lm5hbWUsICcvJykgIT0gbmlsKQoJCQllcnJvcihFYmFkY2hhcik7CgkJaWYoc3RybGVuKGQu bmFtZSkgPj0gc2l6ZW9mKHVwLT5nZW5idWYpKQoJCQllcnJvcihFdG9vbG9uZyk7CgoJCS8v RW5zdXJlIG5ldyBuYW1lIGRvZXNuJ3QgY29uZmxpY3Qgd2l0aCBvbGQgbmFtZXMKCQlpZihj LT5xaWQudHlwZSA9PSBRVERJUikKCQkJcyA9IGItPnBhcmVudDsKCQllbHNlCgkJCXMgPSBi OwoJCWlmKGxvb2t1cChzLT5zcnYsIGQubmFtZSwgfjBVTCkgIT0gbmlsKQoJCQllcnJvcihF ZXhpc3QpOwoJCWlmKGxvb2t1cChzLT5jaGlsZCwgZC5uYW1lLCB+MFVMKSAhPSBuaWwpCgkJ CWVycm9yKEVleGlzdCk7CgkJa3N0cmR1cCgmbHAtPm5hbWUsIGQubmFtZSk7Cgl9CglpZihk LnVpZCAhPSBuaWwgJiYgKmQudWlkKQoJCWtzdHJkdXAoJmxwLT5vd25lciwgZC51aWQpOwoJ aWYoZC5tb2RlICE9IH4wVUwpCgkJbHAtPnBlcm0gPSBkLm1vZGUgJiAwNzc3OwoKCWlmKGMt PnFpZC50eXBlID09IFFURElSKXsKCQl3dW5sb2NrKGItPnBhcmVudCk7CgkJcG9wZXJyb3Io KTsKCX0KCgl3dW5sb2NrKGIpOwoJcG9wZXJyb3IoKTsKCglmcmVlKHN0cnMpOwoJcG9wZXJy b3IoKTsKCglyZXR1cm4gbjsKfQoKc3RhdGljIHZvaWQKc3J2Y2xvc2UoQ2hhbiAqYykKewoJ Qm9hcmQgKmI7CglpbnQgZXhwaXJlZDsKCglleHBpcmVkID0gMDsKCWlmKE5FVFRZUEUoYy0+ cWlkLnBhdGgpID09IFFsZWFzZSkKCQlleHBpcmVkKys7CgllbHNlIGlmKGMtPmZsYWcgJiBD UkNMT1NFKXsKCQkvKgoJCSAqIGluIHRoZW9yeSB3ZSBuZWVkIHRvIG92ZXJyaWRlIGFueSBj aGFuZ2VzIGluIHJlbW92YWJpbGl0eQoJCSAqIHNpbmNlIG9wZW4sIGJ1dCBzaW5jZSBhbGwg dGhhdCdzIGNoZWNrZWQgaXMgdGhlIG93bmVyLAoJIAkgKiB3aGljaCBpcyBpbW11dGFibGUs IGFsbCBpcyB3ZWxsLgoJIAkgKi8KCQlpZih3YXNlcnJvcigpKQoJCQlyZXR1cm47CgkJc3J2 cmVtb3ZlKGMpOwoJCXBvcGVycm9yKCk7CgkJcmV0dXJuOwoJfQoKCWIgPSBjLT5hdXg7Cgl3 bG9jayhiKTsKCWJvYXJkY2x1bmsoYiwgZXhwaXJlZCk7IC8vdW5sb2NrCn0KCnN0YXRpYyBs b25nCnNydnJlYWQoQ2hhbiAqYywgdm9pZCAqdmEsIGxvbmcgbiwgdmxvbmcgb2ZmKQp7CglC b2FyZCAqYjsKCglpZihORVRUWVBFKGMtPnFpZC5wYXRoKSA9PSBRbGVhc2UpewoJCWIgPSBj LT5hdXg7CgkJcmxvY2soYik7CgkJaWYod2FzZXJyb3IoKSl7CgkJCXJ1bmxvY2soYik7CgkJ CW5leHRlcnJvcigpOwoJCX0KCQluID0gcmVhZHN0cigodWxvbmcpb2ZmLCB2YSwgbiwgYi0+ bmFtZSk7CgkJcnVubG9jayhiKTsKCQlwb3BlcnJvcigpOwoJCXJldHVybiBuOwoJfQoJaXNk aXIoYyk7CglyZXR1cm4gZGV2ZGlycmVhZChjLCB2YSwgbiwgMCwgMCwgc3J2Z2VuKTsKfQoK c3RhdGljIGxvbmcKc3J2d3JpdGUoQ2hhbiAqYywgdm9pZCAqdmEsIGxvbmcgbiwgdmxvbmcp CnsKCUJvYXJkICpiOwoJU3J2ICpzcDsKCUNoYW4gKmMxOwoJaW50IGZkOwoJY2hhciBidWZb MzJdOwoKCWlmKE5FVFRZUEUoYy0+cWlkLnBhdGgpID09IFFsZWFzZSkKCQllcnJvcihFcGVy bSk7CgoJaWYobiA+PSBzaXplb2YgYnVmKQoJCWVycm9yKEV0b29iaWcpOwoJbWVtbW92ZShi dWYsIHZhLCBuKTsJLyogc28gd2UgY2FuIE5VTC10ZXJtaW5hdGUgKi8KCWJ1ZltuXSA9IDA7 CglmZCA9IHN0cnRvdWwoYnVmLCAwLCAwKTsKCgljMSA9IGZkdG9jaGFuKGZkLCAtMSwgMCwg MSk7CS8qIGVycm9yIGNoZWNrIGFuZCBpbmMgcmVmICovCgoJYiA9IGMtPmF1eDsKCXdsb2Nr KGIpOwoJaWYod2FzZXJyb3IoKSkgewoJCXd1bmxvY2soYik7CgkJY2Nsb3NlKGMxKTsKCQlu ZXh0ZXJyb3IoKTsKCX0KCWlmKGItPmNsb3NlZCkKCQllcnJvcihFZXhwaXJlZCk7CglpZihj MS0+cWlkLnR5cGUgJiBRVEFVVEgpCgkJZXJyb3IoImNhbm5vdCBwb3N0IGF1dGggZmlsZSBp biBzcnYiKTsKCXNwID0gbG9va3VwKGItPnNydiwgbmlsLCBjLT5xaWQucGF0aCk7CglpZihz cCA9PSBuaWwpCgkJZXJyb3IoRW5vbmV4aXN0KTsKCglpZihzcC0+Y2hhbiAhPSBuaWwpCgkJ ZXJyb3IoRWJhZHVzZWZkKTsKCglzcC0+Y2hhbiA9IGMxOwoKCXd1bmxvY2soYik7Cglwb3Bl cnJvcigpOwoJcmV0dXJuIG47Cn0KCkRldiBzcnZkZXZ0YWIgPSB7CgkncycsCgkic3J2IiwK CglkZXZyZXNldCwKCXNydmluaXQsCQoJZGV2c2h1dGRvd24sCglzcnZhdHRhY2gsCglzcnZ3 YWxrLAoJc3J2c3RhdCwKCXNydm9wZW4sCglzcnZjcmVhdGUsCglzcnZjbG9zZSwKCXNydnJl YWQsCglkZXZicmVhZCwKCXNydndyaXRlLAoJZGV2YndyaXRlLAoJc3J2cmVtb3ZlLAoJc3J2 d3N0YXQsCn07Cgp2b2lkCnNydnJlbmFtZXVzZXIoY2hhciAqb2xkLCBjaGFyICpuZXcpCnsK CUJvYXJkICpiOwoJU3J2ICpzcDsKCgliID0gJnJvb3Q7Cgl3bG9jayhiKTsKCWtzdHJkdXAo JmItPm93bmVyLCBuZXcpOwoJZm9yKHNwID0gYi0+c3J2OyBzcCAhPSBuaWw7IHNwID0gc3At PmxpbmspIHsKCQlpZihzcC0+b3duZXIgIT0gbmlsICYmIHN0cmNtcChvbGQsIHNwLT5vd25l cikgPT0gMCkKCQkJa3N0cmR1cCgmc3AtPm93bmVyLCBuZXcpOwoJfQoJd3VubG9jayhiKTsK fQo= --upas-mqdzvdyaqpywwsvvpzbhbyfzds-- --------------EVmRT7AVLMLBltOkPMklqYR3--