Unbreak buildworld.
[dragonfly.git] / contrib / smbfs / lib / smb / mbuf.c
CommitLineData
984263bc
MD
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/types.h>
0ce716ae 36#include <sys/endian.h>
984263bc
MD
37#include <ctype.h>
38#include <errno.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42
43#include <netsmb/smb_lib.h>
44
45#define MBERROR(format, args...) printf("%s(%d): "format, __FUNCTION__ , \
46 __LINE__ ,## args)
47
48static int
49m_get(size_t len, struct mbuf **mpp)
50{
51 struct mbuf *m;
52
53 len = M_ALIGN(len);
54 if (len < M_MINSIZE)
55 len = M_MINSIZE;
56 m = malloc(M_BASESIZE + len);
57 if (m == NULL)
58 return ENOMEM;
59 bzero(m, M_BASESIZE + len);
60 m->m_maxlen = len;
61 m->m_data = M_TOP(m);
62 *mpp = m;
63 return 0;
64}
65
66static void
67m_free(struct mbuf *m)
68{
69 free(m);
70}
71
72static void
73m_freem(struct mbuf *m0)
74{
75 struct mbuf *m;
76
77 while (m0) {
78 m = m0->m_next;
79 m_free(m0);
80 m0 = m;
81 }
82}
83
84static size_t
85m_totlen(struct mbuf *m0)
86{
87 struct mbuf *m = m0;
88 int len = 0;
89
90 while (m) {
91 len += m->m_len;
92 m = m->m_next;
93 }
94 return len;
95}
96
97int
98m_lineup(struct mbuf *m0, struct mbuf **mpp)
99{
100 struct mbuf *nm, *m;
101 char *dp;
102 size_t len;
103 int error;
104
105 if (m0->m_next == NULL) {
106 *mpp = m0;
107 return 0;
108 }
109 if ((error = m_get(m_totlen(m0), &nm)) != 0)
110 return error;
111 dp = mtod(nm, char *);
112 while (m0) {
113 len = m0->m_len;
114 bcopy(m0->m_data, dp, len);
115 dp += len;
116 m = m0->m_next;
117 m_free(m0);
118 m0 = m;
119 }
120 *mpp = nm;
121 return 0;
122}
123
124int
125mb_init(struct mbdata *mbp, size_t size)
126{
127 struct mbuf *m;
128 int error;
129
130 if ((error = m_get(size, &m)) != 0)
131 return error;
132 return mb_initm(mbp, m);
133}
134
135int
136mb_initm(struct mbdata *mbp, struct mbuf *m)
137{
138 bzero(mbp, sizeof(*mbp));
139 mbp->mb_top = mbp->mb_cur = m;
140 mbp->mb_pos = mtod(m, char *);
141 return 0;
142}
143
144int
145mb_done(struct mbdata *mbp)
146{
147 if (mbp->mb_top) {
148 m_freem(mbp->mb_top);
149 mbp->mb_top = NULL;
150 }
151 return 0;
152}
153
154/*
155int
156mb_fixhdr(struct mbdata *mbp)
157{
158 struct mbuf *m = mbp->mb_top;
159 int len = 0;
160
161 while (m) {
162 len += m->m_len;
163 m = m->m_next;
164 }
165 mbp->mb_top->m_pkthdr.len = len;
166 return len;
167}
168*/
169int
170m_getm(struct mbuf *top, size_t len, struct mbuf **mpp)
171{
172 struct mbuf *m, *mp;
173 int error;
174
175 for (mp = top; ; mp = mp->m_next) {
176 len -= M_TRAILINGSPACE(mp);
177 if (mp->m_next == NULL)
178 break;
179
180 }
181 if (len > 0) {
182 if ((error = m_get(len, &m)) != 0)
183 return error;
184 mp->m_next = m;
185 }
186 *mpp = top;
187 return 0;
188}
189
190/*
191 * Routines to put data in a buffer
192 */
193#define MB_PUT(t) int error; t *p; \
194 if ((error = mb_fit(mbp, sizeof(t), (char**)&p)) != 0) \
195 return error
196
197/*
198 * Check if object of size 'size' fit to the current position and
199 * allocate new mbuf if not. Advance pointers and increase length of mbuf(s).
200 * Return pointer to the object placeholder or NULL if any error occured.
201 */
202int
203mb_fit(struct mbdata *mbp, size_t size, char **pp)
204{
205 struct mbuf *m, *mn;
206 int error;
207
208 m = mbp->mb_cur;
209 if (M_TRAILINGSPACE(m) < (int)size) {
210 if ((error = m_get(size, &mn)) != 0)
211 return error;
212 mbp->mb_pos = mtod(mn, char *);
213 mbp->mb_cur = m->m_next = mn;
214 m = mn;
215 }
216 m->m_len += size;
217 *pp = mbp->mb_pos;
218 mbp->mb_pos += size;
219 mbp->mb_count += size;
220 return 0;
221}
222
223int
224mb_put_uint8(struct mbdata *mbp, u_int8_t x)
225{
226 MB_PUT(u_int8_t);
227 *p = x;
228 return 0;
229}
230
231int
232mb_put_uint16be(struct mbdata *mbp, u_int16_t x)
233{
234 MB_PUT(u_int16_t);
235 setwbe(p, 0, x);
236 return 0;
237}
238
239int
240mb_put_uint16le(struct mbdata *mbp, u_int16_t x)
241{
242 MB_PUT(u_int16_t);
243 setwle(p, 0, x);
244 return 0;
245}
246
247int
248mb_put_uint32be(struct mbdata *mbp, u_int32_t x)
249{
250 MB_PUT(u_int32_t);
251 setdbe(p, 0, x);
252 return 0;
253}
254
255int
256mb_put_uint32le(struct mbdata *mbp, u_int32_t x)
257{
258 MB_PUT(u_int32_t);
259 setdle(p, 0, x);
260 return 0;
261}
262
263int
264mb_put_int64be(struct mbdata *mbp, int64_t x)
265{
266 MB_PUT(int64_t);
0ce716ae 267 *p = htobe64(x);
984263bc
MD
268 return 0;
269}
270
271int
272mb_put_int64le(struct mbdata *mbp, int64_t x)
273{
274 MB_PUT(int64_t);
0ce716ae 275 *p = htole64(x);
984263bc
MD
276 return 0;
277}
278
279int
280mb_put_mem(struct mbdata *mbp, const char *source, size_t size)
281{
282 struct mbuf *m;
283 char * dst;
284 size_t cplen;
285 int error;
286
287 if (size == 0)
288 return 0;
289 m = mbp->mb_cur;
290 if ((error = m_getm(m, size, &m)) != 0)
291 return error;
292 while (size > 0) {
293 cplen = M_TRAILINGSPACE(m);
294 if (cplen == 0) {
295 m = m->m_next;
296 continue;
297 }
298 if (cplen > size)
299 cplen = size;
300 dst = mtod(m, char *) + m->m_len;
301 if (source) {
302 bcopy(source, dst, cplen);
303 source += cplen;
304 } else
305 bzero(dst, cplen);
306 size -= cplen;
307 m->m_len += cplen;
308 mbp->mb_count += cplen;
309 }
310 mbp->mb_pos = mtod(m, char *) + m->m_len;
311 mbp->mb_cur = m;
312 return 0;
313}
314
315int
316mb_put_mbuf(struct mbdata *mbp, struct mbuf *m)
317{
318 mbp->mb_cur->m_next = m;
319 while (m) {
320 mbp->mb_count += m->m_len;
321 if (m->m_next == NULL)
322 break;
323 m = m->m_next;
324 }
325 mbp->mb_pos = mtod(m, char *) + m->m_len;
326 mbp->mb_cur = m;
327 return 0;
328}
329
330int
331mb_put_pstring(struct mbdata *mbp, const char *s)
332{
333 int error, len = strlen(s);
334
335 if (len > 255) {
336 len = 255;
337 }
338 if ((error = mb_put_uint8(mbp, len)) != 0)
339 return error;
340 return mb_put_mem(mbp, s, len);
341}
342
343/*
344 * Routines for fetching data from an mbuf chain
345 */
346#define mb_left(m,p) (mtod(m, char *) + (m)->m_len - (p))
347
348int
349mb_get_uint8(struct mbdata *mbp, u_int8_t *x)
350{
351 return mb_get_mem(mbp, x, 1);
352}
353
354int
355mb_get_uint16(struct mbdata *mbp, u_int16_t *x)
356{
357 return mb_get_mem(mbp, (char *)x, 2);
358}
359
360int
361mb_get_uint16le(struct mbdata *mbp, u_int16_t *x)
362{
363 u_int16_t v;
364 int error = mb_get_uint16(mbp, &v);
365
0ce716ae
SW
366 if (x != NULL)
367 *x = le16toh(v);
984263bc
MD
368 return error;
369}
370
371int
372mb_get_uint16be(struct mbdata *mbp, u_int16_t *x) {
373 u_int16_t v;
374 int error = mb_get_uint16(mbp, &v);
375
0ce716ae
SW
376 if (x != NULL)
377 *x = be16toh(v);
984263bc
MD
378 return error;
379}
380
381int
382mb_get_uint32(struct mbdata *mbp, u_int32_t *x)
383{
384 return mb_get_mem(mbp, (char *)x, 4);
385}
386
387int
388mb_get_uint32be(struct mbdata *mbp, u_int32_t *x)
389{
390 u_int32_t v;
391 int error;
392
393 error = mb_get_uint32(mbp, &v);
0ce716ae
SW
394 if (x != NULL)
395 *x = be32toh(v);
984263bc
MD
396 return error;
397}
398
399int
400mb_get_uint32le(struct mbdata *mbp, u_int32_t *x)
401{
402 u_int32_t v;
403 int error;
404
405 error = mb_get_uint32(mbp, &v);
0ce716ae
SW
406 if (x != NULL)
407 *x = le32toh(v);
984263bc
MD
408 return error;
409}
410
411int
412mb_get_int64(struct mbdata *mbp, int64_t *x)
413{
414 return mb_get_mem(mbp, (char *)x, 8);
415}
416
417int
418mb_get_int64be(struct mbdata *mbp, int64_t *x)
419{
420 int64_t v;
421 int error;
422
423 error = mb_get_int64(mbp, &v);
0ce716ae
SW
424 if (x != NULL)
425 *x = be64toh(v);
984263bc
MD
426 return error;
427}
428
429int
430mb_get_int64le(struct mbdata *mbp, int64_t *x)
431{
432 int64_t v;
433 int error;
434
435 error = mb_get_int64(mbp, &v);
0ce716ae
SW
436 if (x != NULL)
437 *x = le64toh(v);
984263bc
MD
438 return error;
439}
440
441int
442mb_get_mem(struct mbdata *mbp, char * target, size_t size)
443{
444 struct mbuf *m = mbp->mb_cur;
445 u_int count;
446
447 while (size > 0) {
448 if (m == NULL) {
449 MBERROR("incomplete copy\n");
450 return EBADRPC;
451 }
452 count = mb_left(m, mbp->mb_pos);
453 if (count == 0) {
454 mbp->mb_cur = m = m->m_next;
455 if (m)
456 mbp->mb_pos = mtod(m, char *);
457 continue;
458 }
459 if (count > size)
460 count = size;
461 size -= count;
462 if (target) {
463 if (count == 1) {
464 *target++ = *mbp->mb_pos;
465 } else {
466 bcopy(mbp->mb_pos, target, count);
467 target += count;
468 }
469 }
470 mbp->mb_pos += count;
471 }
472 return 0;
473}