home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 5 / DATAFILE_PDCD5.iso / internet / netlite2 / NET / c / MBUF < prev    next >
Encoding:
Text File  |  1992-03-01  |  10.1 KB  |  369 lines

  1. /* Primitive mbuf allocate/free routines */
  2.  
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include "global.h"
  6. #include "mbuf.h"
  7.  
  8. /* Allocate mbuf with associated buffer of 'size' bytes */
  9. struct mbuf *alloc_mbuf(register int16 size)
  10. {
  11.         register struct mbuf *bp;
  12.  
  13.         if((bp = (struct mbuf *)malloc((unsigned)(size + sizeof(struct mbuf)))) == NULLBUF)
  14.                 return NULLBUF;
  15.         bp->next = bp->anext = NULLBUF;
  16.         if(size != 0){
  17.                 bp->data = (char *)(bp + 1);
  18.         } else {
  19.                 bp->data = NULLCHAR;
  20.         }
  21.         bp->size = size;
  22.         bp->cnt = 0;
  23.         return bp;
  24. }
  25.  
  26. /* Free all resources associated with mbuf
  27.  * Return pointer to next mbuf in packet chain
  28.  */
  29. struct mbuf *free_mbuf(register struct mbuf *bp)
  30. {
  31.         register struct mbuf *bp1 = NULLBUF;
  32.  
  33.         if(bp != NULLBUF){
  34.                 bp1 = bp->next;
  35.                 free((char *)bp);
  36.         }
  37.         return bp1;
  38. }
  39.  
  40. /* Free packet (a chain of mbufs). Return pointer to next packet on queue,
  41.  * if any
  42.  */
  43. struct mbuf *free_p(register struct mbuf *bp)
  44. {
  45.         struct mbuf *abp;
  46.  
  47.         if(bp == NULLBUF)
  48.                 return NULLBUF;
  49.         abp = bp->anext;
  50.         while(bp != NULLBUF)
  51.                 bp = free_mbuf(bp);
  52.         return abp;
  53. }               
  54. /* Free entire queue of packets (of mbufs) */
  55. void free_q(struct mbuf **q)
  56. {
  57.         register struct mbuf *bp;
  58.  
  59.         while((bp = dequeue(q)) != NULLBUF)
  60.                 free_p(bp);
  61. }
  62.  
  63. /* Count up the total number of bytes in an mbuf */
  64. int16 len_mbuf(register struct mbuf *bp)
  65. {
  66.         int cnt;
  67.  
  68.         cnt = 0;
  69.         while(bp != NULLBUF){
  70.                 cnt += bp->cnt;
  71.                 bp = bp->next;
  72.         }
  73.         return cnt;
  74. }
  75. /* Count up the number of packets in a queue */
  76. int16 len_q(register struct mbuf *bp)
  77. {
  78.         register int cnt;
  79.  
  80.         for(cnt=0;bp != NULLBUF;cnt++,bp = bp->anext)
  81.                 ;
  82.         return cnt;
  83. }
  84. /* Trim mbuf to specified length by lopping off end */
  85. void trim_mbuf(struct mbuf **bpp, int16 length)
  86. {
  87.         register int16 tot = 0;
  88.         register struct mbuf *bp;
  89.  
  90.         if(bpp == NULLBUFP || *bpp == NULLBUF)
  91.                 return; /* Nothing to trim */
  92.  
  93.         if(length == 0){
  94.                 /* Toss the whole thing */
  95.                 free_p(*bpp);
  96.                 *bpp = NULLBUF;
  97.                 return;
  98.         }
  99.         /* Find the point at which to trim. If length is greater than
  100.          * the packet, we'll just fall through without doing anything
  101.          */
  102.         for( bp = *bpp; bp != NULLBUF; bp = bp->next){
  103.                 if(tot + bp->cnt < length){
  104.                         tot += bp->cnt;
  105.                 } else {
  106.                         /* Cut here */
  107.                         bp->cnt = length - tot;
  108.                         free_p(bp->next);
  109.                         bp->next = NULLBUF;
  110.                         break;
  111.                 }
  112.         }
  113. }
  114. /* Duplicate/enqueue/dequeue operations based on mbufs */
  115.  
  116. /* Duplicate first 'cnt' bytes of packet starting at 'offset'.
  117.  * This is done without copying data; only the headers are duplicated,
  118.  * but without data segments of their own. The pointers are set up to
  119.  * share the data segments of the original copy. The return pointer is
  120.  * passed back through the first argument, and the return value is the
  121.  * number of bytes actually duplicated.
  122.  */
  123. int16 dup_p(struct mbuf **hp, register struct mbuf *bp,
  124.             register int16 offset, register int16 cnt)
  125. {
  126.         register struct mbuf *cp;
  127.         int16 tot;
  128.  
  129.         if(cnt == 0 || bp == NULLBUF || hp == NULLBUFP){
  130.                 if(hp != NULLBUFP)
  131.                         *hp = NULLBUF;
  132.                 return 0;
  133.         }
  134.         if((*hp = cp = alloc_mbuf(0)) == NULLBUF){
  135.                 return 0;
  136.         }
  137.         /* Skip over leading mbufs that are smaller than the offset */
  138.         while(bp != NULLBUF && bp->cnt <= offset){
  139.                 offset -= bp->cnt;
  140.                 bp = bp->next;
  141.         }
  142.         if(bp == NULLBUF){
  143.                 free_mbuf(cp);
  144.                 *hp = NULLBUF;
  145.                 return 0;       /* Offset was too big */
  146.         }
  147.         tot = 0;
  148.         for(;;){
  149.                 cp->data = bp->data + offset;
  150.                 cp->cnt = min(cnt,bp->cnt - offset);
  151.                 offset = 0;
  152.                 cnt -= cp->cnt;
  153.                 tot += cp->cnt;
  154.                 bp = bp->next;
  155.                 if(cnt == 0 || bp == NULLBUF || (cp->next = alloc_mbuf(0)) == NULLBUF)
  156.                         break;
  157.                 cp = cp->next;
  158.         }
  159.         return tot;
  160. }
  161. /* Copy first 'cnt' bytes of packet into a new, single mbuf */
  162. struct mbuf *copy_p(register struct mbuf *bp, register int16 cnt)
  163. {
  164.         register struct mbuf *cp;
  165.         register char *wp;
  166.         register int16 n;
  167.  
  168.         if(bp == NULLBUF || cnt == 0 || (cp = alloc_mbuf(cnt)) == NULLBUF)
  169.                 return NULLBUF;
  170.         wp = cp->data;
  171.         while(cnt != 0 && bp != NULLBUF){
  172.                 n = min(cnt,bp->cnt);
  173.                 memcpy(wp,bp->data,n);
  174.                 wp += n;
  175.                 cp->cnt += n;
  176.                 cnt -= n;
  177.                 bp = bp->next;
  178.         }
  179.         return cp;
  180. }
  181. /* Copy and delete "cnt" bytes from beginning of packet. Return number of
  182.  * bytes actually pulled off
  183.  */
  184. int16 pullup(struct mbuf **bph, char *buf, int16 cnt)
  185. {
  186.         register struct mbuf *bp;
  187.         int16 n,tot;
  188.  
  189.         tot = 0;
  190.         if(bph == NULLBUFP)
  191.                 return 0;
  192.         while(*bph != NULLBUF && cnt != 0){
  193.                 bp = *bph;
  194.                 n = min(cnt,bp->cnt);
  195.                 if(buf != NULLCHAR && n != 0){
  196.                         memcpy(buf,bp->data,n);
  197.                         buf += n;
  198.                 }
  199.                 tot += n;
  200.                 cnt -= n;
  201.                 bp->data += n;
  202.                 bp->cnt -= n;           
  203.                 if(bp->cnt == 0){
  204.                         *bph = free_mbuf(bp);
  205.                 }
  206.         }
  207.         return tot;
  208. }
  209. /* Append mbuf to end of mbuf chain */
  210. void append(struct mbuf **bph, struct mbuf *bp)
  211. {
  212.         register struct mbuf *p;
  213.  
  214.         if(bph == NULLBUFP || bp == NULLBUF)
  215.                 return;
  216.         if(*bph == NULLBUF){
  217.                 /* First one on chain */
  218.                 *bph = bp;
  219.         } else {
  220.                 for(p = *bph ; p->next != NULLBUF ; p = p->next)
  221.                         ;
  222.                 p->next = bp;
  223.         }
  224. }
  225. /* Insert specified amount of contiguous new space at the beginning of an
  226.  * mbuf chain. If enough space is available in the first mbuf, no new space
  227.  * is allocated. Otherwise a mbuf of the appropriate size is allocated and
  228.  * tacked on the front of the chain.
  229.  *
  230.  * This operation is the logical inverse of pullup(), hence the name.
  231.  */
  232. struct mbuf *pushdown(register struct mbuf *bp, int16 size)
  233. {
  234.         register struct mbuf *nbp;
  235.  
  236.         /* Check that bp is real and that there's data space associated with
  237.          * this buffer (i.e., this is not a buffer from dup_p) before
  238.          * checking to see if there's enough space at its front
  239.          */
  240.         if(bp != NULLBUF && bp->size != 0 && bp->data - (char *)(bp+1) >= size){
  241.                 /* No need to alloc new mbuf, just adjust this one */
  242.                 bp->data -= size;
  243.                 bp->cnt += size;
  244.         } else {
  245.                 if((nbp = alloc_mbuf(size)) != NULLBUF){
  246.                         nbp->next = bp;
  247.                         nbp->cnt = size;
  248.                         bp = nbp;
  249.                 } else {
  250.                         bp = NULLBUF;
  251.                 }
  252.         }
  253.         return bp;
  254. }
  255. /* Append packet to end of packet queue */
  256. void enqueue(struct mbuf **q, struct mbuf *bp)
  257. {
  258.         register struct mbuf *p;
  259.  
  260.         if(q == NULLBUFP || bp == NULLBUF)
  261.                 return;
  262.         if(*q == NULLBUF){
  263.                 /* List is empty, stick at front */
  264.                 *q = bp;
  265.         } else {
  266.                 for(p = *q ; p->anext != NULLBUF ; p = p->anext)
  267.                         ;
  268.                 p->anext = bp;
  269.         }
  270. }
  271. /* Unlink a packet from the head of the queue */
  272. struct mbuf *dequeue(register struct mbuf **q)
  273. {
  274.         register struct mbuf *bp;
  275.  
  276.         if(q == NULLBUFP)
  277.                 return NULLBUF;
  278.         if((bp = *q) != NULLBUF){
  279.                 *q = bp->anext;
  280.                 bp->anext = NULLBUF;
  281.         }
  282.         return bp;
  283. }       
  284.  
  285. /* Copy user data into an mbuf */
  286. struct mbuf *qdata(char *data, int16 cnt)
  287. {
  288.         register struct mbuf *bp;
  289.  
  290.         if((bp = alloc_mbuf(cnt)) == NULLBUF)
  291.                 return NULLBUF;
  292.         memcpy(bp->data,data,cnt);
  293.         bp->cnt = cnt;
  294.         return bp;
  295. }
  296. /* Copy mbuf data into user buffer */
  297. int16 dqdata(struct mbuf *bp, char *buf, unsigned cnt)
  298. {
  299.         unsigned n,tot;
  300.         struct mbuf *bp1;
  301.  
  302.         if(buf == NULLCHAR)
  303.                 return 0;
  304.         
  305.         tot = 0;
  306.         for(bp1 = bp;bp1 != NULLBUF; bp1 = bp1->next){
  307.                 n = min(bp1->cnt,cnt);
  308.                 memcpy(buf,bp1->data,n);
  309.                 cnt -= n;
  310.                 buf += n;
  311.                 tot += n;
  312.         }
  313.         free_p(bp);
  314.         return tot;
  315. }
  316. /* Pull a 32-bit integer in host order from buffer in network byte order */
  317. int32 pull32(struct mbuf **bpp)
  318. {
  319.         int32 rval;
  320.         char buf[4];
  321.         register char *cp;
  322.  
  323.         if(pullup(bpp,buf,4) != 4){
  324.                 /* Return zero if insufficient buffer */
  325.                 return 0;
  326.         }
  327.         cp = buf;
  328.  
  329.         /* Unwound for speed */
  330.         rval = uchar(*cp++);
  331.         rval <<= 8;
  332.         rval |= uchar(*cp++);
  333.         rval <<= 8;
  334.         rval |= uchar(*cp++);
  335.         rval <<= 8;
  336.         rval |= uchar(*cp);
  337.  
  338.         return rval;
  339. }
  340. /* Pull a 16-bit integer in host order from buffer in network byte order */
  341. int16 pull16(struct mbuf **bpp)
  342. {
  343.         int16 rval;
  344.         char buf[2];
  345.         register char *cp;
  346.  
  347.         if(pullup(bpp,buf,2) != 2){
  348.                 /* Return zero if insufficient buffer */
  349.                 return 0;
  350.         }
  351.         cp = buf;
  352.  
  353.         rval = uchar(*cp++);
  354.         rval <<= 8;
  355.         rval |= uchar(*cp);
  356.         return rval;
  357. }
  358. /* Pull single character from mbuf */
  359. char pullchar(struct mbuf **bpp)
  360. {
  361.         char c;
  362.  
  363.         if(pullup(bpp,&c,1) != 1)
  364.                 /* Return zero if nothing left */
  365.                 c = 0;
  366.         return c;
  367. }
  368.  
  369.