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