|
|
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.