source: rtems/cpukit/libfs/src/nfsclient/src/xdr_mbuf.c @ d7613f7a

5
Last change on this file since d7613f7a was 643b820, checked in by Sebastian Huber <sebastian.huber@…>, on 06/06/17 at 09:11:49

Include missing <sys/param.h>

Some kernel-space header expect that <sys/param.h> is present.

Update #2833.

  • Property mode set to 100644
File size: 11.4 KB
Line 
1/**
2 * @file
3 *
4 * @brief XDR Implementation Using mbuf Buffers
5 * @ingroup libfs
6 *
7 * xdr_mbuf is derived from xdr_mem
8 */
9
10/*
11 * Author (mbuf specifica): Till Straumann <strauman@slac.stanford.edu>, 10/2002
12 *
13 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
14 * unrestricted use provided that this legend is included on all tape
15 * media and as a part of the software program in whole or part.  Users
16 * may copy or modify Sun RPC without charge, but are not authorized
17 * to license or distribute it to anyone else except as part of a product or
18 * program developed by the user.
19 *
20 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
21 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
23 *
24 * Sun RPC is provided with no support and without any obligation on the
25 * part of Sun Microsystems, Inc. to assist in its use, correction,
26 * modification or enhancement.
27 *
28 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
29 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
30 * OR ANY PART THEREOF.
31 *
32 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
33 * or profits or other special, indirect and consequential damages, even if
34 * Sun has been advised of the possibility of such damages.
35 *
36 * Sun Microsystems, Inc.
37 * 2550 Garcia Avenue
38 * Mountain View, California  94043
39 */
40
41#if defined(LIBC_SCCS) && !defined(lint)
42/*static char *sccsid = "from: @(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
43/*static char *sccsid = "from: @(#)xdr_mem.c    2.1 88/07/29 4.0 RPCSRC";*/
44static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_mem.c,v 1.8 1999/08/28 00:02:56 peter Exp $";
45#endif
46
47/*
48 * xdr_mbuf,  XDR implementation using mbuf buffers
49 *
50 * derived from:
51 *
52 * xdr_mem.h, XDR implementation using memory buffers.
53 *
54 * Copyright (C) 1984, Sun Microsystems, Inc.
55 *
56 * The MBUF stream is useful for BSDNET kernel (or RTEMS for that matter)
57 * use.
58 */
59
60#if HAVE_CONFIG_H
61#include "config.h"
62#endif
63
64#include <sys/param.h>
65#include <string.h>
66#include <rpc/types.h>
67#include <rpc/xdr.h>
68#include <netinet/in.h>
69
70#include <stdlib.h>
71
72#define TODO
73
74/* TODO remove: a hack because malloc is redefined */
75#ifdef TODO
76static inline void *
77my_malloc(size_t i)
78{
79        return malloc(i);
80}
81
82static inline void
83my_free(void *p)
84{
85        return free(p);
86}
87#endif
88
89#define DEBUG_ASSERT    (1<<0)
90#define DEBUG_VERB              (1<<1)
91
92#define DEBUG                   DEBUG_ASSERT
93
94#define _KERNEL
95#include <sys/mbuf.h>
96
97#include <assert.h>
98
99#if DEBUG & DEBUG_VERB || defined(TODO)
100#include <stdio.h>
101#endif
102
103#include "nfsclient-private.h"
104
105static bool_t   xdrmbuf_getlong_aligned(XDR *xdrs, long *lp);
106static bool_t   xdrmbuf_putlong_aligned(XDR *xdrs, const long *lp);
107static bool_t   xdrmbuf_getlong_unaligned(XDR *xdrs, long *lp);
108static bool_t   xdrmbuf_putlong_unaligned(XDR *xdrs, const long *lp);
109static bool_t   xdrmbuf_getbytes(XDR *xdrs, caddr_t addr, u_int len);
110static bool_t   xdrmbuf_putbytes(XDR *xdrs, const char *addr, u_int len);
111static u_int    xdrmbuf_getpos(XDR *xdrs); /* XXX w/64-bit pointers, u_int not enough! */
112static bool_t   xdrmbuf_setpos(XDR *xdrs, u_int pos);
113static int32_t *xdrmbuf_inline_aligned(XDR *xdrs, u_int len);
114static int32_t *xdrmbuf_inline_unaligned(XDR *xdrs, u_int len);
115static void     xdrmbuf_destroy(XDR *);
116
117static struct   xdr_ops xdrmbuf_ops_aligned = {
118        xdrmbuf_getlong_aligned,
119        xdrmbuf_putlong_aligned,
120        xdrmbuf_getbytes,
121        xdrmbuf_putbytes,
122        xdrmbuf_getpos,
123        xdrmbuf_setpos,
124        xdrmbuf_inline_aligned,
125        xdrmbuf_destroy
126};
127
128static struct   xdr_ops xdrmbuf_ops_unaligned = {
129        xdrmbuf_getlong_unaligned,
130        xdrmbuf_putlong_unaligned,
131        xdrmbuf_getbytes,
132        xdrmbuf_putbytes,
133        xdrmbuf_getpos,
134        xdrmbuf_setpos,
135        xdrmbuf_inline_unaligned,
136        xdrmbuf_destroy
137};
138
139typedef struct MBPrivateRec_ {
140        struct mbuf             *mchain;
141        struct mbuf             *mcurrent;
142        u_int                   pos;            /* number of bytes contained in all MUBFS ahead
143                                                                 * of mcurrent
144                                                                 */
145} MBPrivateRec, *MBPrivate;
146
147/* NOTE: the stream position helper 'pos'
148 *       must be managed by the caller!
149 */
150static inline void
151xdrmbuf_setup(XDR *xdrs, struct mbuf *m)
152{
153MBPrivate       mbp = (MBPrivate)xdrs->x_base;
154
155                mbp->mcurrent    = m;
156                xdrs->x_private  = mtod(m,caddr_t);
157                xdrs->x_handy    = m->m_len;
158                xdrs->x_ops      = ((uintptr_t)xdrs->x_private & (sizeof(int32_t) - 1))
159                                                                ? &xdrmbuf_ops_unaligned : &xdrmbuf_ops_aligned;
160}
161
162static struct mbuf *
163xdrmbuf_next(XDR *xdrs)
164{
165struct mbuf             *rval;
166MBPrivate               mbp = (MBPrivate)xdrs->x_base;
167
168        if (mbp->mcurrent) {
169                mbp->pos += mbp->mcurrent->m_len;
170                rval      = mbp->mcurrent->m_next;
171        } else {
172                rval      = 0;
173        }
174
175        if (rval) {
176                xdrmbuf_setup(xdrs, rval);
177        }
178#if DEBUG & DEBUG_VERB
179        else {
180                fprintf(stderr,"xdrmbuf: end of chain\n");
181        }
182#endif
183
184        return rval;
185}
186
187/*
188 * The procedure xdrmbuf_create initializes a stream descriptor for a
189 * memory buffer.
190 */
191void
192xdrmbuf_create(XDR *xdrs, struct mbuf *mbuf, enum xdr_op op)
193{
194MBPrivate mbp;
195
196        xdrs->x_op = op;
197        mbp = (MBPrivate)my_malloc(sizeof(*mbp));
198        assert( mbp );
199        xdrs->x_base  = (caddr_t) mbp;
200
201        mbp->mchain   = mbuf;
202        mbp->pos      = 0;
203
204#if DEBUG & DEBUG_VERB
205        {
206        struct mbuf *mbf;
207        fprintf(stderr,"Dumping chain:\n");
208        for (mbf = mbuf; mbf; mbf=mbf->m_next) {
209                int ii;
210                fprintf(stderr,"MBUF------------");
211                for (ii=0; ii<mbf->m_len; ii++) {
212                        fprintf(stderr,"%02x ",mtod(mbf,char*)[ii]);
213                        if (ii%16==0)
214                                fputc('\n',stderr);
215                }
216                fputc('\n',stderr);
217        }
218        }
219#endif
220
221        xdrmbuf_setup(xdrs, mbuf);
222}
223
224static void
225xdrmbuf_destroy(XDR *xdrs)
226{
227MBPrivate       mbp = (MBPrivate)xdrs->x_base;
228#if 0 /* leave destroying the chain to the user */
229struct mbuf *m = mbp->mchain;
230
231        rtems_bsdnet_semaphore_obtain();
232                m_freem(m);
233        rtems_bsdnet_semaphore_release();
234#endif
235
236        my_free(mbp);
237}
238
239static bool_t
240xdrmbuf_getlong_aligned(register XDR *xdrs, register long *lp)
241{
242        while ( (signed int)(xdrs->x_handy -= sizeof(int32_t)) < 0) {
243                if ((xdrs->x_handy += sizeof(int32_t)) == 0) {
244                        /* handy was 0 on entry; request a new buffer.
245                         * Coded this way, so the most frequently executed
246                         * path needs only one comparison...
247                         */
248                        if (!xdrmbuf_next(xdrs))
249                                return FALSE;
250                } else {
251                        /* uh-oh an aligned long spread over two MBUFS ??
252                         * let the unaligned handler deal with this rare
253                         * situation.
254                         */
255                        return xdrmbuf_getlong_unaligned(xdrs,lp);
256                }
257        }
258        *lp = ntohl(*(int32_t *)(xdrs->x_private));
259        xdrs->x_private += sizeof(int32_t);
260#if DEBUG & DEBUG_VERB
261        fprintf(stderr,"Got aligned long %x\n",*lp);
262#endif
263        return (TRUE);
264}
265
266static bool_t
267xdrmbuf_putlong_aligned(
268        XDR *xdrs,
269        const long *lp)
270{
271fprintf(stderr,"TODO: xdrmbuf_putlong_aligned() is unimplemented\n");
272        return FALSE;
273#if 0
274        if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
275                return (FALSE);
276        *(int32_t *)xdrs->x_private = htonl(*lp);
277        xdrs->x_private += sizeof(int32_t);
278        return (TRUE);
279#endif
280}
281
282static bool_t
283xdrmbuf_getlong_unaligned(
284        XDR *xdrs,
285        long *lp)
286{
287union {
288        int32_t l;
289        char    c[sizeof(int32_t)];
290}       u;
291
292register int  i,j;
293register char *cp,*sp;
294
295        i = xdrs->x_handy - sizeof(int32_t);
296
297        /* handle the most common case first */
298        if ( i >= 0 ) {
299
300                xdrs->x_handy   = i;
301                sp                          = (char*)xdrs->x_private;
302                xdrs->x_private = sp + sizeof(int32_t);
303
304#ifdef CANDO_UNALIGNED
305                {
306                        *lp              = ntohl(*(int32_t *)sp);
307#        if DEBUG & DEBUG_VERB
308                        fprintf(stderr,"Got unaligned long %x (%i remaining)\n",*lp, xdrs->x_handy);
309#        endif
310                        return TRUE;
311                }
312#else   /* machine can't do unaligned access */
313                {
314                        u.c[0]          = *sp;
315                        u.c[1]          = *++sp;
316                        u.c[2]          = *++sp;
317                        u.c[3]          = *++sp;
318
319                        goto done;
320                }
321#endif /* CANDO_UNALIGNED */
322        }
323
324        /* here the messy 'crossing buffers' business starts */
325
326
327        j  = sizeof(int32_t);
328
329        cp = u.c-1;
330
331        /* NOTE: on entry to this section,  handy < j holds */
332        do {
333                sp = ((char*)xdrs->x_private)-1;
334
335                if ( (i=xdrs->x_handy) >= j ) {
336                        /* more data in the buffer than we need:
337                         * copy everything we need and goto 'done'
338                         */
339                        xdrs->x_handy    = i-j;
340                        do {
341                                *++cp = *++sp;
342                        } while (--j > 0);
343                        xdrs->x_private  = (caddr_t)++sp;
344
345                        goto done;
346
347                } else {
348                        /* not enough data - copy as much as possible
349                         * then get retrieve the next MBUF and start
350                         * over
351                         */
352                        j-=i;
353                        while (i--)
354                                *++cp = *++sp;
355                        if (!xdrmbuf_next(xdrs))
356                                return FALSE;
357#if DEBUG & DEBUG_VERB
358                        fprintf(stderr,"getlong_unaligned: crossed mbuf boundary\n");
359#endif
360                }
361        } while (j > 0);
362
363done:
364
365        *lp = ntohl(u.l);
366
367#if DEBUG & DEBUG_VERB
368        fprintf(stderr,"Got unaligned long %x (%i remaining)\n",*lp, xdrs->x_handy);
369#endif
370        return (TRUE);
371}
372
373static bool_t
374xdrmbuf_putlong_unaligned(
375        XDR *xdrs,
376        const long *lp )
377{
378
379        fprintf(stderr,"TODO: xdrmbuf_putlong_unaligned() is unimplemented\n");
380        return FALSE;
381#if 0
382        {
383        int32_t l;
384
385        if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
386                return (FALSE);
387        l = htonl(*lp);
388        memcpy(xdrs->x_private, &l, sizeof(int32_t));
389        xdrs->x_private += sizeof(int32_t);
390        return (TRUE);
391        }
392#endif
393}
394
395static bool_t
396xdrmbuf_getbytes(
397        XDR *xdrs,
398        caddr_t addr,
399        u_int len)
400{
401#if DEBUG & DEBUG_VERB
402int     olen=len,bufs=0;
403#endif
404
405#if DEBUG & DEBUG_VERB
406        fprintf(stderr,"wanting %i bytes (have %i)\n",olen,xdrs->x_handy);
407#endif
408
409        while (len>0) {
410                if (xdrs->x_handy >= len) {
411                        memcpy(addr, xdrs->x_private, len);
412                        xdrs->x_private += len;
413                        xdrs->x_handy   -= len;
414#if 0 /* save a couple of instructions */
415                        len = 0;
416#else
417                        goto done;
418#endif
419                } else {
420                        if (xdrs->x_handy > 0) {
421                                memcpy(addr, xdrs->x_private, xdrs->x_handy);
422                                len  -= xdrs->x_handy;
423                                addr += xdrs->x_handy;
424                        }
425                        if (!xdrmbuf_next(xdrs))
426                                return FALSE;
427#if DEBUG & DEBUG_VERB
428                        bufs++;
429#endif
430                }
431        }
432done:
433#if DEBUG & DEBUG_VERB
434        fprintf(stderr,"Got %i bytes (out of %i mbufs)\n",olen,bufs);
435#endif
436        return (TRUE);
437}
438
439static bool_t
440xdrmbuf_putbytes(
441        XDR *xdrs,
442        const char *addr,
443        u_int len )
444{
445
446        fprintf(stderr,"TODO: xdrmbuf_putbytes() is unimplemented\n");
447        return FALSE;
448#if 0
449        if ((xdrs->x_handy -= len) < 0)
450                return (FALSE);
451        memcpy(xdrs->x_private, addr, len);
452        xdrs->x_private += len;
453        return (TRUE);
454#endif
455}
456
457static u_int
458xdrmbuf_getpos(
459        XDR *xdrs)
460{
461#if 1
462MBPrivate       mbp  = (MBPrivate)xdrs->x_base;
463struct mbuf *m   = mbp->mcurrent;
464u_int       rval = mbp->pos;
465
466        if (m) {
467                rval += xdrs->x_private - mtod(m, void*);
468        }
469#else
470struct mbuf *m;
471u_int           rval = 0;
472MBPrivate       mbp  = (MBPrivate)xdrs->x_base;
473
474        for ( m = mbp->mchain; m && m != mbp->mcurrent; m = m->m_next )
475                rval += m->m_len;
476        if (m) {
477                rval += (u_long)xdrs->x_private - mtod(m, u_long);
478        }
479
480#endif
481        return rval;
482}
483
484static bool_t
485xdrmbuf_setpos(
486        XDR *xdrs,
487        u_int pos)
488{
489struct          mbuf *m;
490MBPrivate       mbp   = (MBPrivate)xdrs->x_base;
491
492        if (pos >= mbp->pos) {
493                pos      -= mbp->pos;
494                m         = mbp->mcurrent;
495        } else {
496                m         = mbp->mchain;
497                mbp->pos  = 0;
498        }
499
500        while ( m && pos >= m->m_len ) {
501                pos      -= m->m_len;
502                mbp->pos += m->m_len;
503                m         = m->m_next;
504        }
505
506        if (m) {
507                xdrmbuf_setup(xdrs, m);
508                xdrs->x_private += pos;
509                return TRUE;
510        }
511
512        return 0 == pos ? TRUE : FALSE;
513}
514
515static int32_t *
516xdrmbuf_inline_aligned(
517        XDR *xdrs,
518        u_int len)
519{
520int32_t *buf = 0;
521
522        if (xdrs->x_handy == 0 && !xdrmbuf_next(xdrs))
523                return 0;
524
525        if (xdrs->x_handy >= len) {
526                xdrs->x_handy -= len;
527                buf = (int32_t *) xdrs->x_private;
528                xdrs->x_private += len;
529#if DEBUG & DEBUG_VERB
530                fprintf(stderr,"Got %i aligned inline bytes at %x\n", len, buf);
531#endif
532        }
533#if DEBUG & DEBUG_VERB
534        else {
535                fprintf(stderr,"Skipped %i aligned inline bytes\n",len);
536        }
537#endif
538        return (buf);
539}
540
541static int32_t *
542xdrmbuf_inline_unaligned(
543        XDR *xdrs,
544        u_int len )
545{
546        return (0);
547}
Note: See TracBrowser for help on using the repository browser.