/* * mbuf.c * * Written by Toshiharu OHNO * Copyright (c) 1993, Internet Initiative Japan, Inc. All rights reserved. * See ``COPYRIGHT.iij'' * * Rewritten by Archie Cobbs * Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved. * See ``COPYRIGHT.whistle'' */ #include "ppp.h" /* * Malloc() * * Replacement for the usual malloc() */ void * Malloc(const char *type, size_t size) { const char **memory; if ((memory = MALLOC(type, sizeof(char *) + size)) == NULL) { Perror("Malloc: malloc"); DoExit(EX_ERRDEAD); } memory[0] = type; bzero(memory + 1, size); return (memory + 1); } /* * Mdup() * * Malloc() + memcpy() */ void * Mdup(const char *type, const void *src, size_t size) { const char **memory; if ((memory = MALLOC(type, sizeof(char *) + size)) == NULL) { Perror("Mdup: malloc"); DoExit(EX_ERRDEAD); } memory[0] = type; memcpy(memory + 1, src, size); return(memory + 1); } void * Mdup2(const char *type, const void *src, size_t oldsize, size_t newsize) { const char **memory; if ((memory = MALLOC(type, sizeof(char *) + newsize)) == NULL) { Perror("Mdup2: malloc"); DoExit(EX_ERRDEAD); } memory[0] = type; memcpy(memory + 1, src, oldsize < newsize ? oldsize : newsize); return(memory + 1); } void * Mstrdup(const char *type, const void *src) { return (Mdup(type, src, strlen(src) + 1)); } /* * Freee() * * Replacement for the ususal free() */ void Freee(void *ptr) { if (ptr) { char **memory = ptr; memory--; FREE(memory[0], memory); } } /* * mballoc() * * Allocate an mbuf with memory */ Mbuf mballoc(int size) { u_char *memory; int amount, osize; Mbuf bp; assert(size >= 0); if (size == 0) { osize = 64 - sizeof(*bp); } else if (size < 512) osize = ((size - 1) / 32 + 1) * 64 - sizeof(*bp); else osize = ((size - 1) / 64 + 1) * 64 + 512 - sizeof(*bp); amount = sizeof(*bp) + osize; if ((memory = MALLOC(MB_MBUF, amount)) == NULL) { Perror("mballoc: malloc"); DoExit(EX_ERRDEAD); } /* Put mbuf at front of memory region */ bp = (Mbuf)(void *)memory; bp->size = osize; bp->offset = (osize - size) / 2; bp->cnt = 0; return (bp); } /* * mbfree() * * Free head of chain, return next */ void mbfree(Mbuf bp) { if (bp) FREE(MB_MBUF, bp); } /* * mbread() * * Read contents of an mbuf chain into buffer, consuming len bytes. * If all of the chain is consumed, return NULL. * * This should ALWAYS be called like this: * bp = mbread(bp, ... ); */ Mbuf mbread(Mbuf bp, void *buf, int cnt) { int nread; assert(cnt >= 0); if (!bp) return (NULL); if (cnt > bp->cnt) nread = bp->cnt; else nread = cnt; memcpy(buf, MBDATAU(bp), nread); bp->offset += nread; bp->cnt -= nread; if (bp->cnt == 0) { mbfree(bp); return (NULL); } return(bp); } /* * mbcopy() * * Copy contents of an mbuf chain into buffer, up to "cnt" bytes. * This does not consume any of the mbuf chain. Returns number copied. */ int mbcopy(Mbuf bp, int offset, void *buf, int cnt) { int nread; assert(offset >= 0); assert(cnt >= 0); if (!bp) return (0); if (offset >= bp->cnt) return (0); if (cnt > bp->cnt - offset) nread = bp->cnt - offset; else nread = cnt; memcpy(buf, MBDATAU(bp) + offset, nread); return (nread); } /* * mbcopyback() * * Write bytes from buffer into an mbuf chain. Returns first argument. */ Mbuf mbcopyback(Mbuf bp, int offset, const void *buf, int cnt) { int b, e; if (!bp) { if (offset < 0) offset = 0; bp = mballoc(offset + cnt); memcpy(MBDATAU(bp) + offset, buf, cnt); bp->cnt = offset + cnt; return (bp); } b = (offset > 0) ? 0 : -offset; e = (offset + cnt > bp->cnt) ? offset + cnt - bp->cnt : 0; if (b + bp->cnt + e > bp->size) { Mbuf nbp = mballoc(b + bp->cnt + e); memcpy(MBDATAU(nbp) + b, MBDATAU(bp), bp->cnt); nbp->cnt = bp->cnt; mbfree(bp); bp = nbp; } else if ((b > bp->offset) || (bp->offset + bp->cnt + e > bp->size)) { int noff = (bp->size - (b + bp->cnt + e)) / 2; memmove(MBDATAU(bp) - bp->offset + noff + b, MBDATAU(bp), bp->cnt); bp->offset = noff; } else { bp->offset -= b; } bp->cnt = b + bp->cnt + e; memcpy(MBDATAU(bp) + offset + b, buf, cnt); return(bp); } /* * mbtrunc() * * Truncate mbuf to total of "max" bytes. If max is zero * then a zero length mbuf is returned (rather than a NULL mbuf). */ Mbuf mbtrunc(Mbuf bp, int max) { assert(max >= 0); if (!bp) return (NULL); if (bp->cnt > max) bp->cnt = max; return (bp); } /* * mbadj() * * Truncate mbuf cutting "cnt" bytes from begin or end. */ Mbuf mbadj(Mbuf bp, int cnt) { if (!bp) return (NULL); if (cnt >= 0) { if (bp->cnt > cnt) { bp->cnt -= cnt; bp->offset += cnt; } else { bp->cnt = 0; } } else { if (bp->cnt > -cnt) { bp->cnt -= -cnt; } else { bp->cnt = 0; } } return (bp); } /* * mbsplit() * * Break an mbuf chain after "cnt" bytes. * Return the newly created mbuf chain that * starts after "cnt" bytes. If MBLEN(bp) <= cnt, * then returns NULL. The first part of * the chain remains pointed to by "bp". */ Mbuf mbsplit(Mbuf bp, int cnt) { Mbuf nbp; assert(cnt >= 0); if (!bp) return (NULL); if ((int)MBLEN(bp) <= cnt) return (NULL); nbp = mballoc(bp->cnt - cnt); memcpy(MBDATAU(nbp), MBDATAU(bp) + cnt, bp->cnt - cnt); nbp->cnt = bp->cnt - cnt; bp->cnt = cnt; return(nbp); } /* * MemStat() */ int MemStat(Context ctx, int ac, const char *const av[], const void *arg) { struct typed_mem_stats stats; u_int i; u_int total_allocs = 0; u_int total_bytes = 0; (void)ac; (void)av; (void)arg; if (typed_mem_usage(&stats)) Error("typed_mem_usage() error"); /* Print header */ Printf(" %-28s %10s %10s\r\n", "Type", "Count", "Total"); Printf(" %-28s %10s %10s\r\n", "----", "-----", "-----"); for (i = 0; i < stats.length; i++) { struct typed_mem_typestats *type = &stats.elems[i]; Printf(" %-28s %10u %10lu\r\n", type->type, (int)type->allocs, (u_long)type->bytes); total_allocs += type->allocs; total_bytes += type->bytes; } /* Print totals */ Printf(" %-28s %10s %10s\r\n", "", "-----", "-----"); Printf(" %-28s %10lu %10lu\r\n", "Totals", total_allocs, total_bytes); structs_free(&typed_mem_stats_type, NULL, &stats); return(0); }