XDR: decouple from system XDR implementation
[openafs.git] / src / rx / xdr_rx.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * xdr_rx.c.  XDR using RX.
12  */
13
14 #include <afsconfig.h>
15 #include <afs/param.h>
16
17 #ifdef KERNEL
18 # include "afs/sysincludes.h"
19 # ifndef UKERNEL
20 #  include "h/types.h"
21 #  include "h/uio.h"
22 #  ifdef AFS_LINUX20_ENV
23 #   include "h/socket.h"
24 #  else
25 #   include "rpc/types.h"
26 #  endif
27 #  ifdef AFS_LINUX22_ENV
28 #   ifndef quad_t
29 #    define quad_t __quad_t
30 #    define u_quad_t __u_quad_t
31 #   endif
32 #  endif
33 #  include "netinet/in.h"
34 # endif /* !UKERNEL */
35 #else /* KERNEL */
36 # include <roken.h>
37 #endif /* KERNEL */
38
39 #include "rx.h"
40 #include "xdr.h"
41
42 /* Static prototypes */
43 static bool_t xdrrx_getint32(XDR *axdrs, afs_int32 * lp);
44 static bool_t xdrrx_putint32(XDR *axdrs, afs_int32 * lp);
45 static bool_t xdrrx_getbytes(XDR *axdrs, caddr_t addr,
46                              u_int len);
47 static bool_t xdrrx_putbytes(XDR *axdrs, caddr_t addr,
48                              u_int len);
49 static afs_int32 *xdrrx_inline(XDR *axdrs, u_int len);
50
51
52 /*
53  * Ops vector for stdio type XDR
54  */
55 static struct xdr_ops xdrrx_ops = {
56 #ifndef HAVE_STRUCT_LABEL_SUPPORT
57     /* Windows does not support labeled assigments */
58     xdrrx_getint32,     /* deserialize an afs_int32 */
59     xdrrx_putint32,     /* serialize an afs_int32 */
60     xdrrx_getbytes,     /* deserialize counted bytes */
61     xdrrx_putbytes,     /* serialize counted bytes */
62     NULL,               /* get offset in the stream: not supported. */
63     NULL,               /* set offset in the stream: not supported. */
64     xdrrx_inline,       /* prime stream for inline macros */
65     NULL,               /* destroy stream */
66 #else
67     .x_getint32 = xdrrx_getint32,       /* deserialize an afs_int32 */
68     .x_putint32 = xdrrx_putint32,       /* serialize an afs_int32 */
69     .x_getbytes = xdrrx_getbytes,       /* deserialize counted bytes */
70     .x_putbytes = xdrrx_putbytes,       /* serialize counted bytes */
71     .x_getpostn = NULL,         /* get offset in the stream: not supported. */
72     .x_setpostn = NULL,         /* set offset in the stream: not supported. */
73     .x_inline = xdrrx_inline,           /* prime stream for inline macros */
74     .x_destroy = NULL,                  /* destroy stream */
75 #endif
76 };
77
78 /*
79  * Initialize an rx xdr handle, for a given rx call.  op must be XDR_ENCODE or XDR_DECODE.
80  * Call must have been returned by rx_MakeCall or rx_GetCall.
81  */
82 void
83 xdrrx_create(XDR * xdrs, struct rx_call *call,
84              enum xdr_op op)
85 {
86     xdrs->x_op = op;
87     xdrs->x_ops = &xdrrx_ops;
88     xdrs->x_private = (caddr_t) call;
89 }
90
91 #if     defined(KERNEL) && defined(AFS_AIX32_ENV)
92 #define STACK_TO_PIN    2*PAGESIZE      /* 8K */
93 int rx_pin_failed = 0;
94 #endif
95
96 static bool_t
97 xdrrx_getint32(XDR *axdrs, afs_int32 * lp)
98 {
99     afs_int32 l;
100     XDR * xdrs = (XDR *)axdrs;
101     struct rx_call *call = ((struct rx_call *)(xdrs)->x_private);
102 #if     defined(KERNEL) && defined(AFS_AIX32_ENV)
103     char *saddr = (char *)&l;
104     saddr -= STACK_TO_PIN;
105     /*
106      * Hack of hacks: Aix3.2 only guarantees that the next 2K of stack in pinned. Under
107      * splnet (disables interrupts), which is set throughout rx, we can't swap in stack
108      * pages if we need so we panic. Since sometimes, under splnet, we'll use more than
109      * 2K stack we could try to bring the next few stack pages in here before we call the rx
110      * layer. Of course this doesn't guarantee that those stack pages won't be swapped
111      * out between here and calling splnet. So we now pin (and unpin) them instead to
112      * guarantee that they remain there.
113      */
114     if (pin(saddr, STACK_TO_PIN)) {
115         /* XXX There's little we can do by continue XXX */
116         saddr = NULL;
117         rx_pin_failed++;
118     }
119 #endif
120     if (rx_Read32(call, &l) == sizeof(l)) {
121         *lp = ntohl(l);
122 #if     defined(KERNEL) && defined(AFS_AIX32_ENV)
123         if (saddr)
124             unpin(saddr, STACK_TO_PIN);
125 #endif
126         return TRUE;
127     }
128 #if     defined(KERNEL) && defined(AFS_AIX32_ENV)
129     if (saddr)
130         unpin(saddr, STACK_TO_PIN);
131 #endif
132     return FALSE;
133 }
134
135 static bool_t
136 xdrrx_putint32(XDR *axdrs, afs_int32 * lp)
137 {
138     afs_int32 code, l = htonl(*lp);
139     XDR * xdrs = (XDR *)axdrs;
140     struct rx_call *call = ((struct rx_call *)(xdrs)->x_private);
141 #if     defined(KERNEL) && defined(AFS_AIX32_ENV)
142     char *saddr = (char *)&code;
143     saddr -= STACK_TO_PIN;
144     /*
145      * Hack of hacks: Aix3.2 only guarantees that the next 2K of stack in pinned. Under
146      * splnet (disables interrupts), which is set throughout rx, we can't swap in stack
147      * pages if we need so we panic. Since sometimes, under splnet, we'll use more than
148      * 2K stack we could try to bring the next few stack pages in here before we call the rx
149      * layer. Of course this doesn't guarantee that those stack pages won't be swapped
150      * out between here and calling splnet. So we now pin (and unpin) them instead to
151      * guarantee that they remain there.
152      */
153     if (pin(saddr, STACK_TO_PIN)) {
154         saddr = NULL;
155         rx_pin_failed++;
156     }
157 #endif
158     code = (rx_Write32(call, &l) == sizeof(l));
159 #if     defined(KERNEL) && defined(AFS_AIX32_ENV)
160     if (saddr)
161         unpin(saddr, STACK_TO_PIN);
162 #endif
163     return code;
164 }
165
166 static bool_t
167 xdrrx_getbytes(XDR *axdrs, caddr_t addr, u_int len)
168 {
169     afs_int32 code;
170     XDR * xdrs = (XDR *)axdrs;
171     struct rx_call *call = ((struct rx_call *)(xdrs)->x_private);
172 #if     defined(KERNEL) && defined(AFS_AIX32_ENV)
173     char *saddr = (char *)&code;
174     saddr -= STACK_TO_PIN;
175     /*
176      * Hack of hacks: Aix3.2 only guarantees that the next 2K of stack in pinned. Under
177      * splnet (disables interrupts), which is set throughout rx, we can't swap in stack
178      * pages if we need so we panic. Since sometimes, under splnet, we'll use more than
179      * 2K stack we could try to bring the next few stack pages in here before we call the rx
180      * layer. Of course this doesn't guarantee that those stack pages won't be swapped
181      * out between here and calling splnet. So we now pin (and unpin) them instead to
182      * guarantee that they remain there.
183      */
184     if (pin(saddr, STACK_TO_PIN)) {
185         /* XXX There's little we can do by continue XXX */
186         saddr = NULL;
187         rx_pin_failed++;
188     }
189 #endif
190     code = (rx_Read(call, addr, len) == len);
191 #if     defined(KERNEL) && defined(AFS_AIX32_ENV)
192     if (saddr)
193         unpin(saddr, STACK_TO_PIN);
194 #endif
195     return code;
196 }
197
198 static bool_t
199 xdrrx_putbytes(XDR *axdrs, caddr_t addr, u_int len)
200 {
201     afs_int32 code;
202     XDR * xdrs = (XDR *)axdrs;
203     struct rx_call *call = ((struct rx_call *)(xdrs)->x_private);
204 #if     defined(KERNEL) && defined(AFS_AIX32_ENV)
205     char *saddr = (char *)&code;
206     saddr -= STACK_TO_PIN;
207     /*
208      * Hack of hacks: Aix3.2 only guarantees that the next 2K of stack in pinned. Under
209      * splnet (disables interrupts), which is set throughout rx, we can't swap in stack
210      * pages if we need so we panic. Since sometimes, under splnet, we'll use more than
211      * 2K stack we could try to bring the next few stack pages in here before we call the rx
212      * layer. Of course this doesn't guarantee that those stack pages won't be swapped
213      * out between here and calling splnet. So we now pin (and unpin) them instead to
214      * guarantee that they remain there.
215      */
216     if (pin(saddr, STACK_TO_PIN)) {
217         /* XXX There's little we can do by continue XXX */
218         saddr = NULL;
219         rx_pin_failed++;
220     }
221 #endif
222     code = (rx_Write(call, addr, len) == len);
223 #if     defined(KERNEL) && defined(AFS_AIX32_ENV)
224     if (saddr)
225         unpin(saddr, STACK_TO_PIN);
226 #endif
227     return code;
228 }
229
230 #ifdef undef                    /* not used */
231 static u_int
232 xdrrx_getpos(XDR * xdrs)
233 {
234     /* Not supported.  What error code should we return? (It doesn't matter:  it will never be called, anyway!) */
235     return -1;
236 }
237
238 static bool_t
239 xdrrx_setpos(XDR * xdrs, u_int pos)
240 {
241     /* Not supported */
242     return FALSE;
243 }
244 #endif
245
246 static afs_int32 *
247 xdrrx_inline(XDR *axdrs, u_int len)
248 {
249     /* I don't know what this routine is supposed to do, but the stdio module returns null, so we will, too */
250     return (0);
251 }