Print this page
1575 untangle libmlrpc ... (libmlrpc)
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/smbsrv/libmlrpc/common/ndr_client.c
+++ new/usr/src/lib/libmlrpc/common/ndr_client.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 + *
25 + * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
24 26 */
25 27
26 28 #include <sys/errno.h>
27 29 #include <string.h>
28 30 #include <strings.h>
29 31
30 -#include <smbsrv/libsmb.h>
31 -#include <smbsrv/libmlrpc.h>
32 +#include <libmlrpc.h>
32 33
33 34 #define NDR_DEFAULT_FRAGSZ 8192
34 35 #define NDR_MULTI_FRAGSZ (60 * 1024)
35 36
36 37 static void ndr_clnt_init_hdr(ndr_client_t *, ndr_xa_t *);
37 38 static int ndr_clnt_get_frags(ndr_client_t *, ndr_xa_t *);
38 39 static int ndr_clnt_get_frag(ndr_client_t *, ndr_xa_t *, ndr_common_header_t *);
39 40
40 41 int
41 -ndr_clnt_bind(ndr_client_t *clnt, const char *service_name,
42 +ndr_clnt_bind(ndr_client_t *clnt, ndr_service_t *msvc,
42 43 ndr_binding_t **ret_binding_p)
43 44 {
44 - ndr_service_t *msvc;
45 45 ndr_binding_t *mbind;
46 46 ndr_xa_t mxa;
47 47 ndr_bind_hdr_t *bhdr;
48 48 ndr_p_cont_elem_t *pce;
49 49 ndr_bind_ack_hdr_t *bahdr;
50 50 ndr_p_result_t *pre;
51 51 int rc;
52 52
53 53 bzero(&mxa, sizeof (mxa));
54 54
55 - msvc = ndr_svc_lookup_name(service_name);
56 - if (msvc == NULL)
57 - return (NDR_DRC_FAULT_API_SERVICE_INVALID);
58 -
59 55 mxa.binding_list = clnt->binding_list;
60 56 if ((mbind = ndr_svc_new_binding(&mxa)) == NULL)
61 57 return (NDR_DRC_FAULT_API_BIND_NO_SLOTS);
62 58
63 59 ndr_clnt_init_hdr(clnt, &mxa);
64 60
65 61 bhdr = &mxa.send_hdr.bind_hdr;
66 62 bhdr->common_hdr.ptype = NDR_PTYPE_BIND;
67 63 bhdr->common_hdr.frag_length = sizeof (*bhdr);
68 64 bhdr->max_xmit_frag = NDR_DEFAULT_FRAGSZ;
69 65 bhdr->max_recv_frag = NDR_DEFAULT_FRAGSZ;
70 66 bhdr->assoc_group_id = 0;
71 67 bhdr->p_context_elem.n_context_elem = 1;
72 68
73 69 /* Assign presentation context id */
74 70 pce = &bhdr->p_context_elem.p_cont_elem[0];
75 71 pce->p_cont_id = clnt->next_p_cont_id++;
76 72 pce->n_transfer_syn = 1;
77 73
78 74 /* Set up UUIDs and versions from the service */
79 75 pce->abstract_syntax.if_version = msvc->abstract_syntax_version;
80 76 rc = ndr_uuid_parse(msvc->abstract_syntax_uuid,
81 77 &pce->abstract_syntax.if_uuid);
82 78 if (rc != 0)
83 79 return (NDR_DRC_FAULT_API_SERVICE_INVALID);
84 80
85 81 pce->transfer_syntaxes[0].if_version = msvc->transfer_syntax_version;
86 82 rc = ndr_uuid_parse(msvc->transfer_syntax_uuid,
87 83 &pce->transfer_syntaxes[0].if_uuid);
88 84 if (rc != 0)
89 85 return (NDR_DRC_FAULT_API_SERVICE_INVALID);
90 86
91 87 /* Format and exchange the PDU */
92 88
93 89 if ((*clnt->xa_init)(clnt, &mxa) < 0)
94 90 return (NDR_DRC_FAULT_OUT_OF_MEMORY);
95 91
96 92 rc = ndr_encode_pdu_hdr(&mxa);
97 93 if (NDR_DRC_IS_FAULT(rc))
98 94 goto fault_exit;
99 95
100 96 if ((*clnt->xa_exchange)(clnt, &mxa) < 0) {
101 97 rc = NDR_DRC_FAULT_SEND_FAILED;
102 98 goto fault_exit;
103 99 }
104 100
105 101 rc = ndr_decode_pdu_hdr(&mxa);
106 102 if (NDR_DRC_IS_FAULT(rc))
107 103 goto fault_exit;
108 104
109 105 /* done with buffers */
110 106 (*clnt->xa_destruct)(clnt, &mxa);
111 107
112 108 bahdr = &mxa.recv_hdr.bind_ack_hdr;
113 109
114 110 if (mxa.ptype != NDR_PTYPE_BIND_ACK)
115 111 return (NDR_DRC_FAULT_RECEIVED_MALFORMED);
116 112
117 113 if (bahdr->p_result_list.n_results != 1)
118 114 return (NDR_DRC_FAULT_RECEIVED_MALFORMED);
119 115
120 116 pre = &bahdr->p_result_list.p_results[0];
121 117
122 118 if (pre->result != NDR_PCDR_ACCEPTANCE)
123 119 return (NDR_DRC_FAULT_RECEIVED_MALFORMED);
124 120
125 121 mbind->p_cont_id = pce->p_cont_id;
126 122 mbind->which_side = NDR_BIND_SIDE_CLIENT;
127 123 mbind->clnt = clnt;
128 124 mbind->service = msvc;
129 125 mbind->instance_specific = 0;
130 126
131 127 *ret_binding_p = mbind;
132 128 return (NDR_DRC_OK);
↓ open down ↓ |
64 lines elided |
↑ open up ↑ |
133 129
134 130 fault_exit:
135 131 (*clnt->xa_destruct)(clnt, &mxa);
136 132 return (rc);
137 133 }
138 134
139 135 int
140 136 ndr_clnt_call(ndr_binding_t *mbind, int opnum, void *params)
141 137 {
142 138 ndr_client_t *clnt = mbind->clnt;
143 - ndr_service_t *msvc = mbind->service;
144 139 ndr_xa_t mxa;
145 140 ndr_request_hdr_t *reqhdr;
146 141 ndr_common_header_t *rsphdr;
147 142 unsigned long recv_pdu_scan_offset;
148 143 int rc;
149 144
150 - if (ndr_svc_lookup_name(msvc->name) == NULL)
151 - return (NDR_DRC_FAULT_API_SERVICE_INVALID);
152 -
153 145 bzero(&mxa, sizeof (mxa));
154 146 mxa.ptype = NDR_PTYPE_REQUEST;
155 147 mxa.opnum = opnum;
156 148 mxa.binding = mbind;
157 149
158 150 ndr_clnt_init_hdr(clnt, &mxa);
159 151
160 152 reqhdr = &mxa.send_hdr.request_hdr;
161 153 reqhdr->common_hdr.ptype = NDR_PTYPE_REQUEST;
162 154 reqhdr->p_cont_id = mbind->p_cont_id;
163 155 reqhdr->opnum = opnum;
164 156
165 157 rc = (*clnt->xa_init)(clnt, &mxa);
166 158 if (NDR_DRC_IS_FAULT(rc))
167 159 return (rc);
168 160
169 161 /* Reserve room for hdr */
170 162 mxa.send_nds.pdu_scan_offset = sizeof (*reqhdr);
171 163
172 164 rc = ndr_encode_call(&mxa, params);
173 165 if (!NDR_DRC_IS_OK(rc))
174 166 goto fault_exit;
175 167
176 168 mxa.send_nds.pdu_scan_offset = 0;
177 169
178 170 /*
179 171 * Now we have the PDU size, we need to set up the
180 172 * frag_length and calculate the alloc_hint.
181 173 */
182 174 mxa.send_hdr.common_hdr.frag_length = mxa.send_nds.pdu_size;
183 175 reqhdr->alloc_hint = mxa.send_nds.pdu_size -
184 176 sizeof (ndr_request_hdr_t);
185 177
186 178 rc = ndr_encode_pdu_hdr(&mxa);
187 179 if (NDR_DRC_IS_FAULT(rc))
188 180 goto fault_exit;
189 181
190 182 rc = (*clnt->xa_exchange)(clnt, &mxa);
191 183 if (NDR_DRC_IS_FAULT(rc))
192 184 goto fault_exit;
193 185
194 186 rc = ndr_decode_pdu_hdr(&mxa);
195 187 if (NDR_DRC_IS_FAULT(rc))
196 188 goto fault_exit;
197 189
198 190 if (mxa.ptype != NDR_PTYPE_RESPONSE) {
199 191 rc = NDR_DRC_FAULT_RECEIVED_MALFORMED;
200 192 goto fault_exit;
201 193 }
202 194
203 195 rsphdr = &mxa.recv_hdr.common_hdr;
204 196
205 197 if (!NDR_IS_LAST_FRAG(rsphdr->pfc_flags)) {
206 198 /*
207 199 * This is a multi-fragment response.
208 200 * Preserve the current scan offset while getting
209 201 * fragments so that we can continue afterward
210 202 * as if we had received the entire response as
211 203 * a single PDU.
212 204 */
213 205 (void) NDS_GROW_PDU(&mxa.recv_nds, NDR_MULTI_FRAGSZ, NULL);
214 206
215 207 recv_pdu_scan_offset = mxa.recv_nds.pdu_scan_offset;
216 208 mxa.recv_nds.pdu_scan_offset = rsphdr->frag_length;
217 209 mxa.recv_nds.pdu_size = rsphdr->frag_length;
218 210
219 211 if (ndr_clnt_get_frags(clnt, &mxa) < 0) {
220 212 rc = NDR_DRC_FAULT_RECEIVED_MALFORMED;
221 213 goto fault_exit;
222 214 }
223 215
224 216 mxa.recv_nds.pdu_scan_offset = recv_pdu_scan_offset;
225 217 }
226 218
227 219 rc = ndr_decode_return(&mxa, params);
228 220 if (NDR_DRC_IS_FAULT(rc))
229 221 goto fault_exit;
230 222
231 223 (*clnt->xa_preserve)(clnt, &mxa);
232 224 (*clnt->xa_destruct)(clnt, &mxa);
233 225 return (NDR_DRC_OK);
234 226
235 227 fault_exit:
236 228 (*clnt->xa_destruct)(clnt, &mxa);
237 229 return (rc);
238 230 }
239 231
240 232 void
241 233 ndr_clnt_free_heap(ndr_client_t *clnt)
242 234 {
243 235 (*clnt->xa_release)(clnt);
244 236 }
245 237
246 238 static void
247 239 ndr_clnt_init_hdr(ndr_client_t *clnt, ndr_xa_t *mxa)
248 240 {
249 241 ndr_common_header_t *hdr = &mxa->send_hdr.common_hdr;
250 242
251 243 hdr->rpc_vers = 5;
252 244 hdr->rpc_vers_minor = 0;
253 245 hdr->pfc_flags = NDR_PFC_FIRST_FRAG + NDR_PFC_LAST_FRAG;
254 246 hdr->packed_drep.intg_char_rep = NDR_REPLAB_CHAR_ASCII;
255 247 #ifndef _BIG_ENDIAN
256 248 hdr->packed_drep.intg_char_rep |= NDR_REPLAB_INTG_LITTLE_ENDIAN;
257 249 #endif
258 250 /* hdr->frag_length */
259 251 hdr->auth_length = 0;
260 252 hdr->call_id = clnt->next_call_id++;
261 253 }
262 254
263 255 /*
264 256 * ndr_clnt_get_frags
265 257 *
266 258 * A DCE RPC message that is larger than a single fragment is transmitted
267 259 * as a series of fragments: 5280 bytes for Windows NT and 4280 bytes for
268 260 * both Windows 2000 and 2003.
269 261 *
270 262 * Collect RPC fragments and append them to the receive stream buffer.
271 263 * Each received fragment has a header, which we need to remove as we
272 264 * build the full RPC PDU. The scan offset is used to track frag headers.
273 265 */
274 266 static int
275 267 ndr_clnt_get_frags(ndr_client_t *clnt, ndr_xa_t *mxa)
276 268 {
277 269 ndr_stream_t *nds = &mxa->recv_nds;
278 270 ndr_common_header_t hdr;
279 271 int frag_size;
280 272 int last_frag;
281 273
282 274 do {
283 275 if (ndr_clnt_get_frag(clnt, mxa, &hdr) < 0) {
284 276 nds_show_state(nds);
285 277 return (-1);
286 278 }
287 279
288 280 last_frag = NDR_IS_LAST_FRAG(hdr.pfc_flags);
289 281 frag_size = hdr.frag_length;
290 282
291 283 if (frag_size > (nds->pdu_size - nds->pdu_scan_offset)) {
292 284 nds_show_state(nds);
293 285 return (-1);
294 286 }
295 287
296 288 ndr_remove_frag_hdr(nds);
297 289 nds->pdu_scan_offset += frag_size - NDR_RSP_HDR_SIZE;
298 290 } while (!last_frag);
299 291
300 292 return (0);
301 293 }
302 294
303 295 /*
304 296 * Read the next RPC fragment. The xa_read() calls correspond to SmbReadX
305 297 * requests. Note that there is no correspondence between SmbReadX buffering
306 298 * and DCE RPC fragment alignment.
307 299 */
308 300 static int
309 301 ndr_clnt_get_frag(ndr_client_t *clnt, ndr_xa_t *mxa, ndr_common_header_t *hdr)
310 302 {
311 303 ndr_stream_t *nds = &mxa->recv_nds;
312 304 unsigned long available;
313 305 int nbytes = 0;
314 306
315 307 available = nds->pdu_size - nds->pdu_scan_offset;
316 308
317 309 while (available < NDR_RSP_HDR_SIZE) {
318 310 if ((nbytes += (*clnt->xa_read)(clnt, mxa)) <= 0)
319 311 return (-1);
320 312 available += nbytes;
321 313 }
322 314
323 315 ndr_decode_frag_hdr(nds, hdr);
324 316 ndr_show_hdr(hdr);
325 317
326 318 while (available < hdr->frag_length) {
327 319 if ((nbytes = (*clnt->xa_read)(clnt, mxa)) <= 0)
328 320 return (-1);
329 321 available += nbytes;
330 322 }
331 323
332 324 return (nbytes);
333 325 }
↓ open down ↓ |
171 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX