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