carp: add carp_group_demote_adj()
[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.9 2008/10/28 17:23:46 swildner 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 /*
80  * xdr.c, Generic XDR routines implementation.
81  *
82  * Copyright (C) 1986, Sun Microsystems, Inc.
83  *
84  * These are the "generic" xdr routines used to serialize and de-serialize
85  * most common data items.  See xdr.h for more info on the interface to
86  * xdr.
87  */
88
89 #include <netproto/atm/spans/spans_kxdr.h>
90
91 /*
92  * constants specific to the xdr "protocol"
93  */
94 #define XDR_FALSE       ((long) 0)
95 #define XDR_TRUE        ((long) 1)
96 #define LASTUNSIGNED    ((u_int) 0-1)
97
98 /*
99  * for unit alignment
100  */
101 static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
102
103 /*
104  * XDR integers
105  */
106 bool_t
107 xdr_int(XDR *xdrs, int *ip)
108 {
109
110 #ifdef lint
111         (xdr_short(xdrs, (short *)ip));
112         return (xdr_long(xdrs, (long *)ip));
113 #else
114         if (sizeof (int) == sizeof (long)) {
115                 return (xdr_long(xdrs, (long *)ip));
116         } else {
117                 return (xdr_short(xdrs, (short *)ip));
118         }
119 #endif
120 }
121
122 /*
123  * XDR unsigned integers
124  */
125 bool_t
126 xdr_u_int(XDR *xdrs, u_int *up)
127 {
128
129 #ifdef lint
130         (xdr_short(xdrs, (short *)up));
131         return (xdr_u_long(xdrs, (u_long *)up));
132 #else
133         if (sizeof (u_int) == sizeof (u_long)) {
134                 return (xdr_u_long(xdrs, (u_long *)up));
135         } else {
136                 return (xdr_short(xdrs, (short *)up));
137         }
138 #endif
139 }
140
141 /*
142  * XDR long integers
143  * same as xdr_u_long - open coded to save a proc call!
144  */
145 bool_t
146 xdr_long(XDR *xdrs, long *lp)
147 {
148
149         if (xdrs->x_op == XDR_ENCODE)
150                 return (XDR_PUTLONG(xdrs, lp));
151
152         if (xdrs->x_op == XDR_DECODE)
153                 return (XDR_GETLONG(xdrs, lp));
154
155         if (xdrs->x_op == XDR_FREE)
156                 return (TRUE);
157
158         return (FALSE);
159 }
160
161 /*
162  * XDR unsigned long integers
163  * same as xdr_long - open coded to save a proc call!
164  */
165 bool_t
166 xdr_u_long(XDR *xdrs, u_long *ulp)
167 {
168
169         if (xdrs->x_op == XDR_DECODE)
170                 return (XDR_GETLONG(xdrs, (long *)ulp));
171         if (xdrs->x_op == XDR_ENCODE)
172                 return (XDR_PUTLONG(xdrs, (long *)ulp));
173         if (xdrs->x_op == XDR_FREE)
174                 return (TRUE);
175         return (FALSE);
176 }
177
178 /*
179  * XDR short integers
180  */
181 bool_t
182 xdr_short(XDR *xdrs, short *sp)
183 {
184         long l;
185
186         switch (xdrs->x_op) {
187
188         case XDR_ENCODE:
189                 l = (long) *sp;
190                 return (XDR_PUTLONG(xdrs, &l));
191
192         case XDR_DECODE:
193                 if (!XDR_GETLONG(xdrs, &l)) {
194                         return (FALSE);
195                 }
196                 *sp = (short) l;
197                 return (TRUE);
198
199         case XDR_FREE:
200                 return (TRUE);
201         }
202         return (FALSE);
203 }
204
205 /*
206  * XDR unsigned short integers
207  */
208 bool_t
209 xdr_u_short(XDR *xdrs, u_short *usp)
210 {
211         u_long l;
212
213         switch (xdrs->x_op) {
214
215         case XDR_ENCODE:
216                 l = (u_long) *usp;
217                 return (XDR_PUTLONG(xdrs, &l));
218
219         case XDR_DECODE:
220                 if (!XDR_GETLONG(xdrs, &l)) {
221                         return (FALSE);
222                 }
223                 *usp = (u_short) l;
224                 return (TRUE);
225
226         case XDR_FREE:
227                 return (TRUE);
228         }
229         return (FALSE);
230 }
231
232
233 /*
234  * XDR a char
235  */
236 bool_t
237 xdr_char(XDR *xdrs, char *cp)
238 {
239         int i;
240
241         i = (*cp);
242         if (!xdr_int(xdrs, &i)) {
243                 return (FALSE);
244         }
245         *cp = i;
246         return (TRUE);
247 }
248
249 /*
250  * XDR an unsigned char
251  */
252 bool_t
253 xdr_u_char(XDR *xdrs, u_char *cp)
254 {
255         u_int u;
256
257         u = (*cp);
258         if (!xdr_u_int(xdrs, &u)) {
259                 return (FALSE);
260         }
261         *cp = u;
262         return (TRUE);
263 }
264
265 /*
266  * XDR booleans
267  */
268 bool_t
269 xdr_bool(XDR *xdrs, bool_t *bp)
270 {
271         long lb;
272
273         switch (xdrs->x_op) {
274
275         case XDR_ENCODE:
276                 lb = *bp ? XDR_TRUE : XDR_FALSE;
277                 return (XDR_PUTLONG(xdrs, &lb));
278
279         case XDR_DECODE:
280                 if (!XDR_GETLONG(xdrs, &lb)) {
281                         return (FALSE);
282                 }
283                 *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
284                 return (TRUE);
285
286         case XDR_FREE:
287                 return (TRUE);
288         }
289         return (FALSE);
290 }
291
292 /*
293  * XDR enumerations
294  */
295 bool_t
296 xdr_enum(XDR *xdrs, enum_t *ep)
297 {
298 #ifndef lint
299         enum sizecheck { SIZEVAL };     /* used to find the size of an enum */
300
301         /*
302          * enums are treated as ints
303          */
304         if (sizeof (enum sizecheck) == sizeof (long)) {
305                 return (xdr_long(xdrs, (long *)ep));
306         } else if (sizeof (enum sizecheck) == sizeof (short)) {
307                 return (xdr_short(xdrs, (short *)ep));
308         } else {
309                 return (FALSE);
310         }
311 #else
312         (xdr_short(xdrs, (short *)ep));
313         return (xdr_long(xdrs, (long *)ep));
314 #endif
315 }
316
317 /*
318  * XDR opaque data
319  * Allows the specification of a fixed size sequence of opaque bytes.
320  * cp points to the opaque object and cnt gives the byte length.
321  */
322 bool_t
323 xdr_opaque(XDR *xdrs, caddr_t cp, u_int cnt)
324 {
325         u_int rndup;
326         static char crud[BYTES_PER_XDR_UNIT];
327
328         /*
329          * if no data we are done
330          */
331         if (cnt == 0)
332                 return (TRUE);
333
334         /*
335          * round byte count to full xdr units
336          */
337         rndup = cnt % BYTES_PER_XDR_UNIT;
338         if (rndup > 0)
339                 rndup = BYTES_PER_XDR_UNIT - rndup;
340
341         if (xdrs->x_op == XDR_DECODE) {
342                 if (!XDR_GETBYTES(xdrs, cp, cnt)) {
343                         return (FALSE);
344                 }
345                 if (rndup == 0)
346                         return (TRUE);
347                 return (XDR_GETBYTES(xdrs, crud, rndup));
348         }
349
350         if (xdrs->x_op == XDR_ENCODE) {
351                 if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
352                         return (FALSE);
353                 }
354                 if (rndup == 0)
355                         return (TRUE);
356                 return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
357         }
358
359         if (xdrs->x_op == XDR_FREE) {
360                 return (TRUE);
361         }
362
363         return (FALSE);
364 }
365
366
367 /*
368  * XDR implementation using kernel buffers
369  */
370
371 /*
372  * xdr_mem.h, XDR implementation using memory buffers.
373  *
374  * Copyright (C) 1984, Sun Microsystems, Inc.
375  *
376  * If you have some data to be interpreted as external data representation
377  * or to be converted to external data representation in a memory buffer,
378  * then this is the package for you.
379  *
380  */
381
382
383 void            xdrmbuf_init (XDR *, KBuffer *, enum xdr_op);
384 static bool_t   xdrmbuf_getlong (XDR *, long *);
385 static bool_t   xdrmbuf_putlong (XDR *, long *);
386 static bool_t   xdrmbuf_getbytes (XDR *, caddr_t, u_int);
387 static bool_t   xdrmbuf_putbytes (XDR *, caddr_t, u_int);
388 static u_int    xdrmbuf_getpos (XDR *);
389
390 static struct   xdr_ops xdrmbuf_ops = {
391         xdrmbuf_getlong,
392         xdrmbuf_putlong,
393         xdrmbuf_getbytes,
394         xdrmbuf_putbytes,
395         xdrmbuf_getpos,
396         NULL,
397         NULL,
398         NULL
399 };
400
401 /*
402  * The procedure xdrmbuf_init initializes a stream descriptor for a
403  * kernel buffer.
404  */
405 void
406 xdrmbuf_init(XDR *xdrs, KBuffer *m, enum xdr_op op)
407 {
408
409         xdrs->x_op = op;
410         xdrs->x_ops = &xdrmbuf_ops;
411         xdrs->x_base = (caddr_t)m;
412         KB_DATASTART(m, xdrs->x_private, caddr_t);
413         xdrs->x_handy = KB_LEN(m);
414 }
415
416 static bool_t
417 xdrmbuf_getlong(XDR *xdrs, long *lp)
418 {
419
420         /*
421          * See if long is contained in this buffer
422          */
423         if ((xdrs->x_handy -= sizeof(long)) < 0) {
424                 KBuffer *m;
425
426                 /*
427                  * We (currently) don't allow a long to span a buffer
428                  */
429                 if (xdrs->x_handy != -sizeof(long)) {
430                         kprintf("xdrmbuf_getlong: data spans buffers\n");
431                         return (FALSE);
432                 }
433
434                 /*
435                  * Try to move to a chained buffer
436                  */
437                 if ((m = (KBuffer *)(xdrs->x_base)) != NULL) {
438                         m = KB_NEXT(m);
439                         xdrs->x_base = (caddr_t)m;
440                 }
441                 if (m) {
442                         /*
443                          * Setup new buffer's info
444                          */
445                         KB_DATASTART(m, xdrs->x_private, caddr_t);
446                         if ((xdrs->x_handy = KB_LEN(m) - sizeof(long)) < 0) {
447                                 kprintf("xdrmbuf_getlong: short buffer\n");
448                                 return (FALSE);
449                         }
450                 } else {
451                         /*
452                          * No more buffers
453                          */
454                         return (FALSE);
455                 }
456         }
457
458         /*
459          * Return the long value
460          */
461         *lp = (long)ntohl((u_long)(*((long *)(xdrs->x_private))));
462
463         /*
464          * Advance the data stream
465          */
466         xdrs->x_private = (char *)xdrs->x_private + sizeof(long);
467         return (TRUE);
468 }
469
470 static bool_t
471 xdrmbuf_putlong(XDR *xdrs, long *lp)
472 {
473
474         /*
475          * See if long will fit in this buffer
476          */
477         if ((xdrs->x_handy -= sizeof(long)) < 0) {
478                 KBuffer *m;
479
480                 /*
481                  * We (currently) don't allow a long to span a buffer
482                  */
483                 if (xdrs->x_handy != -sizeof(long)) {
484                         kprintf("xdrmbuf_putlong: data spans buffers\n");
485                         return (FALSE);
486                 }
487
488                 /*
489                  * Try to move to a chained buffer
490                  */
491                 if ((m = (KBuffer *)(xdrs->x_base)) != NULL) {
492                         m = KB_NEXT(m);
493                         xdrs->x_base = (caddr_t)m;
494                 }
495                 if (m) {
496                         /*
497                          * Setup new buffer's info
498                          */
499                         KB_DATASTART(m, xdrs->x_private, caddr_t);
500                         if ((xdrs->x_handy = KB_LEN(m) - sizeof(long)) < 0) {
501                                 kprintf("xdrmbuf_putlong: short buffer\n");
502                                 return (FALSE);
503                         }
504                 } else {
505                         /*
506                          * No more buffers
507                          */
508                         return (FALSE);
509                 }
510         }
511
512         /*
513          * Store the long value into our buffer
514          */
515         *(long *)xdrs->x_private = (long)htonl((u_long)(*lp));
516
517         /*
518          * Advance the data stream
519          */
520         xdrs->x_private = (char *)xdrs->x_private + sizeof(long);
521         return (TRUE);
522 }
523
524 static bool_t
525 xdrmbuf_getbytes(XDR *xdrs, caddr_t addr, u_int len)
526 {
527
528         while (len > 0) {
529                 u_int   copy;
530
531                 if (xdrs->x_handy <= 0) {
532                         KBuffer *m;
533
534                         /*
535                          * No data in current buffer, move to a chained buffer
536                          */
537                         if ((m = (KBuffer *)(xdrs->x_base)) != NULL) {
538                                 m = KB_NEXT(m);
539                                 xdrs->x_base = (caddr_t)m;
540                         }
541                         if (m) {
542                                 /*
543                                  * Setup new buffer's info
544                                  */
545                                 KB_DATASTART(m, xdrs->x_private, caddr_t);
546                                 xdrs->x_handy = KB_LEN(m);
547                         } else {
548                                 /*
549                                  * No more buffers
550                                  */
551                                 return (FALSE);
552                         }
553                 }
554
555                 /*
556                  * Copy from buffer to user's space
557                  */
558                 copy = MIN(len, xdrs->x_handy);
559                 KM_COPY(xdrs->x_private, addr, copy);
560
561                 /*
562                  * Update data stream controls
563                  */
564                 xdrs->x_private = (char *)xdrs->x_private + copy;
565                 xdrs->x_handy -= copy;
566                 addr += copy;
567                 len -= copy;
568         }
569         return (TRUE);
570 }
571
572 static bool_t
573 xdrmbuf_putbytes(XDR *xdrs, caddr_t addr, 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 user's space into buffer
605                  */
606                 copy = MIN(len, xdrs->x_handy);
607                 KM_COPY(addr, xdrs->x_private, copy);
608
609                 /*
610                  * Update data stream controls
611                  */
612                 xdrs->x_private = (char *)xdrs->x_private + copy;
613                 xdrs->x_handy -= copy;
614                 addr += copy;
615                 len -= copy;
616         }
617         return (TRUE);
618 }
619
620 static u_int
621 xdrmbuf_getpos(XDR *xdrs)
622 {
623
624         return ((u_int)xdrs->x_private - (u_int)xdrs->x_base);
625 }