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

5
Last change on this file since 1e0cc86 was a2aa920, checked in by Sebastian Huber <sebastian.huber@…>, on 04/22/16 at 06:00:40

nfsclient: Fix warnings

  • Property mode set to 100644
File size: 11.3 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 <string.h>
65#include <rpc/types.h>
66#include <rpc/xdr.h>
67#include <netinet/in.h>
68
69#include <stdlib.h>
70
71#define TODO
72
73/* TODO remove: a hack because malloc is redefined */
74#ifdef TODO
75static inline void *
76my_malloc(size_t i)
77{
78        return malloc(i);
79}
80
81static inline void
82my_free(void *p)
83{
84        return free(p);
85}
86#endif
87
88#define DEBUG_ASSERT    (1<<0)
89#define DEBUG_VERB              (1<<1)
90
91#define DEBUG                   DEBUG_ASSERT
92
93#define _KERNEL
94#include <sys/mbuf.h>
95
96#include <assert.h>
97
98#if DEBUG & DEBUG_VERB || defined(TODO)
99#include <stdio.h>
100#endif
101
102#include "nfsclient-private.h"
103
104static bool_t   xdrmbuf_getlong_aligned(XDR *xdrs, long *lp);
105static bool_t   xdrmbuf_putlong_aligned(XDR *xdrs, const long *lp);
106static bool_t   xdrmbuf_getlong_unaligned(XDR *xdrs, long *lp);
107static bool_t   xdrmbuf_putlong_unaligned(XDR *xdrs, const long *lp);
108static bool_t   xdrmbuf_getbytes(XDR *xdrs, caddr_t addr, u_int len);
109static bool_t   xdrmbuf_putbytes(XDR *xdrs, const char *addr, u_int len);
110static u_int    xdrmbuf_getpos(XDR *xdrs); /* XXX w/64-bit pointers, u_int not enough! */
111static bool_t   xdrmbuf_setpos(XDR *xdrs, u_int pos);
112static int32_t *xdrmbuf_inline_aligned(XDR *xdrs, u_int len);
113static int32_t *xdrmbuf_inline_unaligned(XDR *xdrs, u_int len);
114static void     xdrmbuf_destroy(XDR *);
115
116static struct   xdr_ops xdrmbuf_ops_aligned = {
117        xdrmbuf_getlong_aligned,
118        xdrmbuf_putlong_aligned,
119        xdrmbuf_getbytes,
120        xdrmbuf_putbytes,
121        xdrmbuf_getpos,
122        xdrmbuf_setpos,
123        xdrmbuf_inline_aligned,
124        xdrmbuf_destroy
125};
126
127static struct   xdr_ops xdrmbuf_ops_unaligned = {
128        xdrmbuf_getlong_unaligned,
129        xdrmbuf_putlong_unaligned,
130        xdrmbuf_getbytes,
131        xdrmbuf_putbytes,
132        xdrmbuf_getpos,
133        xdrmbuf_setpos,
134        xdrmbuf_inline_unaligned,
135        xdrmbuf_destroy
136};
137
138typedef struct MBPrivateRec_ {
139        struct mbuf             *mchain;
140        struct mbuf             *mcurrent;
141        u_int                   pos;            /* number of bytes contained in all MUBFS ahead
142                                                                 * of mcurrent
143                                                                 */
144} MBPrivateRec, *MBPrivate;
145
146/* NOTE: the stream position helper 'pos'
147 *       must be managed by the caller!
148 */
149static inline void
150xdrmbuf_setup(XDR *xdrs, struct mbuf *m)
151{
152MBPrivate       mbp = (MBPrivate)xdrs->x_base;
153
154                mbp->mcurrent    = m;
155                xdrs->x_private  = mtod(m,caddr_t);
156                xdrs->x_handy    = m->m_len;
157                xdrs->x_ops      = ((uintptr_t)xdrs->x_private & (sizeof(int32_t) - 1))
158                                                                ? &xdrmbuf_ops_unaligned : &xdrmbuf_ops_aligned;
159}
160
161static struct mbuf *
162xdrmbuf_next(XDR *xdrs)
163{
164struct mbuf             *rval;
165MBPrivate               mbp = (MBPrivate)xdrs->x_base;
166
167        if (mbp->mcurrent) {
168                mbp->pos += mbp->mcurrent->m_len;
169                rval      = mbp->mcurrent->m_next;
170        } else {
171                rval      = 0;
172        }
173
174        if (rval) {
175                xdrmbuf_setup(xdrs, rval);
176        }
177#if DEBUG & DEBUG_VERB
178        else {
179                fprintf(stderr,"xdrmbuf: end of chain\n");
180        }
181#endif
182
183        return rval;
184}
185
186/*
187 * The procedure xdrmbuf_create initializes a stream descriptor for a
188 * memory buffer.
189 */
190void
191xdrmbuf_create(XDR *xdrs, struct mbuf *mbuf, enum xdr_op op)
192{
193MBPrivate mbp;
194
195        xdrs->x_op = op;
196        mbp = (MBPrivate)my_malloc(sizeof(*mbp));
197        assert( mbp );
198        xdrs->x_base  = (caddr_t) mbp;
199
200        mbp->mchain   = mbuf;
201        mbp->pos      = 0;
202
203#if DEBUG & DEBUG_VERB
204        {
205        struct mbuf *mbf;
206        fprintf(stderr,"Dumping chain:\n");
207        for (mbf = mbuf; mbf; mbf=mbf->m_next) {
208                int ii;
209                fprintf(stderr,"MBUF------------");
210                for (ii=0; ii<mbf->m_len; ii++) {
211                        fprintf(stderr,"%02x ",mtod(mbf,char*)[ii]);
212                        if (ii%16==0)
213                                fputc('\n',stderr);
214                }
215                fputc('\n',stderr);
216        }
217        }
218#endif
219
220        xdrmbuf_setup(xdrs, mbuf);
221}
222
223static void
224xdrmbuf_destroy(XDR *xdrs)
225{
226MBPrivate       mbp = (MBPrivate)xdrs->x_base;
227#if 0 /* leave destroying the chain to the user */
228struct mbuf *m = mbp->mchain;
229
230        rtems_bsdnet_semaphore_obtain();
231                m_freem(m);
232        rtems_bsdnet_semaphore_release();
233#endif
234
235        my_free(mbp);
236}
237
238static bool_t
239xdrmbuf_getlong_aligned(register XDR *xdrs, register long *lp)
240{
241        while ( (signed int)(xdrs->x_handy -= sizeof(int32_t)) < 0) {
242                if ((xdrs->x_handy += sizeof(int32_t)) == 0) {
243                        /* handy was 0 on entry; request a new buffer.
244                         * Coded this way, so the most frequently executed
245                         * path needs only one comparison...
246                         */
247                        if (!xdrmbuf_next(xdrs))
248                                return FALSE;
249                } else {
250                        /* uh-oh an aligned long spread over two MBUFS ??
251                         * let the unaligned handler deal with this rare
252                         * situation.
253                         */
254                        return xdrmbuf_getlong_unaligned(xdrs,lp);
255                }
256        }
257        *lp = ntohl(*(int32_t *)(xdrs->x_private));
258        xdrs->x_private += sizeof(int32_t);
259#if DEBUG & DEBUG_VERB
260        fprintf(stderr,"Got aligned long %x\n",*lp);
261#endif
262        return (TRUE);
263}
264
265static bool_t
266xdrmbuf_putlong_aligned(
267        XDR *xdrs,
268        const long *lp)
269{
270fprintf(stderr,"TODO: xdrmbuf_putlong_aligned() is unimplemented\n");
271        return FALSE;
272#if 0
273        if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
274                return (FALSE);
275        *(int32_t *)xdrs->x_private = htonl(*lp);
276        xdrs->x_private += sizeof(int32_t);
277        return (TRUE);
278#endif
279}
280
281static bool_t
282xdrmbuf_getlong_unaligned(
283        XDR *xdrs,
284        long *lp)
285{
286union {
287        int32_t l;
288        char    c[sizeof(int32_t)];
289}       u;
290
291register int  i,j;
292register char *cp,*sp;
293
294        i = xdrs->x_handy - sizeof(int32_t);
295
296        /* handle the most common case first */
297        if ( i >= 0 ) {
298
299                xdrs->x_handy   = i;
300                sp                          = (char*)xdrs->x_private;
301                xdrs->x_private = sp + sizeof(int32_t);
302
303#ifdef CANDO_UNALIGNED
304                {
305                        *lp              = ntohl(*(int32_t *)sp);
306#        if DEBUG & DEBUG_VERB
307                        fprintf(stderr,"Got unaligned long %x (%i remaining)\n",*lp, xdrs->x_handy);
308#        endif
309                        return TRUE;
310                }
311#else   /* machine can't do unaligned access */
312                {
313                        u.c[0]          = *sp;
314                        u.c[1]          = *++sp;
315                        u.c[2]          = *++sp;
316                        u.c[3]          = *++sp;
317
318                        goto done;
319                }
320#endif /* CANDO_UNALIGNED */
321        }
322
323        /* here the messy 'crossing buffers' business starts */
324
325
326        j  = sizeof(int32_t);
327
328        cp = u.c-1;
329
330        /* NOTE: on entry to this section,  handy < j holds */
331        do {
332                sp = ((char*)xdrs->x_private)-1;
333
334                if ( (i=xdrs->x_handy) >= j ) {
335                        /* more data in the buffer than we need:
336                         * copy everything we need and goto 'done'
337                         */
338                        xdrs->x_handy    = i-j;
339                        do {
340                                *++cp = *++sp;
341                        } while (--j > 0);
342                        xdrs->x_private  = (caddr_t)++sp;
343
344                        goto done;
345
346                } else {
347                        /* not enough data - copy as much as possible
348                         * then get retrieve the next MBUF and start
349                         * over
350                         */
351                        j-=i;
352                        while (i--)
353                                *++cp = *++sp;
354                        if (!xdrmbuf_next(xdrs))
355                                return FALSE;
356#if DEBUG & DEBUG_VERB
357                        fprintf(stderr,"getlong_unaligned: crossed mbuf boundary\n");
358#endif
359                }
360        } while (j > 0);
361
362done:
363
364        *lp = ntohl(u.l);
365
366#if DEBUG & DEBUG_VERB
367        fprintf(stderr,"Got unaligned long %x (%i remaining)\n",*lp, xdrs->x_handy);
368#endif
369        return (TRUE);
370}
371
372static bool_t
373xdrmbuf_putlong_unaligned(
374        XDR *xdrs,
375        const long *lp )
376{
377
378        fprintf(stderr,"TODO: xdrmbuf_putlong_unaligned() is unimplemented\n");
379        return FALSE;
380#if 0
381        {
382        int32_t l;
383
384        if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
385                return (FALSE);
386        l = htonl(*lp);
387        memcpy(xdrs->x_private, &l, sizeof(int32_t));
388        xdrs->x_private += sizeof(int32_t);
389        return (TRUE);
390        }
391#endif
392}
393
394static bool_t
395xdrmbuf_getbytes(
396        XDR *xdrs,
397        caddr_t addr,
398        u_int len)
399{
400#if DEBUG & DEBUG_VERB
401int     olen=len,bufs=0;
402#endif
403
404#if DEBUG & DEBUG_VERB
405        fprintf(stderr,"wanting %i bytes (have %i)\n",olen,xdrs->x_handy);
406#endif
407
408        while (len>0) {
409                if (xdrs->x_handy >= len) {
410                        memcpy(addr, xdrs->x_private, len);
411                        xdrs->x_private += len;
412                        xdrs->x_handy   -= len;
413#if 0 /* save a couple of instructions */
414                        len = 0;
415#else
416                        goto done;
417#endif
418                } else {
419                        if (xdrs->x_handy > 0) {
420                                memcpy(addr, xdrs->x_private, xdrs->x_handy);
421                                len  -= xdrs->x_handy;
422                                addr += xdrs->x_handy;
423                        }
424                        if (!xdrmbuf_next(xdrs))
425                                return FALSE;
426#if DEBUG & DEBUG_VERB
427                        bufs++;
428#endif
429                }
430        }
431done:
432#if DEBUG & DEBUG_VERB
433        fprintf(stderr,"Got %i bytes (out of %i mbufs)\n",olen,bufs);
434#endif
435        return (TRUE);
436}
437
438static bool_t
439xdrmbuf_putbytes(
440        XDR *xdrs,
441        const char *addr,
442        u_int len )
443{
444
445        fprintf(stderr,"TODO: xdrmbuf_putbytes() is unimplemented\n");
446        return FALSE;
447#if 0
448        if ((xdrs->x_handy -= len) < 0)
449                return (FALSE);
450        memcpy(xdrs->x_private, addr, len);
451        xdrs->x_private += len;
452        return (TRUE);
453#endif
454}
455
456static u_int
457xdrmbuf_getpos(
458        XDR *xdrs)
459{
460#if 1
461MBPrivate       mbp  = (MBPrivate)xdrs->x_base;
462struct mbuf *m   = mbp->mcurrent;
463u_int       rval = mbp->pos;
464
465        if (m) {
466                rval += xdrs->x_private - mtod(m, void*);
467        }
468#else
469struct mbuf *m;
470u_int           rval = 0;
471MBPrivate       mbp  = (MBPrivate)xdrs->x_base;
472
473        for ( m = mbp->mchain; m && m != mbp->mcurrent; m = m->m_next )
474                rval += m->m_len;
475        if (m) {
476                rval += (u_long)xdrs->x_private - mtod(m, u_long);
477        }
478
479#endif
480        return rval;
481}
482
483static bool_t
484xdrmbuf_setpos(
485        XDR *xdrs,
486        u_int pos)
487{
488struct          mbuf *m;
489MBPrivate       mbp   = (MBPrivate)xdrs->x_base;
490
491        if (pos >= mbp->pos) {
492                pos      -= mbp->pos;
493                m         = mbp->mcurrent;
494        } else {
495                m         = mbp->mchain;
496                mbp->pos  = 0;
497        }
498
499        while ( m && pos >= m->m_len ) {
500                pos      -= m->m_len;
501                mbp->pos += m->m_len;
502                m         = m->m_next;
503        }
504
505        if (m) {
506                xdrmbuf_setup(xdrs, m);
507                xdrs->x_private += pos;
508                return TRUE;
509        }
510
511        return 0 == pos ? TRUE : FALSE;
512}
513
514static int32_t *
515xdrmbuf_inline_aligned(
516        XDR *xdrs,
517        u_int len)
518{
519int32_t *buf = 0;
520
521        if (xdrs->x_handy == 0 && !xdrmbuf_next(xdrs))
522                return 0;
523
524        if (xdrs->x_handy >= len) {
525                xdrs->x_handy -= len;
526                buf = (int32_t *) xdrs->x_private;
527                xdrs->x_private += len;
528#if DEBUG & DEBUG_VERB
529                fprintf(stderr,"Got %i aligned inline bytes at %x\n", len, buf);
530#endif
531        }
532#if DEBUG & DEBUG_VERB
533        else {
534                fprintf(stderr,"Skipped %i aligned inline bytes\n",len);
535        }
536#endif
537        return (buf);
538}
539
540static int32_t *
541xdrmbuf_inline_unaligned(
542        XDR *xdrs,
543        u_int len )
544{
545        return (0);
546}
Note: See TracBrowser for help on using the repository browser.