1 | /* |
2 | * Copyright (c) 2010, Oracle America, Inc. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions are |
6 | * met: |
7 | * |
8 | * * Redistributions of source code must retain the above copyright |
9 | * notice, this list of conditions and the following disclaimer. |
10 | * * Redistributions in binary form must reproduce the above |
11 | * copyright notice, this list of conditions and the following |
12 | * disclaimer in the documentation and/or other materials |
13 | * provided with the distribution. |
14 | * * Neither the name of the "Oracle America, Inc." nor the names of its |
15 | * contributors may be used to endorse or promote products derived |
16 | * from this software without specific prior written permission. |
17 | * |
18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
21 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
22 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
23 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
25 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
27 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 | */ |
31 | |
32 | #include <rpcsvc/yp.h> |
33 | #include <rpcsvc/ypclnt.h> |
34 | #include <shlib-compat.h> |
35 | |
36 | /* The NIS v2 protocol suggests 1024 bytes as a maximum length of all fields. |
37 | Current Linux systems don't use this limit. To remain compatible with |
38 | recent Linux systems we choose limits large enough to load large key and |
39 | data values, but small enough to not pose a DoS threat. */ |
40 | |
41 | #define XDRMAXNAME 1024 |
42 | #define XDRMAXRECORD (16 * 1024 * 1024) |
43 | |
44 | bool_t |
45 | xdr_ypstat (XDR *xdrs, ypstat *objp) |
46 | { |
47 | return xdr_enum (xdrs: xdrs, ep: (enum_t *) objp); |
48 | } |
49 | libnsl_hidden_nolink_def (xdr_ypstat, GLIBC_2_0) |
50 | |
51 | bool_t |
52 | xdr_ypxfrstat (XDR *xdrs, ypxfrstat *objp) |
53 | { |
54 | return xdr_enum (xdrs: xdrs, ep: (enum_t *) objp); |
55 | } |
56 | libnsl_hidden_nolink_def (xdr_ypxfrstat, GLIBC_2_0) |
57 | |
58 | bool_t |
59 | xdr_domainname (XDR *xdrs, domainname *objp) |
60 | { |
61 | return xdr_string (xdrs: xdrs, cpp: objp, XDRMAXNAME); |
62 | } |
63 | libnsl_hidden_nolink_def (xdr_domainname, GLIBC_2_0) |
64 | |
65 | bool_t |
66 | xdr_mapname (XDR *xdrs, mapname *objp) |
67 | { |
68 | return xdr_string (xdrs: xdrs, cpp: objp, XDRMAXNAME); |
69 | } |
70 | libnsl_hidden_nolink_def (xdr_mapname, GLIBC_2_0) |
71 | |
72 | bool_t |
73 | xdr_peername (XDR *xdrs, peername *objp) |
74 | { |
75 | return xdr_string (xdrs: xdrs, cpp: objp, XDRMAXNAME); |
76 | } |
77 | libnsl_hidden_nolink_def (xdr_peername, GLIBC_2_0) |
78 | |
79 | bool_t |
80 | xdr_keydat (XDR *xdrs, keydat *objp) |
81 | { |
82 | return xdr_bytes (xdrs: xdrs, cpp: (char **) &objp->keydat_val, |
83 | sizep: (u_int *) &objp->keydat_len, XDRMAXRECORD); |
84 | } |
85 | libnsl_hidden_nolink_def (xdr_keydat, GLIBC_2_0) |
86 | |
87 | bool_t |
88 | xdr_valdat (XDR *xdrs, valdat *objp) |
89 | { |
90 | return xdr_bytes (xdrs: xdrs, cpp: (char **) &objp->valdat_val, |
91 | sizep: (u_int *) &objp->valdat_len, XDRMAXRECORD); |
92 | } |
93 | libnsl_hidden_nolink_def (xdr_valdat, GLIBC_2_0) |
94 | |
95 | bool_t |
96 | xdr_ypmap_parms (XDR *xdrs, ypmap_parms *objp) |
97 | { |
98 | if (!xdr_domainname (xdrs, objp: &objp->domain)) |
99 | return FALSE; |
100 | if (!xdr_mapname (xdrs, objp: &objp->map)) |
101 | return FALSE; |
102 | if (!xdr_u_int (xdrs: xdrs, up: &objp->ordernum)) |
103 | return FALSE; |
104 | return xdr_peername (xdrs, objp: &objp->peer); |
105 | } |
106 | libnsl_hidden_nolink_def (xdr_ypmap_parms, GLIBC_2_0) |
107 | |
108 | bool_t |
109 | xdr_ypreq_key (XDR *xdrs, ypreq_key *objp) |
110 | { |
111 | if (!xdr_domainname (xdrs, objp: &objp->domain)) |
112 | return FALSE; |
113 | if (!xdr_mapname (xdrs, objp: &objp->map)) |
114 | return FALSE; |
115 | return xdr_keydat (xdrs, objp: &objp->key); |
116 | } |
117 | libnsl_hidden_nolink_def (xdr_ypreq_key, GLIBC_2_0) |
118 | |
119 | bool_t |
120 | xdr_ypreq_nokey (XDR *xdrs, ypreq_nokey *objp) |
121 | { |
122 | if (!xdr_domainname (xdrs, objp: &objp->domain)) |
123 | return FALSE; |
124 | return xdr_mapname (xdrs, objp: &objp->map); |
125 | } |
126 | libnsl_hidden_nolink_def (xdr_ypreq_nokey, GLIBC_2_0) |
127 | |
128 | bool_t |
129 | xdr_ypreq_xfr (XDR *xdrs, ypreq_xfr *objp) |
130 | { |
131 | if (!xdr_ypmap_parms (xdrs, objp: &objp->map_parms)) |
132 | return FALSE; |
133 | if (!xdr_u_int (xdrs: xdrs, up: &objp->transid)) |
134 | return FALSE; |
135 | if (!xdr_u_int (xdrs: xdrs, up: &objp->prog)) |
136 | return FALSE; |
137 | return xdr_u_int (xdrs: xdrs, up: &objp->port); |
138 | } |
139 | libnsl_hidden_nolink_def (xdr_ypreq_xfr, GLIBC_2_0) |
140 | |
141 | bool_t |
142 | xdr_ypresp_val (XDR *xdrs, ypresp_val *objp) |
143 | { |
144 | if (!xdr_ypstat (xdrs, objp: &objp->stat)) |
145 | return FALSE; |
146 | return xdr_valdat (xdrs, objp: &objp->val); |
147 | } |
148 | libnsl_hidden_nolink_def (xdr_ypresp_val, GLIBC_2_0) |
149 | |
150 | bool_t |
151 | xdr_ypresp_key_val (XDR *xdrs, ypresp_key_val *objp) |
152 | { |
153 | if (!xdr_ypstat (xdrs, objp: &objp->stat)) |
154 | return FALSE; |
155 | if (!xdr_valdat (xdrs, objp: &objp->val)) |
156 | return FALSE; |
157 | return xdr_keydat (xdrs, objp: &objp->key); |
158 | } |
159 | libnsl_hidden_nolink_def (xdr_ypresp_key_val, GLIBC_2_0) |
160 | |
161 | bool_t |
162 | xdr_ypresp_master (XDR *xdrs, ypresp_master *objp) |
163 | { |
164 | if (!xdr_ypstat (xdrs, objp: &objp->stat)) |
165 | return FALSE; |
166 | return xdr_peername (xdrs, objp: &objp->peer); |
167 | } |
168 | libnsl_hidden_nolink_def (xdr_ypresp_master, GLIBC_2_0) |
169 | |
170 | bool_t |
171 | xdr_ypresp_order (XDR *xdrs, ypresp_order *objp) |
172 | { |
173 | if (!xdr_ypstat (xdrs, objp: &objp->stat)) |
174 | return FALSE; |
175 | return xdr_u_int (xdrs: xdrs, up: &objp->ordernum); |
176 | } |
177 | libnsl_hidden_nolink_def (xdr_ypresp_order, GLIBC_2_0) |
178 | |
179 | bool_t |
180 | xdr_ypresp_all (XDR *xdrs, ypresp_all *objp) |
181 | { |
182 | if (!xdr_bool (xdrs: xdrs, bp: &objp->more)) |
183 | return FALSE; |
184 | switch (objp->more) |
185 | { |
186 | case TRUE: |
187 | return xdr_ypresp_key_val (xdrs, objp: &objp->ypresp_all_u.val); |
188 | case FALSE: |
189 | break; |
190 | default: |
191 | return FALSE; |
192 | } |
193 | return TRUE; |
194 | } |
195 | libnsl_hidden_nolink_def (xdr_ypresp_all, GLIBC_2_0) |
196 | |
197 | bool_t |
198 | xdr_ypresp_xfr (XDR *xdrs, ypresp_xfr *objp) |
199 | { |
200 | if (!xdr_u_int (xdrs: xdrs, up: &objp->transid)) |
201 | return FALSE; |
202 | return xdr_ypxfrstat (xdrs, objp: &objp->xfrstat); |
203 | } |
204 | libnsl_hidden_nolink_def (xdr_ypresp_xfr, GLIBC_2_0) |
205 | |
206 | bool_t |
207 | xdr_ypmaplist (XDR *xdrs, ypmaplist *objp) |
208 | { |
209 | if (!xdr_mapname (xdrs, objp: &objp->map)) |
210 | return FALSE; |
211 | /* Prevent gcc warning about alias violation. */ |
212 | char **tp = (void *) &objp->next; |
213 | return xdr_pointer (xdrs: xdrs, objpp: tp, obj_size: sizeof (ypmaplist), xdr_obj: (xdrproc_t) xdr_ypmaplist); |
214 | } |
215 | libnsl_hidden_nolink_def (xdr_ypmaplist, GLIBC_2_0) |
216 | |
217 | bool_t |
218 | xdr_ypresp_maplist (XDR *xdrs, ypresp_maplist *objp) |
219 | { |
220 | if (!xdr_ypstat (xdrs, objp: &objp->stat)) |
221 | return FALSE; |
222 | /* Prevent gcc warning about alias violation. */ |
223 | char **tp = (void *) &objp->maps; |
224 | return xdr_pointer (xdrs: xdrs, objpp: tp, obj_size: sizeof (ypmaplist), xdr_obj: (xdrproc_t) xdr_ypmaplist); |
225 | } |
226 | libnsl_hidden_nolink_def (xdr_ypresp_maplist, GLIBC_2_0) |
227 | |
228 | bool_t |
229 | xdr_yppush_status (XDR *xdrs, yppush_status *objp) |
230 | { |
231 | return xdr_enum (xdrs: xdrs, ep: (enum_t *) objp); |
232 | } |
233 | libnsl_hidden_nolink_def (xdr_yppush_status, GLIBC_2_0) |
234 | |
235 | bool_t |
236 | xdr_yppushresp_xfr (XDR *xdrs, yppushresp_xfr *objp) |
237 | { |
238 | if (!xdr_u_int (xdrs: xdrs, up: &objp->transid)) |
239 | return FALSE; |
240 | return xdr_yppush_status (xdrs, objp: &objp->status); |
241 | } |
242 | libnsl_hidden_nolink_def (xdr_yppushresp_xfr, GLIBC_2_0) |
243 | |
244 | bool_t |
245 | xdr_ypbind_resptype (XDR *xdrs, ypbind_resptype *objp) |
246 | { |
247 | return xdr_enum (xdrs: xdrs, ep: (enum_t *) objp); |
248 | } |
249 | libnsl_hidden_nolink_def (xdr_ypbind_resptype, GLIBC_2_0) |
250 | |
251 | bool_t |
252 | xdr_ypbind_binding (XDR *xdrs, ypbind_binding *objp) |
253 | { |
254 | if (!xdr_opaque (xdrs: xdrs, cp: objp->ypbind_binding_addr, cnt: 4)) |
255 | return FALSE; |
256 | return xdr_opaque (xdrs: xdrs, cp: objp->ypbind_binding_port, cnt: 2); |
257 | } |
258 | libnsl_hidden_nolink_def (xdr_ypbind_binding, GLIBC_2_0) |
259 | |
260 | bool_t |
261 | xdr_ypbind_resp (XDR *xdrs, ypbind_resp *objp) |
262 | { |
263 | if (!xdr_ypbind_resptype (xdrs, objp: &objp->ypbind_status)) |
264 | return FALSE; |
265 | switch (objp->ypbind_status) |
266 | { |
267 | case YPBIND_FAIL_VAL: |
268 | return xdr_u_int (xdrs: xdrs, up: &objp->ypbind_resp_u.ypbind_error); |
269 | case YPBIND_SUCC_VAL: |
270 | return xdr_ypbind_binding (xdrs, objp: &objp->ypbind_resp_u.ypbind_bindinfo); |
271 | } |
272 | return FALSE; |
273 | } |
274 | libnsl_hidden_nolink_def (xdr_ypbind_resp, GLIBC_2_0) |
275 | |
276 | bool_t |
277 | xdr_ypbind_setdom (XDR *xdrs, ypbind_setdom *objp) |
278 | { |
279 | if (!xdr_domainname (xdrs, objp: &objp->ypsetdom_domain)) |
280 | return FALSE; |
281 | if (!xdr_ypbind_binding (xdrs, objp: &objp->ypsetdom_binding)) |
282 | return FALSE; |
283 | return xdr_u_int (xdrs: xdrs, up: &objp->ypsetdom_vers); |
284 | } |
285 | libnsl_hidden_nolink_def (xdr_ypbind_setdom, GLIBC_2_0) |
286 | |
287 | bool_t |
288 | xdr_ypall(XDR *xdrs, struct ypall_callback *incallback) |
289 | { |
290 | struct ypresp_key_val out; |
291 | char key[YPMAXRECORD], val[YPMAXRECORD]; |
292 | |
293 | /* |
294 | * Set up key/val struct to be used during the transaction. |
295 | */ |
296 | memset(s: &out, c: 0, n: sizeof out); |
297 | out.key.keydat_val = key; |
298 | out.key.keydat_len = sizeof(key); |
299 | out.val.valdat_val = val; |
300 | out.val.valdat_len = sizeof(val); |
301 | |
302 | for (;;) { |
303 | bool_t more, status; |
304 | |
305 | /* Values pending? */ |
306 | if (!xdr_bool(xdrs: xdrs, bp: &more)) |
307 | return FALSE; /* can't tell! */ |
308 | if (!more) |
309 | return TRUE; /* no more */ |
310 | |
311 | /* Transfer key/value pair. */ |
312 | status = xdr_ypresp_key_val(xdrs, objp: &out); |
313 | |
314 | /* |
315 | * If we succeeded, call the callback function. |
316 | * The callback will return TRUE when it wants |
317 | * no more values. If we fail, indicate the |
318 | * error. |
319 | */ |
320 | if (status) { |
321 | if ((*incallback->foreach)(out.stat, |
322 | (char *)out.key.keydat_val, out.key.keydat_len, |
323 | (char *)out.val.valdat_val, out.val.valdat_len, |
324 | incallback->data)) |
325 | return TRUE; |
326 | } else |
327 | return FALSE; |
328 | } |
329 | } |
330 | libnsl_hidden_nolink_def (xdr_ypall, GLIBC_2_2) |
331 | |