]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/smbfs/lib/smb/mbuf.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / smbfs / lib / smb / mbuf.c
1 /*
2  * Copyright (c) 2000, Boris Popov
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *    This product includes software developed by Boris Popov.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $Id: mbuf.c,v 1.6 2001/02/24 15:56:04 bp Exp $
33  */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 #include <sys/types.h>
39 #include <sys/endian.h>
40 #include <arpa/inet.h>
41 #include <ctype.h>
42 #include <errno.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46
47 #include <netsmb/smb_lib.h>
48
49 #define MBERROR(format, args...) printf("%s(%d): "format, __FUNCTION__ , \
50                                     __LINE__ ,## args)
51
52 static int
53 m_get(size_t len, struct mbuf **mpp)
54 {
55         struct mbuf *m;
56
57         len = M_ALIGN(len);
58         if (len < M_MINSIZE)
59                 len = M_MINSIZE;
60         m = malloc(M_BASESIZE + len);
61         if (m == NULL)
62                 return ENOMEM;
63         bzero(m, M_BASESIZE + len);
64         m->m_maxlen = len;
65         m->m_data = M_TOP(m);
66         *mpp = m;
67         return 0;
68 }
69
70 static void
71 m_free(struct mbuf *m)
72 {
73         free(m);
74 }
75
76 static void
77 m_freem(struct mbuf *m0)
78 {
79         struct mbuf *m;
80
81         while (m0) {
82                 m = m0->m_next;
83                 m_free(m0);
84                 m0 = m;
85         }
86 }
87
88 static size_t
89 m_totlen(struct mbuf *m0)
90 {
91         struct mbuf *m = m0;
92         int len = 0;
93
94         while (m) {
95                 len += m->m_len;
96                 m = m->m_next;
97         }
98         return len;
99 }
100
101 int
102 m_lineup(struct mbuf *m0, struct mbuf **mpp)
103 {
104         struct mbuf *nm, *m;
105         char *dp;
106         size_t len;
107         int error;
108
109         if (m0->m_next == NULL) {
110                 *mpp = m0;
111                 return 0;
112         }
113         if ((error = m_get(m_totlen(m0), &nm)) != 0)
114                 return error;
115         dp = mtod(nm, char *);
116         while (m0) {
117                 len = m0->m_len;
118                 bcopy(m0->m_data, dp, len);
119                 dp += len;
120                 m = m0->m_next;
121                 m_free(m0);
122                 m0 = m;
123         }
124         *mpp = nm;
125         return 0;
126 }
127
128 int
129 mb_init(struct mbdata *mbp, size_t size)
130 {
131         struct mbuf *m;
132         int error;
133
134         if ((error = m_get(size, &m)) != 0)
135                 return error;
136         return mb_initm(mbp, m);
137 }
138
139 int
140 mb_initm(struct mbdata *mbp, struct mbuf *m)
141 {
142         bzero(mbp, sizeof(*mbp));
143         mbp->mb_top = mbp->mb_cur = m;
144         mbp->mb_pos = mtod(m, char *);
145         return 0;
146 }
147
148 int
149 mb_done(struct mbdata *mbp)
150 {
151         if (mbp->mb_top) {
152                 m_freem(mbp->mb_top);
153                 mbp->mb_top = NULL;
154         }
155         return 0;
156 }
157
158 /*
159 int
160 mb_fixhdr(struct mbdata *mbp)
161 {
162         struct mbuf *m = mbp->mb_top;
163         int len = 0;
164
165         while (m) {
166                 len += m->m_len;
167                 m = m->m_next;
168         }
169         mbp->mb_top->m_pkthdr.len = len;
170         return len;
171 }
172 */
173 int
174 m_getm(struct mbuf *top, size_t len, struct mbuf **mpp)
175 {
176         struct mbuf *m, *mp;
177         int error;
178         
179         for (mp = top; ; mp = mp->m_next) {
180                 len -= M_TRAILINGSPACE(mp);
181                 if (mp->m_next == NULL)
182                         break;
183                 
184         }
185         if (len > 0) {
186                 if ((error = m_get(len, &m)) != 0)
187                         return error;
188                 mp->m_next = m;
189         }
190         *mpp = top;
191         return 0;
192 }
193
194 /*
195  * Routines to put data in a buffer
196  */
197 #define MB_PUT(t)       int error; t *p; \
198                         if ((error = mb_fit(mbp, sizeof(t), (char**)&p)) != 0) \
199                                 return error
200
201 /*
202  * Check if object of size 'size' fit to the current position and
203  * allocate new mbuf if not. Advance pointers and increase length of mbuf(s).
204  * Return pointer to the object placeholder or NULL if any error occured.
205  */
206 int
207 mb_fit(struct mbdata *mbp, size_t size, char **pp)
208 {
209         struct mbuf *m, *mn;
210         int error;
211
212         m = mbp->mb_cur;
213         if (M_TRAILINGSPACE(m) < (int)size) {
214                 if ((error = m_get(size, &mn)) != 0)
215                         return error;
216                 mbp->mb_pos = mtod(mn, char *);
217                 mbp->mb_cur = m->m_next = mn;
218                 m = mn;
219         }
220         m->m_len += size;
221         *pp = mbp->mb_pos;
222         mbp->mb_pos += size;
223         mbp->mb_count += size;
224         return 0;
225 }
226
227 int
228 mb_put_uint8(struct mbdata *mbp, u_int8_t x)
229 {
230         MB_PUT(u_int8_t);
231         *p = x;
232         return 0;
233 }
234
235 int
236 mb_put_uint16be(struct mbdata *mbp, u_int16_t x)
237 {
238         MB_PUT(u_int16_t);
239         setwbe(p, 0, x);
240         return 0;
241 }
242
243 int
244 mb_put_uint16le(struct mbdata *mbp, u_int16_t x)
245 {
246         MB_PUT(u_int16_t);
247         setwle(p, 0, x);
248         return 0;
249 }
250
251 int
252 mb_put_uint32be(struct mbdata *mbp, u_int32_t x)
253 {
254         MB_PUT(u_int32_t);
255         setdbe(p, 0, x);
256         return 0;
257 }
258
259 int
260 mb_put_uint32le(struct mbdata *mbp, u_int32_t x)
261 {
262         MB_PUT(u_int32_t);
263         setdle(p, 0, x);
264         return 0;
265 }
266
267 int
268 mb_put_int64be(struct mbdata *mbp, int64_t x)
269 {
270         MB_PUT(int64_t);
271         *p = htobe64(x);
272         return 0;
273 }
274
275 int
276 mb_put_int64le(struct mbdata *mbp, int64_t x)
277 {
278         MB_PUT(int64_t);
279         *p = htole64(x);
280         return 0;
281 }
282
283 int
284 mb_put_mem(struct mbdata *mbp, const char *source, size_t size)
285 {
286         struct mbuf *m;
287         char * dst;
288         size_t cplen;
289         int error;
290
291         if (size == 0)
292                 return 0;
293         m = mbp->mb_cur;
294         if ((error = m_getm(m, size, &m)) != 0)
295                 return error;
296         while (size > 0) {
297                 cplen = M_TRAILINGSPACE(m);
298                 if (cplen == 0) {
299                         m = m->m_next;
300                         continue;
301                 }
302                 if (cplen > size)
303                         cplen = size;
304                 dst = mtod(m, char *) + m->m_len;
305                 if (source) {
306                         bcopy(source, dst, cplen);
307                         source += cplen;
308                 } else
309                         bzero(dst, cplen);
310                 size -= cplen;
311                 m->m_len += cplen;
312                 mbp->mb_count += cplen;
313         }
314         mbp->mb_pos = mtod(m, char *) + m->m_len;
315         mbp->mb_cur = m;
316         return 0;
317 }
318
319 int
320 mb_put_mbuf(struct mbdata *mbp, struct mbuf *m)
321 {
322         mbp->mb_cur->m_next = m;
323         while (m) {
324                 mbp->mb_count += m->m_len;
325                 if (m->m_next == NULL)
326                         break;
327                 m = m->m_next;
328         }
329         mbp->mb_pos = mtod(m, char *) + m->m_len;
330         mbp->mb_cur = m;
331         return 0;
332 }
333
334 int 
335 mb_put_pstring(struct mbdata *mbp, const char *s)
336 {
337         int error, len = strlen(s);
338
339         if (len > 255) {
340                 len = 255;
341         }
342         if ((error = mb_put_uint8(mbp, len)) != 0)
343                 return error;
344         return mb_put_mem(mbp, s, len);
345 }
346
347 /*
348  * Routines for fetching data from an mbuf chain
349  */
350 #define mb_left(m,p)    (mtod(m, char *) + (m)->m_len - (p))
351
352 int
353 mb_get_uint8(struct mbdata *mbp, u_int8_t *x)
354 {
355         return mb_get_mem(mbp, x, 1);
356 }
357
358 int
359 mb_get_uint16(struct mbdata *mbp, u_int16_t *x)
360 {
361         return mb_get_mem(mbp, (char *)x, 2);
362 }
363
364 int
365 mb_get_uint16le(struct mbdata *mbp, u_int16_t *x)
366 {
367         u_int16_t v;
368         int error = mb_get_uint16(mbp, &v);
369
370         *x = le16toh(v);
371         return error;
372 }
373
374 int
375 mb_get_uint16be(struct mbdata *mbp, u_int16_t *x) {
376         u_int16_t v;
377         int error = mb_get_uint16(mbp, &v);
378
379         *x = be16toh(v);
380         return error;
381 }
382
383 int
384 mb_get_uint32(struct mbdata *mbp, u_int32_t *x)
385 {
386         return mb_get_mem(mbp, (char *)x, 4);
387 }
388
389 int
390 mb_get_uint32be(struct mbdata *mbp, u_int32_t *x)
391 {
392         u_int32_t v;
393         int error;
394
395         error = mb_get_uint32(mbp, &v);
396         *x = be32toh(v);
397         return error;
398 }
399
400 int
401 mb_get_uint32le(struct mbdata *mbp, u_int32_t *x)
402 {
403         u_int32_t v;
404         int error;
405
406         error = mb_get_uint32(mbp, &v);
407         *x = le32toh(v);
408         return error;
409 }
410
411 int
412 mb_get_int64(struct mbdata *mbp, int64_t *x)
413 {
414         return mb_get_mem(mbp, (char *)x, 8);
415 }
416
417 int
418 mb_get_int64be(struct mbdata *mbp, int64_t *x)
419 {
420         int64_t v;
421         int error;
422
423         error = mb_get_int64(mbp, &v);
424         *x = be64toh(v);
425         return error;
426 }
427
428 int
429 mb_get_int64le(struct mbdata *mbp, int64_t *x)
430 {
431         int64_t v;
432         int error;
433
434         error = mb_get_int64(mbp, &v);
435         *x = le64toh(v);
436         return error;
437 }
438
439 int
440 mb_get_mem(struct mbdata *mbp, char * target, size_t size)
441 {
442         struct mbuf *m = mbp->mb_cur;
443         u_int count;
444         
445         while (size > 0) {
446                 if (m == NULL) {
447                         MBERROR("incomplete copy\n");
448                         return EBADRPC;
449                 }
450                 count = mb_left(m, mbp->mb_pos);
451                 if (count == 0) {
452                         mbp->mb_cur = m = m->m_next;
453                         if (m)
454                                 mbp->mb_pos = mtod(m, char *);
455                         continue;
456                 }
457                 if (count > size)
458                         count = size;
459                 size -= count;
460                 if (target) {
461                         if (count == 1) {
462                                 *target++ = *mbp->mb_pos;
463                         } else {
464                                 bcopy(mbp->mb_pos, target, count);
465                                 target += count;
466                         }
467                 }
468                 mbp->mb_pos += count;
469         }
470         return 0;
471 }