c4142f8aea41201aebec2cd17ac1c57d312305fe
[dragonfly.git] / sys / netproto / atm / spans / spans_kxdr.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
8  * This Host ATM Research Platform ("HARP") file (the "Software") is
9  * made available by Network Computing Services, Inc. ("NetworkCS")
10  * "AS IS".  NetworkCS does not provide maintenance, improvements or
11  * support of any kind.
12  *
13  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17  * In no event shall NetworkCS be responsible for any damages, including
18  * but not limited to consequential damages, arising from or relating to
19  * any use of the Software or related support.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
26  *      @(#) $FreeBSD: src/sys/netatm/spans/spans_kxdr.c,v 1.3 1999/08/28 00:48:50 peter Exp $
27  *      @(#) $DragonFly: src/sys/netproto/atm/spans/spans_kxdr.c,v 1.4 2003/08/07 21:54:34 dillon Exp $
28  */
29
30 /*
31  * SPANS Signalling Manager
32  * ---------------------------
33  *
34  * Kernel XDR (External Data Representation) routines
35  *
36  */
37
38 #include <netproto/atm/kern_include.h>
39
40 /*
41  * This file contains code that has been copied and/or modified from
42  * the following FreeBSD files:
43  *
44  *      /usr/src/lib/libc/xdr/xdr.c
45  *      /usr/src/lib/libc/xdr/xdr_mem.c
46  *
47  * which are covered by the copyright notice below.
48  */
49
50 /*
51  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
52  * unrestricted use provided that this legend is included on all tape
53  * media and as a part of the software program in whole or part.  Users
54  * may copy or modify Sun RPC without charge, but are not authorized
55  * to license or distribute it to anyone else except as part of a product or
56  * program developed by the user.
57  *
58  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
59  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
60  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
61  *
62  * Sun RPC is provided with no support and without any obligation on the
63  * part of Sun Microsystems, Inc. to assist in its use, correction,
64  * modification or enhancement.
65  *
66  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
67  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
68  * OR ANY PART THEREOF.
69  *
70  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
71  * or profits or other special, indirect and consequential damages, even if
72  * Sun has been advised of the possibility of such damages.
73  *
74  * Sun Microsystems, Inc.
75  * 2550 Garcia Avenue
76  * Mountain View, California  94043
77  */
78
79 #if !defined(sun)
80
81 #if defined(LIBC_SCCS) && !defined(lint)
82 /*static char *sccsid = "from: @(#)xdr.c 1.35 87/08/12";*/
83 /*static char *sccsid = "from: @(#)xdr.c        2.1 88/07/29 4.0 RPCSRC";*/
84 /*static char *rcsid = "Id: xdr.c,v 1.2.4.2 1996/06/05 02:52:02 jkh Exp";*/
85 #endif
86
87 /*
88  * xdr.c, Generic XDR routines implementation.
89  *
90  * Copyright (C) 1986, Sun Microsystems, Inc.
91  *
92  * These are the "generic" xdr routines used to serialize and de-serialize
93  * most common data items.  See xdr.h for more info on the interface to
94  * xdr.
95  */
96
97 #include <rpc/types.h>
98 #include <rpc/xdr.h>
99
100 /*
101  * constants specific to the xdr "protocol"
102  */
103 #define XDR_FALSE       ((long) 0)
104 #define XDR_TRUE        ((long) 1)
105 #define LASTUNSIGNED    ((u_int) 0-1)
106
107 /*
108  * for unit alignment
109  */
110 static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
111
112 /*
113  * XDR integers
114  */
115 bool_t
116 xdr_int(xdrs, ip)
117         XDR *xdrs;
118         int *ip;
119 {
120
121 #ifdef lint
122         (void) (xdr_short(xdrs, (short *)ip));
123         return (xdr_long(xdrs, (long *)ip));
124 #else
125         if (sizeof (int) == sizeof (long)) {
126                 return (xdr_long(xdrs, (long *)ip));
127         } else {
128                 return (xdr_short(xdrs, (short *)ip));
129         }
130 #endif
131 }
132
133 /*
134  * XDR unsigned integers
135  */
136 bool_t
137 xdr_u_int(xdrs, up)
138         XDR *xdrs;
139         u_int *up;
140 {
141
142 #ifdef lint
143         (void) (xdr_short(xdrs, (short *)up));
144         return (xdr_u_long(xdrs, (u_long *)up));
145 #else
146         if (sizeof (u_int) == sizeof (u_long)) {
147                 return (xdr_u_long(xdrs, (u_long *)up));
148         } else {
149                 return (xdr_short(xdrs, (short *)up));
150         }
151 #endif
152 }
153
154 /*
155  * XDR long integers
156  * same as xdr_u_long - open coded to save a proc call!
157  */
158 bool_t
159 xdr_long(xdrs, lp)
160         XDR *xdrs;
161         long *lp;
162 {
163
164         if (xdrs->x_op == XDR_ENCODE)
165                 return (XDR_PUTLONG(xdrs, lp));
166
167         if (xdrs->x_op == XDR_DECODE)
168                 return (XDR_GETLONG(xdrs, lp));
169
170         if (xdrs->x_op == XDR_FREE)
171                 return (TRUE);
172
173         return (FALSE);
174 }
175
176 /*
177  * XDR unsigned long integers
178  * same as xdr_long - open coded to save a proc call!
179  */
180 bool_t
181 xdr_u_long(xdrs, ulp)
182         XDR *xdrs;
183         u_long *ulp;
184 {
185
186         if (xdrs->x_op == XDR_DECODE)
187                 return (XDR_GETLONG(xdrs, (long *)ulp));
188         if (xdrs->x_op == XDR_ENCODE)
189                 return (XDR_PUTLONG(xdrs, (long *)ulp));
190         if (xdrs->x_op == XDR_FREE)
191                 return (TRUE);
192         return (FALSE);
193 }
194
195 /*
196  * XDR short integers
197  */
198 bool_t
199 xdr_short(xdrs, sp)
200         XDR *xdrs;
201         short *sp;
202 {
203         long l;
204
205         switch (xdrs->x_op) {
206
207         case XDR_ENCODE:
208                 l = (long) *sp;
209                 return (XDR_PUTLONG(xdrs, &l));
210
211         case XDR_DECODE:
212                 if (!XDR_GETLONG(xdrs, &l)) {
213                         return (FALSE);
214                 }
215                 *sp = (short) l;
216                 return (TRUE);
217
218         case XDR_FREE:
219                 return (TRUE);
220         }
221         return (FALSE);
222 }
223
224 /*
225  * XDR unsigned short integers
226  */
227 bool_t
228 xdr_u_short(xdrs, usp)
229         XDR *xdrs;
230         u_short *usp;
231 {
232         u_long l;
233
234         switch (xdrs->x_op) {
235
236         case XDR_ENCODE:
237                 l = (u_long) *usp;
238                 return (XDR_PUTLONG(xdrs, &l));
239
240         case XDR_DECODE:
241                 if (!XDR_GETLONG(xdrs, &l)) {
242                         return (FALSE);
243                 }
244                 *usp = (u_short) l;
245                 return (TRUE);
246
247         case XDR_FREE:
248                 return (TRUE);
249         }
250         return (FALSE);
251 }
252
253
254 /*
255  * XDR a char
256  */
257 bool_t
258 xdr_char(xdrs, cp)
259         XDR *xdrs;
260         char *cp;
261 {
262         int i;
263
264         i = (*cp);
265         if (!xdr_int(xdrs, &i)) {
266                 return (FALSE);
267         }
268         *cp = i;
269         return (TRUE);
270 }
271
272 /*
273  * XDR an unsigned char
274  */
275 bool_t
276 xdr_u_char(xdrs, cp)
277         XDR *xdrs;
278         u_char *cp;
279 {
280         u_int u;
281
282         u = (*cp);
283         if (!xdr_u_int(xdrs, &u)) {
284                 return (FALSE);
285         }
286         *cp = u;
287         return (TRUE);
288 }
289
290 /*
291  * XDR booleans
292  */
293 bool_t
294 xdr_bool(xdrs, bp)
295         XDR *xdrs;
296         bool_t *bp;
297 {
298         long lb;
299
300         switch (xdrs->x_op) {
301
302         case XDR_ENCODE:
303                 lb = *bp ? XDR_TRUE : XDR_FALSE;
304                 return (XDR_PUTLONG(xdrs, &lb));
305
306         case XDR_DECODE:
307                 if (!XDR_GETLONG(xdrs, &lb)) {
308                         return (FALSE);
309                 }
310                 *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
311                 return (TRUE);
312
313         case XDR_FREE:
314                 return (TRUE);
315         }
316         return (FALSE);
317 }
318
319 /*
320  * XDR enumerations
321  */
322 bool_t
323 xdr_enum(xdrs, ep)
324         XDR *xdrs;
325         enum_t *ep;
326 {
327 #ifndef lint
328         enum sizecheck { SIZEVAL };     /* used to find the size of an enum */
329
330         /*
331          * enums are treated as ints
332          */
333         if (sizeof (enum sizecheck) == sizeof (long)) {
334                 return (xdr_long(xdrs, (long *)ep));
335         } else if (sizeof (enum sizecheck) == sizeof (short)) {
336                 return (xdr_short(xdrs, (short *)ep));
337         } else {
338                 return (FALSE);
339         }
340 #else
341         (void) (xdr_short(xdrs, (short *)ep));
342         return (xdr_long(xdrs, (long *)ep));
343 #endif
344 }
345
346 /*
347  * XDR opaque data
348  * Allows the specification of a fixed size sequence of opaque bytes.
349  * cp points to the opaque object and cnt gives the byte length.
350  */
351 bool_t
352 xdr_opaque(xdrs, cp, cnt)
353         XDR *xdrs;
354         caddr_t cp;
355         u_int cnt;
356 {
357         u_int rndup;
358         static char crud[BYTES_PER_XDR_UNIT];
359
360         /*
361          * if no data we are done
362          */
363         if (cnt == 0)
364                 return (TRUE);
365
366         /*
367          * round byte count to full xdr units
368          */
369         rndup = cnt % BYTES_PER_XDR_UNIT;
370         if (rndup > 0)
371                 rndup = BYTES_PER_XDR_UNIT - rndup;
372
373         if (xdrs->x_op == XDR_DECODE) {
374                 if (!XDR_GETBYTES(xdrs, cp, cnt)) {
375                         return (FALSE);
376                 }
377                 if (rndup == 0)
378                         return (TRUE);
379                 return (XDR_GETBYTES(xdrs, crud, rndup));
380         }
381
382         if (xdrs->x_op == XDR_ENCODE) {
383                 if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
384                         return (FALSE);
385                 }
386                 if (rndup == 0)
387                         return (TRUE);
388                 return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
389         }
390
391         if (xdrs->x_op == XDR_FREE) {
392                 return (TRUE);
393         }
394
395         return (FALSE);
396 }
397
398
399 /*
400  * XDR implementation using kernel buffers
401  */
402
403 #if defined(LIBC_SCCS) && !defined(lint)
404 /*static char *sccsid = "from: @(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
405 /*static char *sccsid = "from: @(#)xdr_mem.c    2.1 88/07/29 4.0 RPCSRC";*/
406 /*static char *rcsid = "Id: xdr_mem.c,v 1.2.4.2 1996/06/05 02:52:04 jkh Exp";*/
407 #endif
408
409 /*
410  * xdr_mem.h, XDR implementation using memory buffers.
411  *
412  * Copyright (C) 1984, Sun Microsystems, Inc.
413  *
414  * If you have some data to be interpreted as external data representation
415  * or to be converted to external data representation in a memory buffer,
416  * then this is the package for you.
417  *
418  */
419
420
421 void            xdrmbuf_init __P((XDR *, KBuffer *, enum xdr_op));
422 static bool_t   xdrmbuf_getlong __P((XDR *, long *));
423 static bool_t   xdrmbuf_putlong __P((XDR *, long *));
424 static bool_t   xdrmbuf_getbytes __P((XDR *, caddr_t, u_int));
425 static bool_t   xdrmbuf_putbytes __P((XDR *, caddr_t, u_int));
426 static u_int    xdrmbuf_getpos __P((XDR *));
427
428 static struct   xdr_ops xdrmbuf_ops = {
429         xdrmbuf_getlong,
430         xdrmbuf_putlong,
431         xdrmbuf_getbytes,
432         xdrmbuf_putbytes,
433         xdrmbuf_getpos,
434         NULL,
435         NULL,
436         NULL
437 };
438
439 /*
440  * The procedure xdrmbuf_init initializes a stream descriptor for a
441  * kernel buffer.
442  */
443 void
444 xdrmbuf_init(xdrs, m, op)
445         XDR *xdrs;
446         KBuffer *m;
447         enum xdr_op op;
448 {
449
450         xdrs->x_op = op;
451         xdrs->x_ops = &xdrmbuf_ops;
452         xdrs->x_base = (caddr_t)m;
453         KB_DATASTART(m, xdrs->x_private, caddr_t);
454         xdrs->x_handy = KB_LEN(m);
455 }
456
457 static bool_t
458 xdrmbuf_getlong(xdrs, lp)
459         XDR *xdrs;
460         long *lp;
461 {
462
463         /*
464          * See if long is contained in this buffer
465          */
466         if ((xdrs->x_handy -= sizeof(long)) < 0) {
467                 KBuffer *m;
468
469                 /*
470                  * We (currently) don't allow a long to span a buffer
471                  */
472                 if (xdrs->x_handy != -sizeof(long)) {
473                         printf("xdrmbuf_getlong: data spans buffers\n");
474                         return (FALSE);
475                 }
476
477                 /*
478                  * Try to move to a chained buffer
479                  */
480                 if ((m = (KBuffer *)(xdrs->x_base)) != NULL) {
481                         m = KB_NEXT(m);
482                         xdrs->x_base = (caddr_t)m;
483                 }
484                 if (m) {
485                         /*
486                          * Setup new buffer's info
487                          */
488                         KB_DATASTART(m, xdrs->x_private, caddr_t);
489                         if ((xdrs->x_handy = KB_LEN(m) - sizeof(long)) < 0) {
490                                 printf("xdrmbuf_getlong: short buffer\n");
491                                 return (FALSE);
492                         }
493                 } else {
494                         /*
495                          * No more buffers
496                          */
497                         return (FALSE);
498                 }
499         }
500
501         /*
502          * Return the long value
503          */
504         *lp = (long)ntohl((u_long)(*((long *)(xdrs->x_private))));
505
506         /*
507          * Advance the data stream
508          */
509         xdrs->x_private += sizeof(long);
510         return (TRUE);
511 }
512
513 static bool_t
514 xdrmbuf_putlong(xdrs, lp)
515         XDR *xdrs;
516         long *lp;
517 {
518
519         /*
520          * See if long will fit in this buffer
521          */
522         if ((xdrs->x_handy -= sizeof(long)) < 0) {
523                 KBuffer *m;
524
525                 /*
526                  * We (currently) don't allow a long to span a buffer
527                  */
528                 if (xdrs->x_handy != -sizeof(long)) {
529                         printf("xdrmbuf_putlong: data spans buffers\n");
530                         return (FALSE);
531                 }
532
533                 /*
534                  * Try to move to a chained buffer
535                  */
536                 if ((m = (KBuffer *)(xdrs->x_base)) != NULL) {
537                         m = KB_NEXT(m);
538                         xdrs->x_base = (caddr_t)m;
539                 }
540                 if (m) {
541                         /*
542                          * Setup new buffer's info
543                          */
544                         KB_DATASTART(m, xdrs->x_private, caddr_t);
545                         if ((xdrs->x_handy = KB_LEN(m) - sizeof(long)) < 0) {
546                                 printf("xdrmbuf_putlong: short buffer\n");
547                                 return (FALSE);
548                         }
549                 } else {
550                         /*
551                          * No more buffers
552                          */
553                         return (FALSE);
554                 }
555         }
556
557         /*
558          * Store the long value into our buffer
559          */
560         *(long *)xdrs->x_private = (long)htonl((u_long)(*lp));
561
562         /*
563          * Advance the data stream
564          */
565         xdrs->x_private += sizeof(long);
566         return (TRUE);
567 }
568
569 static bool_t
570 xdrmbuf_getbytes(xdrs, addr, len)
571         XDR *xdrs;
572         caddr_t addr;
573         u_int len;
574 {
575
576         while (len > 0) {
577                 u_int   copy;
578
579                 if (xdrs->x_handy <= 0) {
580                         KBuffer *m;
581
582                         /*
583                          * No data in current buffer, move to a chained buffer
584                          */
585                         if ((m = (KBuffer *)(xdrs->x_base)) != NULL) {
586                                 m = KB_NEXT(m);
587                                 xdrs->x_base = (caddr_t)m;
588                         }
589                         if (m) {
590                                 /*
591                                  * Setup new buffer's info
592                                  */
593                                 KB_DATASTART(m, xdrs->x_private, caddr_t);
594                                 xdrs->x_handy = KB_LEN(m);
595                         } else {
596                                 /*
597                                  * No more buffers
598                                  */
599                                 return (FALSE);
600                         }
601                 }
602
603                 /*
604                  * Copy from buffer to user's space
605                  */
606                 copy = MIN(len, xdrs->x_handy);
607                 KM_COPY(xdrs->x_private, addr, copy);
608
609                 /*
610                  * Update data stream controls
611                  */
612                 xdrs->x_private += copy;
613                 xdrs->x_handy -= copy;
614                 addr += copy;
615                 len -= copy;
616         }
617         return (TRUE);
618 }
619
620 static bool_t
621 xdrmbuf_putbytes(xdrs, addr, len)
622         XDR *xdrs;
623         caddr_t addr;
624         u_int len;
625 {
626
627         while (len > 0) {
628                 u_int   copy;
629
630                 if (xdrs->x_handy <= 0) {
631                         KBuffer *m;
632
633                         /*
634                          * No data in current buffer, move to a chained buffer
635                          */
636                         if ((m = (KBuffer *)(xdrs->x_base)) != NULL) {
637                                 m = KB_NEXT(m);
638                                 xdrs->x_base = (caddr_t)m;
639                         }
640                         if (m) {
641                                 /*
642                                  * Setup new buffer's info
643                                  */
644                                 KB_DATASTART(m, xdrs->x_private, caddr_t);
645                                 xdrs->x_handy = KB_LEN(m);
646                         } else {
647                                 /*
648                                  * No more buffers
649                                  */
650                                 return (FALSE);
651                         }
652                 }
653
654                 /*
655                  * Copy from user's space into buffer
656                  */
657                 copy = MIN(len, xdrs->x_handy);
658                 KM_COPY(addr, xdrs->x_private, copy);
659
660                 /*
661                  * Update data stream controls
662                  */
663                 xdrs->x_private += copy;
664                 xdrs->x_handy -= copy;
665                 addr += copy;
666                 len -= copy;
667         }
668         return (TRUE);
669 }
670
671 static u_int
672 xdrmbuf_getpos(xdrs)
673         XDR *xdrs;
674 {
675
676         return ((u_int)xdrs->x_private - (u_int)xdrs->x_base);
677 }
678
679 #endif  /* !defined(sun) */
680