123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- #include <u.h>
- #include <libc.h>
- #include <ip.h>
- #include <auth.h>
- #include "ppp.h"
- enum
- {
- PAD = 128,
- NLIST = (1<<5),
- BPOW = 10,
- };
- typedef struct Barena Barena;
- struct Barena
- {
- QLock;
- Block* list[NLIST];
- };
- static Barena area;
- #define ADEBUG if(0)
- /*
- * allocation tracing
- */
- enum
- {
- Npc= 64,
- };
- typedef struct Arefent Arefent;
- struct Arefent
- {
- uint pc;
- uint n;
- };
- typedef struct Aref Aref;
- struct Aref
- {
- Arefent tab[Npc];
- QLock;
- };
- Aref arefblock;
- static ulong callerpc(void*);
- static void aref(Aref*, ulong);
- static void aunref(Aref*, ulong);
- Block*
- allocb(int len)
- {
- int sz;
- Block *bp, **l;
- len += PAD;
- sz = (len>>BPOW)&(NLIST-1);
-
- qlock(&area);
- l = &area.list[sz];
- for(bp = *l; bp; bp = bp->flist) {
- if(bp->bsz >= len) {
- *l = bp->flist;
- qunlock(&area);
- bp->next = nil;
- bp->list = nil;
- bp->flist = nil;
- bp->base = (uchar*)bp+sizeof(Block);
- bp->rptr = bp->base+PAD;
- bp->wptr = bp->rptr;
- bp->lim = bp->base+bp->bsz;
- bp->flow = nil;
- bp->flags= 0;
- ADEBUG {
- bp->pc = callerpc(&len);
- aref(&arefblock, bp->pc);
- }
- return bp;
- }
- l = &bp->flist;
- }
- qunlock(&area);
- bp = mallocz(sizeof(Block)+len, 1);
- bp->bsz = len;
- bp->base = (uchar*)bp+sizeof(Block);
- bp->rptr = bp->base+PAD;
- bp->wptr = bp->rptr;
- bp->lim = bp->base+len;
- ADEBUG {
- bp->pc = callerpc(&len);
- aref(&arefblock, bp->pc);
- }
- return bp;
- }
- void
- freeb(Block *bp)
- {
- int sz;
- Block **l, *next;
- qlock(&area);
- while(bp) {
- sz = (bp->bsz>>BPOW)&(NLIST-1);
- l = &area.list[sz];
- bp->flist = *l;
- *l = bp;
- next = bp->next;
- /* to catch use after free */
- bp->rptr = (uchar*)0xdeadbabe;
- bp->wptr = (uchar*)0xdeadbabe;
- bp->next = (Block*)0xdeadbabe;
- bp->list = (Block*)0xdeadbabe;
- ADEBUG aunref(&arefblock, bp->pc);
- bp = next;
- }
- qunlock(&area);
- }
- /*
- * concatenate a list of blocks into a single one and make sure
- * the result is at least min uchars
- */
- Block*
- concat(Block *bp)
- {
- int len;
- Block *nb, *f;
- nb = allocb(blen(bp));
- for(f = bp; f; f = f->next) {
- len = BLEN(f);
- memmove(nb->wptr, f->rptr, len);
- nb->wptr += len;
- }
- freeb(bp);
- return nb;
- }
- int
- blen(Block *bp)
- {
- int len;
- len = 0;
- while(bp) {
- len += BLEN(bp);
- bp = bp->next;
- }
- return len;
- }
- Block *
- pullup(Block *bp, int n)
- {
- int i;
- Block *nbp;
- /*
- * this should almost always be true, the rest it
- * just for to avoid every caller checking.
- */
- if(BLEN(bp) >= n)
- return bp;
- /*
- * if not enough room in the first block,
- * add another to the front of the list.
- */
- if(bp->lim - bp->rptr < n){
- nbp = allocb(n);
- nbp->next = bp;
- bp = nbp;
- }
- /*
- * copy uchars from the trailing blocks into the first
- */
- n -= BLEN(bp);
- while(nbp = bp->next){
- i = BLEN(nbp);
- if(i >= n) {
- memmove(bp->wptr, nbp->rptr, n);
- bp->wptr += n;
- nbp->rptr += n;
- return bp;
- }
- else {
- memmove(bp->wptr, nbp->rptr, i);
- bp->wptr += i;
- bp->next = nbp->next;
- nbp->next = nil;
- freeb(nbp);
- n -= i;
- }
- }
- freeb(bp);
- return nil;
- }
- /*
- * Pad a block to the front with n uchars. This is used to add protocol
- * headers to the front of blocks.
- */
- Block*
- padb(Block *bp, int n)
- {
- Block *nbp;
- if(bp->rptr-bp->base >= n) {
- bp->rptr -= n;
- return bp;
- }
- else {
- /* fprint(2, "padb: required %d PAD %d\n", n, PAD) = malloc(sizeof(*required %d PAD %d\n", n, PAD))); */
- nbp = allocb(n);
- nbp->wptr = nbp->lim;
- nbp->rptr = nbp->wptr - n;
- nbp->next = bp;
- return nbp;
- }
- }
- Block *
- btrim(Block *bp, int offset, int len)
- {
- ulong l;
- Block *nb, *startb;
- if(blen(bp) < offset+len) {
- freeb(bp);
- return nil;
- }
- while((l = BLEN(bp)) < offset) {
- offset -= l;
- nb = bp->next;
- bp->next = nil;
- freeb(bp);
- bp = nb;
- }
- startb = bp;
- bp->rptr += offset;
- while((l = BLEN(bp)) < len) {
- len -= l;
- bp = bp->next;
- }
- bp->wptr -= (BLEN(bp) - len);
- bp->flags |= S_DELIM;
- if(bp->next) {
- freeb(bp->next);
- bp->next = nil;
- }
- return startb;
- }
- Block*
- copyb(Block *bp, int count)
- {
- int l;
- Block *nb, *head, **p;
- p = &head;
- head = nil;
- while(bp != nil && count != 0) {
- l = BLEN(bp);
- if(count < l)
- l = count;
- nb = allocb(l);
- memmove(nb->wptr, bp->rptr, l);
- nb->wptr += l;
- count -= l;
- nb->flags = bp->flags;
- *p = nb;
- p = &nb->next;
- bp = bp->next;
- }
- if(count) {
- nb = allocb(count);
- memset(nb->wptr, 0, count);
- nb->wptr += count;
- nb->flags |= S_DELIM;
- *p = nb;
- }
- if(blen(head) == 0)
- fprint(2, "copyb: zero length\n");
- return head;
- }
- int
- pullb(Block **bph, int count)
- {
- Block *bp;
- int n, uchars;
- uchars = 0;
- if(bph == nil)
- return 0;
- while(*bph != nil && count != 0) {
- bp = *bph;
- n = BLEN(bp);
- if(count < n)
- n = count;
- uchars += n;
- count -= n;
- bp->rptr += n;
- if(BLEN(bp) == 0) {
- *bph = bp->next;
- bp->next = nil;
- freeb(bp);
- }
- }
- return uchars;
- }
- /*
- * handy routines for keeping track of allocations
- */
- static ulong
- callerpc(void *a)
- {
- return ((ulong*)a)[-1];
- }
- static void
- aref(Aref *ap, ulong pc)
- {
- Arefent *a, *e;
- e = &ap->tab[Npc-1];
- qlock(ap);
- for(a = ap->tab; a < e; a++)
- if(a->pc == pc || a->pc == 0)
- break;
- a->pc = pc;
- a->n++;
- qunlock(ap);
- }
- static void
- aunref(Aref *ap, ulong pc)
- {
- Arefent *a, *e;
- e = &ap->tab[Npc-1];
- qlock(ap);
- for(a = ap->tab; a < e; a++)
- if(a->pc == pc || a->pc == 0)
- break;
- a->n--;
- qunlock(ap);
- }
|