|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1995 Danny Gasparovski ! 3: * ! 4: * Please read the file COPYRIGHT for the ! 5: * terms and conditions of the copyright. ! 6: */ ! 7: ! 8: /* ! 9: * mbuf's in SLiRP are much simpler than the real mbufs in ! 10: * FreeBSD. They are fixed size, determined by the MTU, ! 11: * so that one whole packet can fit. Mbuf's cannot be ! 12: * chained together. If there's more data than the mbuf ! 13: * could hold, an external malloced buffer is pointed to ! 14: * by m_ext (and the data pointers) and M_EXT is set in ! 15: * the flags ! 16: */ ! 17: ! 18: #include <stdlib.h> ! 19: #include <slirp.h> ! 20: ! 21: struct mbuf *mbutl; ! 22: char *mclrefcnt; ! 23: int mbuf_alloced = 0; ! 24: struct mbuf m_freelist, m_usedlist; ! 25: int mbuf_thresh = 30; ! 26: int mbuf_max = 0; ! 27: size_t msize; ! 28: ! 29: void m_init() ! 30: { ! 31: m_freelist.m_next = m_freelist.m_prev = &m_freelist; ! 32: m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist; ! 33: msize_init(); ! 34: } ! 35: ! 36: void msize_init() ! 37: { ! 38: /* ! 39: * Find a nice value for msize ! 40: * XXX if_maxlinkhdr already in mtu ! 41: */ ! 42: msize = (if_mtu>if_mru?if_mtu:if_mru) + ! 43: if_maxlinkhdr + sizeof(struct m_hdr ) + 6; ! 44: } ! 45: ! 46: /* ! 47: * Get an mbuf from the free list, if there are none ! 48: * malloc one ! 49: * ! 50: * Because fragmentation can occur if we alloc new mbufs and ! 51: * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE, ! 52: * which tells m_free to actually free() it ! 53: */ ! 54: struct mbuf *m_get() ! 55: { ! 56: register struct mbuf *m; ! 57: int flags = 0; ! 58: ! 59: DEBUG_CALL("m_get"); ! 60: ! 61: if (m_freelist.m_next == &m_freelist) { ! 62: m = (struct mbuf *)malloc(msize); ! 63: if (m == NULL) goto end_error; ! 64: mbuf_alloced++; ! 65: if (mbuf_alloced > mbuf_thresh) ! 66: flags = M_DOFREE; ! 67: if (mbuf_alloced > mbuf_max) ! 68: mbuf_max = mbuf_alloced; ! 69: } else { ! 70: m = m_freelist.m_next; ! 71: remque(m); ! 72: } ! 73: ! 74: /* Insert it in the used list */ ! 75: insque(m,&m_usedlist); ! 76: m->m_flags = (flags | M_USEDLIST); ! 77: ! 78: /* Initialise it */ ! 79: m->m_size = msize - sizeof(struct m_hdr); ! 80: m->m_data = m->m_dat; ! 81: m->m_len = 0; ! 82: m->m_nextpkt = 0; ! 83: m->m_prevpkt = 0; ! 84: end_error: ! 85: DEBUG_ARG("m = %lx", (long )m); ! 86: return m; ! 87: } ! 88: ! 89: void m_free(struct mbuf *m) ! 90: { ! 91: ! 92: DEBUG_CALL("m_free"); ! 93: DEBUG_ARG("m = %lx", (long )m); ! 94: ! 95: if(m) { ! 96: /* Remove from m_usedlist */ ! 97: if (m->m_flags & M_USEDLIST) ! 98: remque(m); ! 99: ! 100: /* If it's M_EXT, free() it */ ! 101: if (m->m_flags & M_EXT) ! 102: free(m->m_ext); ! 103: ! 104: /* ! 105: * Either free() it or put it on the free list ! 106: */ ! 107: if (m->m_flags & M_DOFREE) { ! 108: free(m); ! 109: mbuf_alloced--; ! 110: } else if ((m->m_flags & M_FREELIST) == 0) { ! 111: insque(m,&m_freelist); ! 112: m->m_flags = M_FREELIST; /* Clobber other flags */ ! 113: } ! 114: } /* if(m) */ ! 115: } ! 116: ! 117: /* ! 118: * Copy data from one mbuf to the end of ! 119: * the other.. if result is too big for one mbuf, malloc() ! 120: * an M_EXT data segment ! 121: */ ! 122: void m_cat(register struct mbuf *m, register struct mbuf *n) ! 123: { ! 124: /* ! 125: * If there's no room, realloc ! 126: */ ! 127: if (M_FREEROOM(m) < n->m_len) ! 128: m_inc(m,m->m_size+MINCSIZE); ! 129: ! 130: memcpy(m->m_data+m->m_len, n->m_data, n->m_len); ! 131: m->m_len += n->m_len; ! 132: ! 133: m_free(n); ! 134: } ! 135: ! 136: ! 137: /* make m size bytes large */ ! 138: void m_inc(struct mbuf *m, u_int size) ! 139: { ! 140: int datasize; ! 141: ! 142: /* some compiles throw up on gotos. This one we can fake. */ ! 143: if(m->m_size>size) return; ! 144: ! 145: if (m->m_flags & M_EXT) { ! 146: datasize = m->m_data - m->m_ext; ! 147: m->m_ext = (char *)realloc(m->m_ext,size); ! 148: /* if (m->m_ext == NULL) ! 149: * return (struct mbuf *)NULL; ! 150: */ ! 151: m->m_data = m->m_ext + datasize; ! 152: } else { ! 153: char *dat; ! 154: datasize = m->m_data - m->m_dat; ! 155: dat = (char *)malloc(size); ! 156: /* if (dat == NULL) ! 157: * return (struct mbuf *)NULL; ! 158: */ ! 159: memcpy(dat, m->m_dat, m->m_size); ! 160: ! 161: m->m_ext = dat; ! 162: m->m_data = m->m_ext + datasize; ! 163: m->m_flags |= M_EXT; ! 164: } ! 165: ! 166: m->m_size = size; ! 167: ! 168: } ! 169: ! 170: ! 171: ! 172: void m_adj(struct mbuf *m, int len) ! 173: { ! 174: if (m == NULL) ! 175: return; ! 176: if (len >= 0) { ! 177: /* Trim from head */ ! 178: m->m_data += len; ! 179: m->m_len -= len; ! 180: } else { ! 181: /* Trim from tail */ ! 182: len = -len; ! 183: m->m_len -= len; ! 184: } ! 185: } ! 186: ! 187: ! 188: /* ! 189: * Copy len bytes from m, starting off bytes into n ! 190: */ ! 191: int ! 192: m_copy(struct mbuf *n, struct mbuf *m, u_int off, u_int len) ! 193: { ! 194: if (len > M_FREEROOM(n)) ! 195: return -1; ! 196: ! 197: memcpy((n->m_data + n->m_len), (m->m_data + off), len); ! 198: n->m_len += len; ! 199: return 0; ! 200: } ! 201: ! 202: ! 203: /* ! 204: * Given a pointer into an mbuf, return the mbuf ! 205: * XXX This is a kludge, I should eliminate the need for it ! 206: * Fortunately, it's not used often ! 207: */ ! 208: struct mbuf *dtom(void *dat) ! 209: { ! 210: struct mbuf *m; ! 211: ! 212: DEBUG_CALL("dtom"); ! 213: DEBUG_ARG("dat = %lx", (long )dat); ! 214: ! 215: /* bug corrected for M_EXT buffers */ ! 216: for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next) { ! 217: if (m->m_flags & M_EXT) { ! 218: if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) ) ! 219: return m; ! 220: } else { ! 221: if( (char *)dat >= m->m_dat && (char *)dat<(m->m_dat + m->m_size) ) ! 222: return m; ! 223: } ! 224: } ! 225: ! 226: DEBUG_ERROR((dfd, "dtom failed")); ! 227: ! 228: return (struct mbuf *)0; ! 229: } ! 230:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.