xref: /freebsd/usr.sbin/ppp/mbuf.c (revision 4cf49a43559ed9fdad601bdcccd2c55963008675)
1 /*
2  *	      PPP Memory handling module
3  *
4  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5  *
6  *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by the Internet Initiative Japan, Inc.  The name of the
14  * IIJ may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  *
20  * $FreeBSD$
21  *
22  */
23 #include <sys/types.h>
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sysexits.h>
29 #include <termios.h>
30 
31 #include "defs.h"
32 #include "command.h"
33 #include "mbuf.h"
34 #include "log.h"
35 #include "descriptor.h"
36 #include "prompt.h"
37 #include "main.h"
38 
39 static struct memmap {
40   struct mbuf *queue;
41   int fragments, octets;
42 } MemMap[MB_MAX + 1];
43 
44 static int totalalloced;
45 static unsigned long long mbuf_Mallocs, mbuf_Frees;
46 
47 int
48 mbuf_Length(struct mbuf *bp)
49 {
50   int len;
51 
52   for (len = 0; bp; bp = bp->next)
53     len += bp->cnt;
54   return len;
55 }
56 
57 struct mbuf *
58 mbuf_Alloc(int cnt, int type)
59 {
60   struct mbuf *bp;
61 
62   if (type > MB_MAX) {
63     log_Printf(LogERROR, "Bad mbuf type %d\n", type);
64     type = MB_UNKNOWN;
65   }
66   bp = malloc(sizeof(struct mbuf) + cnt);
67   if (bp == NULL) {
68     log_Printf(LogALERT, "failed to allocate memory: %ld\n",
69                (long)sizeof(struct mbuf));
70     AbortProgram(EX_OSERR);
71   }
72   mbuf_Mallocs++;
73   memset(bp, '\0', sizeof(struct mbuf));
74   MemMap[type].fragments++;
75   MemMap[type].octets += cnt;
76   totalalloced += cnt;
77   bp->size = bp->cnt = cnt;
78   bp->type = type;
79   return bp;
80 }
81 
82 struct mbuf *
83 mbuf_FreeSeg(struct mbuf *bp)
84 {
85   struct mbuf *nbp;
86 
87   if (bp) {
88     nbp = bp->next;
89     MemMap[bp->type].fragments--;
90     MemMap[bp->type].octets -= bp->size;
91     totalalloced -= bp->size;
92     free(bp);
93     mbuf_Frees++;
94     bp = nbp;
95   }
96 
97   return bp;
98 }
99 
100 void
101 mbuf_Free(struct mbuf *bp)
102 {
103   while (bp)
104     bp = mbuf_FreeSeg(bp);
105 }
106 
107 struct mbuf *
108 mbuf_Read(struct mbuf *bp, void *v, size_t len)
109 {
110   int nb;
111   u_char *ptr = v;
112 
113   while (bp && len > 0) {
114     if (len > bp->cnt)
115       nb = bp->cnt;
116     else
117       nb = len;
118     if (nb) {
119       memcpy(ptr, MBUF_CTOP(bp), nb);
120       ptr += nb;
121       bp->cnt -= nb;
122       len -= nb;
123       bp->offset += nb;
124     }
125     if (bp->cnt == 0)
126       bp = mbuf_FreeSeg(bp);
127   }
128 
129   while (bp && bp->cnt == 0)
130     bp = mbuf_FreeSeg(bp);
131 
132   return bp;
133 }
134 
135 size_t
136 mbuf_View(struct mbuf *bp, void *v, size_t len)
137 {
138   size_t nb, l = len;
139   u_char *ptr = v;
140 
141   while (bp && l > 0) {
142     if (l > bp->cnt)
143       nb = bp->cnt;
144     else
145       nb = l;
146     memcpy(ptr, MBUF_CTOP(bp), nb);
147     ptr += nb;
148     l -= nb;
149     bp = bp->next;
150   }
151 
152   return len - l;
153 }
154 
155 struct mbuf *
156 mbuf_Prepend(struct mbuf *bp, const void *ptr, size_t len, size_t extra)
157 {
158   struct mbuf *head;
159 
160   if (bp && bp->offset) {
161     if (bp->offset >= len) {
162       bp->offset -= len;
163       bp->cnt += len;
164       memcpy(MBUF_CTOP(bp), ptr, len);
165       return bp;
166     }
167     len -= bp->offset;
168     memcpy(bp + sizeof *bp, (const char *)ptr + len, bp->offset);
169     bp->cnt += bp->offset;
170     bp->offset = 0;
171   }
172 
173   head = mbuf_Alloc(len + extra, bp ? bp->type : MB_UNKNOWN);
174   head->offset = extra;
175   head->cnt -= extra;
176   memcpy(MBUF_CTOP(head), ptr, len);
177   head->next = bp;
178 
179   return head;
180 }
181 
182 struct mbuf *
183 mbuf_Truncate(struct mbuf *bp, size_t n)
184 {
185   if (n == 0) {
186     mbuf_Free(bp);
187     return NULL;
188   }
189 
190   for (; bp; bp = bp->next, n -= bp->cnt)
191     if (n < bp->cnt) {
192       bp->cnt = n;
193       mbuf_Free(bp->next);
194       bp->next = NULL;
195       break;
196     }
197 
198   return bp;
199 }
200 
201 void
202 mbuf_Write(struct mbuf *bp, const void *ptr, size_t cnt)
203 {
204   int plen;
205   int nb;
206 
207   plen = mbuf_Length(bp);
208   if (plen < cnt)
209     cnt = plen;
210 
211   while (cnt > 0) {
212     nb = (cnt < bp->cnt) ? cnt : bp->cnt;
213     memcpy(MBUF_CTOP(bp), ptr, nb);
214     cnt -= bp->cnt;
215     bp = bp->next;
216   }
217 }
218 
219 int
220 mbuf_Show(struct cmdargs const *arg)
221 {
222   int i;
223   static const char *mbuftype[] = {
224     "ip in", "ip out", "nat in", "nat out", "mp in", "mp out",
225     "vj in", "vj out", "icompd in", "icompd out", "compd in", "compd out",
226     "lqr in", "lqr out", "echo in", "echo out", "proto in", "proto out",
227     "acf in", "acf out", "sync in", "sync out", "hdlc in", "hdlc out",
228     "async in", "async out", "cbcp in", "cbcp out", "chap in", "chap out",
229     "pap in", "pap out", "ccp in", "ccp out", "ipcp in", "ipcp out",
230     "lcp in", "lcp out", "unknown"
231   };
232 
233   prompt_Printf(arg->prompt, "Fragments (octets) in use:\n");
234   for (i = 0; i < MB_MAX; i += 2)
235     prompt_Printf(arg->prompt, "%10.10s: %04d (%06d)\t%10.10s: %04d (%06d)\n",
236 	    mbuftype[i], MemMap[i].fragments, MemMap[i].octets,
237             mbuftype[i+1], MemMap[i+1].fragments, MemMap[i+1].octets);
238 
239   if (i == MB_MAX)
240     prompt_Printf(arg->prompt, "%10.10s: %04d (%06d)\n",
241                   mbuftype[i], MemMap[i].fragments, MemMap[i].octets);
242 
243   prompt_Printf(arg->prompt, "Mallocs: %llu,   Frees: %llu\n",
244                 mbuf_Mallocs, mbuf_Frees);
245 
246   return 0;
247 }
248 
249 struct mbuf *
250 mbuf_Dequeue(struct mqueue *q)
251 {
252   struct mbuf *bp;
253 
254   log_Printf(LogDEBUG, "mbuf_Dequeue: queue len = %d\n", q->qlen);
255   bp = q->top;
256   if (bp) {
257     q->top = q->top->pnext;
258     q->qlen--;
259     if (q->top == NULL) {
260       q->last = q->top;
261       if (q->qlen)
262 	log_Printf(LogERROR, "mbuf_Dequeue: Not zero (%d)!!!\n", q->qlen);
263     }
264     bp->pnext = NULL;
265   }
266 
267   return bp;
268 }
269 
270 void
271 mbuf_Enqueue(struct mqueue *queue, struct mbuf *bp)
272 {
273   if (bp != NULL) {
274     if (queue->last) {
275       queue->last->pnext = bp;
276       queue->last = bp;
277     } else
278       queue->last = queue->top = bp;
279     queue->qlen++;
280     log_Printf(LogDEBUG, "mbuf_Enqueue: len = %d\n", queue->qlen);
281   }
282 }
283 
284 struct mbuf *
285 mbuf_Contiguous(struct mbuf *bp)
286 {
287   /* Put it all in one contigous (aligned) mbuf */
288 
289   if (bp != NULL) {
290     if (bp->next != NULL) {
291       struct mbuf *nbp;
292       u_char *cp;
293 
294       nbp = mbuf_Alloc(mbuf_Length(bp), bp->type);
295 
296       for (cp = MBUF_CTOP(nbp); bp; bp = mbuf_FreeSeg(bp)) {
297         memcpy(cp, MBUF_CTOP(bp), bp->cnt);
298         cp += bp->cnt;
299       }
300       bp = nbp;
301     }
302 #ifndef __i386__	/* Do any other archs not care about alignment ? */
303     else if ((bp->offset & (sizeof(long) - 1)) != 0) {
304       bcopy(MBUF_CTOP(bp), bp + 1, bp->cnt);
305       bp->offset = 0;
306     }
307 #endif
308   }
309 
310   return bp;
311 }
312 
313 void
314 mbuf_SetType(struct mbuf *bp, int type)
315 {
316   for (; bp; bp = bp->next)
317     if (type != bp->type) {
318       MemMap[bp->type].fragments--;
319       MemMap[bp->type].octets -= bp->size;
320       bp->type = type;
321       MemMap[type].fragments++;
322       MemMap[type].octets += bp->size;
323     }
324 }
325