17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <ip.h>
4*9a747e4fSDavid du Colombier #include <auth.h>
57dd7cddfSDavid du Colombier #include "ppp.h"
67dd7cddfSDavid du Colombier
77dd7cddfSDavid du Colombier enum
87dd7cddfSDavid du Colombier {
97dd7cddfSDavid du Colombier PAD = 128,
107dd7cddfSDavid du Colombier NLIST = (1<<5),
117dd7cddfSDavid du Colombier BPOW = 10,
127dd7cddfSDavid du Colombier };
137dd7cddfSDavid du Colombier
147dd7cddfSDavid du Colombier typedef struct Barena Barena;
157dd7cddfSDavid du Colombier struct Barena
167dd7cddfSDavid du Colombier {
177dd7cddfSDavid du Colombier QLock;
187dd7cddfSDavid du Colombier Block* list[NLIST];
197dd7cddfSDavid du Colombier };
207dd7cddfSDavid du Colombier static Barena area;
217dd7cddfSDavid du Colombier
227dd7cddfSDavid du Colombier #define ADEBUG if(0)
237dd7cddfSDavid du Colombier
247dd7cddfSDavid du Colombier
257dd7cddfSDavid du Colombier /*
267dd7cddfSDavid du Colombier * allocation tracing
277dd7cddfSDavid du Colombier */
287dd7cddfSDavid du Colombier enum
297dd7cddfSDavid du Colombier {
307dd7cddfSDavid du Colombier Npc= 64,
317dd7cddfSDavid du Colombier };
327dd7cddfSDavid du Colombier typedef struct Arefent Arefent;
337dd7cddfSDavid du Colombier struct Arefent
347dd7cddfSDavid du Colombier {
357dd7cddfSDavid du Colombier uint pc;
367dd7cddfSDavid du Colombier uint n;
377dd7cddfSDavid du Colombier };
387dd7cddfSDavid du Colombier typedef struct Aref Aref;
397dd7cddfSDavid du Colombier struct Aref
407dd7cddfSDavid du Colombier {
417dd7cddfSDavid du Colombier Arefent tab[Npc];
427dd7cddfSDavid du Colombier QLock;
437dd7cddfSDavid du Colombier };
447dd7cddfSDavid du Colombier Aref arefblock;
457dd7cddfSDavid du Colombier
467dd7cddfSDavid du Colombier static ulong callerpc(void*);
477dd7cddfSDavid du Colombier static void aref(Aref*, ulong);
487dd7cddfSDavid du Colombier static void aunref(Aref*, ulong);
497dd7cddfSDavid du Colombier
507dd7cddfSDavid du Colombier Block*
allocb(int len)517dd7cddfSDavid du Colombier allocb(int len)
527dd7cddfSDavid du Colombier {
537dd7cddfSDavid du Colombier int sz;
547dd7cddfSDavid du Colombier Block *bp, **l;
557dd7cddfSDavid du Colombier
567dd7cddfSDavid du Colombier len += PAD;
577dd7cddfSDavid du Colombier sz = (len>>BPOW)&(NLIST-1);
587dd7cddfSDavid du Colombier
597dd7cddfSDavid du Colombier qlock(&area);
607dd7cddfSDavid du Colombier l = &area.list[sz];
617dd7cddfSDavid du Colombier for(bp = *l; bp; bp = bp->flist) {
627dd7cddfSDavid du Colombier if(bp->bsz >= len) {
637dd7cddfSDavid du Colombier *l = bp->flist;
647dd7cddfSDavid du Colombier qunlock(&area);
657dd7cddfSDavid du Colombier
667dd7cddfSDavid du Colombier bp->next = nil;
677dd7cddfSDavid du Colombier bp->list = nil;
687dd7cddfSDavid du Colombier bp->flist = nil;
697dd7cddfSDavid du Colombier bp->base = (uchar*)bp+sizeof(Block);
707dd7cddfSDavid du Colombier bp->rptr = bp->base+PAD;
717dd7cddfSDavid du Colombier bp->wptr = bp->rptr;
727dd7cddfSDavid du Colombier bp->lim = bp->base+bp->bsz;
737dd7cddfSDavid du Colombier bp->flow = nil;
747dd7cddfSDavid du Colombier bp->flags= 0;
757dd7cddfSDavid du Colombier ADEBUG {
767dd7cddfSDavid du Colombier bp->pc = callerpc(&len);
777dd7cddfSDavid du Colombier aref(&arefblock, bp->pc);
787dd7cddfSDavid du Colombier }
797dd7cddfSDavid du Colombier return bp;
807dd7cddfSDavid du Colombier }
817dd7cddfSDavid du Colombier l = &bp->flist;
827dd7cddfSDavid du Colombier }
837dd7cddfSDavid du Colombier
847dd7cddfSDavid du Colombier qunlock(&area);
857dd7cddfSDavid du Colombier
867dd7cddfSDavid du Colombier bp = mallocz(sizeof(Block)+len, 1);
877dd7cddfSDavid du Colombier
887dd7cddfSDavid du Colombier bp->bsz = len;
897dd7cddfSDavid du Colombier bp->base = (uchar*)bp+sizeof(Block);
907dd7cddfSDavid du Colombier bp->rptr = bp->base+PAD;
917dd7cddfSDavid du Colombier bp->wptr = bp->rptr;
927dd7cddfSDavid du Colombier bp->lim = bp->base+len;
937dd7cddfSDavid du Colombier ADEBUG {
947dd7cddfSDavid du Colombier bp->pc = callerpc(&len);
957dd7cddfSDavid du Colombier aref(&arefblock, bp->pc);
967dd7cddfSDavid du Colombier }
977dd7cddfSDavid du Colombier return bp;
987dd7cddfSDavid du Colombier }
997dd7cddfSDavid du Colombier
1007dd7cddfSDavid du Colombier void
freeb(Block * bp)1017dd7cddfSDavid du Colombier freeb(Block *bp)
1027dd7cddfSDavid du Colombier {
1037dd7cddfSDavid du Colombier int sz;
1047dd7cddfSDavid du Colombier Block **l, *next;
1057dd7cddfSDavid du Colombier
1067dd7cddfSDavid du Colombier qlock(&area);
1077dd7cddfSDavid du Colombier while(bp) {
1087dd7cddfSDavid du Colombier sz = (bp->bsz>>BPOW)&(NLIST-1);
1097dd7cddfSDavid du Colombier
1107dd7cddfSDavid du Colombier l = &area.list[sz];
1117dd7cddfSDavid du Colombier bp->flist = *l;
1127dd7cddfSDavid du Colombier *l = bp;
1137dd7cddfSDavid du Colombier
1147dd7cddfSDavid du Colombier next = bp->next;
1157dd7cddfSDavid du Colombier
1167dd7cddfSDavid du Colombier /* to catch use after free */
1177dd7cddfSDavid du Colombier bp->rptr = (uchar*)0xdeadbabe;
1187dd7cddfSDavid du Colombier bp->wptr = (uchar*)0xdeadbabe;
1197dd7cddfSDavid du Colombier bp->next = (Block*)0xdeadbabe;
1207dd7cddfSDavid du Colombier bp->list = (Block*)0xdeadbabe;
1217dd7cddfSDavid du Colombier
1227dd7cddfSDavid du Colombier ADEBUG aunref(&arefblock, bp->pc);
1237dd7cddfSDavid du Colombier
1247dd7cddfSDavid du Colombier bp = next;
1257dd7cddfSDavid du Colombier }
1267dd7cddfSDavid du Colombier qunlock(&area);
1277dd7cddfSDavid du Colombier }
1287dd7cddfSDavid du Colombier
1297dd7cddfSDavid du Colombier /*
1307dd7cddfSDavid du Colombier * concatenate a list of blocks into a single one and make sure
1317dd7cddfSDavid du Colombier * the result is at least min uchars
1327dd7cddfSDavid du Colombier */
1337dd7cddfSDavid du Colombier Block*
concat(Block * bp)1347dd7cddfSDavid du Colombier concat(Block *bp)
1357dd7cddfSDavid du Colombier {
1367dd7cddfSDavid du Colombier int len;
1377dd7cddfSDavid du Colombier Block *nb, *f;
1387dd7cddfSDavid du Colombier
1397dd7cddfSDavid du Colombier nb = allocb(blen(bp));
1407dd7cddfSDavid du Colombier for(f = bp; f; f = f->next) {
1417dd7cddfSDavid du Colombier len = BLEN(f);
1427dd7cddfSDavid du Colombier memmove(nb->wptr, f->rptr, len);
1437dd7cddfSDavid du Colombier nb->wptr += len;
1447dd7cddfSDavid du Colombier }
1457dd7cddfSDavid du Colombier freeb(bp);
1467dd7cddfSDavid du Colombier return nb;
1477dd7cddfSDavid du Colombier }
1487dd7cddfSDavid du Colombier
1497dd7cddfSDavid du Colombier int
blen(Block * bp)1507dd7cddfSDavid du Colombier blen(Block *bp)
1517dd7cddfSDavid du Colombier {
1527dd7cddfSDavid du Colombier int len;
1537dd7cddfSDavid du Colombier
1547dd7cddfSDavid du Colombier len = 0;
1557dd7cddfSDavid du Colombier while(bp) {
1567dd7cddfSDavid du Colombier len += BLEN(bp);
1577dd7cddfSDavid du Colombier bp = bp->next;
1587dd7cddfSDavid du Colombier }
1597dd7cddfSDavid du Colombier return len;
1607dd7cddfSDavid du Colombier }
1617dd7cddfSDavid du Colombier
1627dd7cddfSDavid du Colombier Block *
pullup(Block * bp,int n)1637dd7cddfSDavid du Colombier pullup(Block *bp, int n)
1647dd7cddfSDavid du Colombier {
1657dd7cddfSDavid du Colombier int i;
1667dd7cddfSDavid du Colombier Block *nbp;
1677dd7cddfSDavid du Colombier
1687dd7cddfSDavid du Colombier /*
1697dd7cddfSDavid du Colombier * this should almost always be true, the rest it
1707dd7cddfSDavid du Colombier * just for to avoid every caller checking.
1717dd7cddfSDavid du Colombier */
1727dd7cddfSDavid du Colombier if(BLEN(bp) >= n)
1737dd7cddfSDavid du Colombier return bp;
1747dd7cddfSDavid du Colombier
1757dd7cddfSDavid du Colombier /*
1767dd7cddfSDavid du Colombier * if not enough room in the first block,
1777dd7cddfSDavid du Colombier * add another to the front of the list.
1787dd7cddfSDavid du Colombier */
1797dd7cddfSDavid du Colombier if(bp->lim - bp->rptr < n){
1807dd7cddfSDavid du Colombier nbp = allocb(n);
1817dd7cddfSDavid du Colombier nbp->next = bp;
1827dd7cddfSDavid du Colombier bp = nbp;
1837dd7cddfSDavid du Colombier }
1847dd7cddfSDavid du Colombier
1857dd7cddfSDavid du Colombier /*
1867dd7cddfSDavid du Colombier * copy uchars from the trailing blocks into the first
1877dd7cddfSDavid du Colombier */
1887dd7cddfSDavid du Colombier n -= BLEN(bp);
1897dd7cddfSDavid du Colombier while(nbp = bp->next){
1907dd7cddfSDavid du Colombier i = BLEN(nbp);
1917dd7cddfSDavid du Colombier if(i >= n) {
1927dd7cddfSDavid du Colombier memmove(bp->wptr, nbp->rptr, n);
1937dd7cddfSDavid du Colombier bp->wptr += n;
1947dd7cddfSDavid du Colombier nbp->rptr += n;
1957dd7cddfSDavid du Colombier return bp;
1967dd7cddfSDavid du Colombier }
1977dd7cddfSDavid du Colombier else {
1987dd7cddfSDavid du Colombier memmove(bp->wptr, nbp->rptr, i);
1997dd7cddfSDavid du Colombier bp->wptr += i;
2007dd7cddfSDavid du Colombier bp->next = nbp->next;
2017dd7cddfSDavid du Colombier nbp->next = nil;
2027dd7cddfSDavid du Colombier freeb(nbp);
2037dd7cddfSDavid du Colombier n -= i;
2047dd7cddfSDavid du Colombier }
2057dd7cddfSDavid du Colombier }
2067dd7cddfSDavid du Colombier freeb(bp);
2077dd7cddfSDavid du Colombier return nil;
2087dd7cddfSDavid du Colombier }
2097dd7cddfSDavid du Colombier
2107dd7cddfSDavid du Colombier /*
2117dd7cddfSDavid du Colombier * Pad a block to the front with n uchars. This is used to add protocol
2127dd7cddfSDavid du Colombier * headers to the front of blocks.
2137dd7cddfSDavid du Colombier */
2147dd7cddfSDavid du Colombier Block*
padb(Block * bp,int n)2157dd7cddfSDavid du Colombier padb(Block *bp, int n)
2167dd7cddfSDavid du Colombier {
2177dd7cddfSDavid du Colombier Block *nbp;
2187dd7cddfSDavid du Colombier
2197dd7cddfSDavid du Colombier if(bp->rptr-bp->base >= n) {
2207dd7cddfSDavid du Colombier bp->rptr -= n;
2217dd7cddfSDavid du Colombier return bp;
2227dd7cddfSDavid du Colombier }
2237dd7cddfSDavid du Colombier else {
2247dd7cddfSDavid du Colombier /* fprint(2, "padb: required %d PAD %d\n", n, PAD) = malloc(sizeof(*required %d PAD %d\n", n, PAD))); */
2257dd7cddfSDavid du Colombier nbp = allocb(n);
2267dd7cddfSDavid du Colombier nbp->wptr = nbp->lim;
2277dd7cddfSDavid du Colombier nbp->rptr = nbp->wptr - n;
2287dd7cddfSDavid du Colombier nbp->next = bp;
2297dd7cddfSDavid du Colombier return nbp;
2307dd7cddfSDavid du Colombier }
2317dd7cddfSDavid du Colombier }
2327dd7cddfSDavid du Colombier
2337dd7cddfSDavid du Colombier Block *
btrim(Block * bp,int offset,int len)2347dd7cddfSDavid du Colombier btrim(Block *bp, int offset, int len)
2357dd7cddfSDavid du Colombier {
2367dd7cddfSDavid du Colombier ulong l;
2377dd7cddfSDavid du Colombier Block *nb, *startb;
2387dd7cddfSDavid du Colombier
2397dd7cddfSDavid du Colombier if(blen(bp) < offset+len) {
2407dd7cddfSDavid du Colombier freeb(bp);
2417dd7cddfSDavid du Colombier return nil;
2427dd7cddfSDavid du Colombier }
2437dd7cddfSDavid du Colombier
2447dd7cddfSDavid du Colombier while((l = BLEN(bp)) < offset) {
2457dd7cddfSDavid du Colombier offset -= l;
2467dd7cddfSDavid du Colombier nb = bp->next;
2477dd7cddfSDavid du Colombier bp->next = nil;
2487dd7cddfSDavid du Colombier freeb(bp);
2497dd7cddfSDavid du Colombier bp = nb;
2507dd7cddfSDavid du Colombier }
2517dd7cddfSDavid du Colombier
2527dd7cddfSDavid du Colombier startb = bp;
2537dd7cddfSDavid du Colombier bp->rptr += offset;
2547dd7cddfSDavid du Colombier
2557dd7cddfSDavid du Colombier while((l = BLEN(bp)) < len) {
2567dd7cddfSDavid du Colombier len -= l;
2577dd7cddfSDavid du Colombier bp = bp->next;
2587dd7cddfSDavid du Colombier }
2597dd7cddfSDavid du Colombier
2607dd7cddfSDavid du Colombier bp->wptr -= (BLEN(bp) - len);
2617dd7cddfSDavid du Colombier bp->flags |= S_DELIM;
2627dd7cddfSDavid du Colombier
2637dd7cddfSDavid du Colombier if(bp->next) {
2647dd7cddfSDavid du Colombier freeb(bp->next);
2657dd7cddfSDavid du Colombier bp->next = nil;
2667dd7cddfSDavid du Colombier }
2677dd7cddfSDavid du Colombier
2687dd7cddfSDavid du Colombier return startb;
2697dd7cddfSDavid du Colombier }
2707dd7cddfSDavid du Colombier
2717dd7cddfSDavid du Colombier Block*
copyb(Block * bp,int count)2727dd7cddfSDavid du Colombier copyb(Block *bp, int count)
2737dd7cddfSDavid du Colombier {
2747dd7cddfSDavid du Colombier int l;
2757dd7cddfSDavid du Colombier Block *nb, *head, **p;
2767dd7cddfSDavid du Colombier
2777dd7cddfSDavid du Colombier p = &head;
2787dd7cddfSDavid du Colombier head = nil;
2797dd7cddfSDavid du Colombier while(bp != nil && count != 0) {
2807dd7cddfSDavid du Colombier l = BLEN(bp);
2817dd7cddfSDavid du Colombier if(count < l)
2827dd7cddfSDavid du Colombier l = count;
2837dd7cddfSDavid du Colombier nb = allocb(l);
2847dd7cddfSDavid du Colombier memmove(nb->wptr, bp->rptr, l);
2857dd7cddfSDavid du Colombier nb->wptr += l;
2867dd7cddfSDavid du Colombier count -= l;
2877dd7cddfSDavid du Colombier nb->flags = bp->flags;
2887dd7cddfSDavid du Colombier *p = nb;
2897dd7cddfSDavid du Colombier p = &nb->next;
2907dd7cddfSDavid du Colombier bp = bp->next;
2917dd7cddfSDavid du Colombier }
2927dd7cddfSDavid du Colombier if(count) {
2937dd7cddfSDavid du Colombier nb = allocb(count);
2947dd7cddfSDavid du Colombier memset(nb->wptr, 0, count);
2957dd7cddfSDavid du Colombier nb->wptr += count;
2967dd7cddfSDavid du Colombier nb->flags |= S_DELIM;
2977dd7cddfSDavid du Colombier *p = nb;
2987dd7cddfSDavid du Colombier }
2997dd7cddfSDavid du Colombier if(blen(head) == 0)
3007dd7cddfSDavid du Colombier fprint(2, "copyb: zero length\n");
3017dd7cddfSDavid du Colombier
3027dd7cddfSDavid du Colombier return head;
3037dd7cddfSDavid du Colombier }
3047dd7cddfSDavid du Colombier
3057dd7cddfSDavid du Colombier int
pullb(Block ** bph,int count)3067dd7cddfSDavid du Colombier pullb(Block **bph, int count)
3077dd7cddfSDavid du Colombier {
3087dd7cddfSDavid du Colombier Block *bp;
3097dd7cddfSDavid du Colombier int n, uchars;
3107dd7cddfSDavid du Colombier
3117dd7cddfSDavid du Colombier uchars = 0;
3127dd7cddfSDavid du Colombier if(bph == nil)
3137dd7cddfSDavid du Colombier return 0;
3147dd7cddfSDavid du Colombier
3157dd7cddfSDavid du Colombier while(*bph != nil && count != 0) {
3167dd7cddfSDavid du Colombier bp = *bph;
3177dd7cddfSDavid du Colombier n = BLEN(bp);
3187dd7cddfSDavid du Colombier if(count < n)
3197dd7cddfSDavid du Colombier n = count;
3207dd7cddfSDavid du Colombier uchars += n;
3217dd7cddfSDavid du Colombier count -= n;
3227dd7cddfSDavid du Colombier bp->rptr += n;
3237dd7cddfSDavid du Colombier if(BLEN(bp) == 0) {
3247dd7cddfSDavid du Colombier *bph = bp->next;
3257dd7cddfSDavid du Colombier bp->next = nil;
3267dd7cddfSDavid du Colombier freeb(bp);
3277dd7cddfSDavid du Colombier }
3287dd7cddfSDavid du Colombier }
3297dd7cddfSDavid du Colombier return uchars;
3307dd7cddfSDavid du Colombier }
3317dd7cddfSDavid du Colombier
3327dd7cddfSDavid du Colombier /*
3337dd7cddfSDavid du Colombier * handy routines for keeping track of allocations
3347dd7cddfSDavid du Colombier */
3357dd7cddfSDavid du Colombier static ulong
callerpc(void * a)3367dd7cddfSDavid du Colombier callerpc(void *a)
3377dd7cddfSDavid du Colombier {
3387dd7cddfSDavid du Colombier return ((ulong*)a)[-1];
3397dd7cddfSDavid du Colombier }
3407dd7cddfSDavid du Colombier static void
aref(Aref * ap,ulong pc)3417dd7cddfSDavid du Colombier aref(Aref *ap, ulong pc)
3427dd7cddfSDavid du Colombier {
3437dd7cddfSDavid du Colombier Arefent *a, *e;
3447dd7cddfSDavid du Colombier
3457dd7cddfSDavid du Colombier e = &ap->tab[Npc-1];
3467dd7cddfSDavid du Colombier qlock(ap);
3477dd7cddfSDavid du Colombier for(a = ap->tab; a < e; a++)
3487dd7cddfSDavid du Colombier if(a->pc == pc || a->pc == 0)
3497dd7cddfSDavid du Colombier break;
3507dd7cddfSDavid du Colombier a->pc = pc;
3517dd7cddfSDavid du Colombier a->n++;
3527dd7cddfSDavid du Colombier qunlock(ap);
3537dd7cddfSDavid du Colombier }
3547dd7cddfSDavid du Colombier static void
aunref(Aref * ap,ulong pc)3557dd7cddfSDavid du Colombier aunref(Aref *ap, ulong pc)
3567dd7cddfSDavid du Colombier {
3577dd7cddfSDavid du Colombier Arefent *a, *e;
3587dd7cddfSDavid du Colombier
3597dd7cddfSDavid du Colombier e = &ap->tab[Npc-1];
3607dd7cddfSDavid du Colombier qlock(ap);
3617dd7cddfSDavid du Colombier for(a = ap->tab; a < e; a++)
3627dd7cddfSDavid du Colombier if(a->pc == pc || a->pc == 0)
3637dd7cddfSDavid du Colombier break;
3647dd7cddfSDavid du Colombier a->n--;
3657dd7cddfSDavid du Colombier qunlock(ap);
3667dd7cddfSDavid du Colombier }
367