1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Portions of this software have been released under the following terms: 31 * 32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. 33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY 34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION 35 * 36 * To anyone who acknowledges that this file is provided "AS IS" 37 * without any express or implied warranty: 38 * permission to use, copy, modify, and distribute this file for any 39 * purpose is hereby granted without fee, provided that the above 40 * copyright notices and this notice appears in all source code copies, 41 * and that none of the names of Open Software Foundation, Inc., Hewlett- 42 * Packard Company or Digital Equipment Corporation be used 43 * in advertising or publicity pertaining to distribution of the software 44 * without specific, written prior permission. Neither Open Software 45 * Foundation, Inc., Hewlett-Packard Company nor Digital 46 * Equipment Corporation makes any representations about the suitability 47 * of this software for any purpose. 48 * 49 * Copyright (c) 2007, Novell, Inc. All rights reserved. 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in the 58 * documentation and/or other materials provided with the distribution. 59 * 3. Neither the name of Novell Inc. nor the names of its contributors 60 * may be used to endorse or promote products derived from this 61 * this software without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY 67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 73 * 74 * @APPLE_LICENSE_HEADER_END@ 75 */ 76 77/* 78** 79** NAME 80** 81** cs_s_eval.c 82** 83** FACILITY: 84** 85** Remote Procedure Call (RPC) evaluation setup function 86** 87** ABSTRACT: 88** 89** PUBLIC RPC 90** by 91** 92*/ 93 94#include <commonp.h> /* RPC common definitions */ 95#include <com.h> /* RPC communication definitons */ 96#include <comp.h> /* Private Communication Services */ 97#include <ns.h> /* Private NS defs for other RPC components */ 98#include <nsp.h> /* Private defs for Naming Service component */ 99#include <nsentry.h> /* Externals for NS Entry sub-component */ 100#include <dce/rpc.h> 101 102#include <cs_s.h> /* Private defs for code set interoperability */ 103#include <dce/dce_cf.h> /* Access to the backing store library */ 104 105 106/* 107**++ 108** ROUTINE NAME: rpc_ns_import_ctx_add_eval 109** 110** SCOPE: PUBLIC - declared in rpc.idl 111** 112** DESCRIPTION: 113** 114** Add an evaluation routine (function pointer) to a list of an import context. 115** If the list does not exit, allocate the list first. 116** 117** INPUTS: 118** 119** function type Evaluation function type. Currently, only types 120** supported are 'RPC_EVAL_TYPE_CODESETS' and 121** 'RPC_CUSTOM_EVAL_TYPE_CODESETS'. 122** 123** args Arguments to the custom evaluation routine. 124** For OSF supplied evaluation routine, this is NULL. 125** 126** evaluation function 127** Function pointer to an evaluation routine. 128** Currently, only evaluation expected is code set 129** compatibility evaluations. 130** 131** free function 132** Function pointer to a free routine. This is 133** a user supplied routine, which is called when 134** 'function type' is 'rpc_custom_eval_type_codesets'. 135** 136** 137** 138** INPUT/OUPUTS: 139** 140** import context Import context which is used for finding a server. 141** This is allocated by the previous 142** rpc_ns_binding_import_begin() call. 'eval_routines' 143** (which is type rpc_ns_handle_t) will hold the 144** information about evaluation routines. 145** 146** OUTPUTS: 147** 148** status The result of the operation. One of: 149** rpc_s_ok 150** rpc_s_invalid_ns_handle 151** rpc_s_no_memory 152** Status from rpc_rgy_get_codesets() 153** 154** IMPLICIT INPUTS: none 155** 156** IMPLICIT OUTPUTS: none 157** 158** FUNCTION VALUE: void 159** 160** SIDE EFFECTS: none 161** 162**-- 163*/ 164 165PUBLIC 166void rpc_ns_import_ctx_add_eval 167( 168 rpc_ns_handle_t *import_ctx, 169 unsigned32 func_type, 170 void *args, 171 void (*eval_func)(handle_t binding_h, void *args, void **cntx), 172 void (*cs_free_func)(void *cntx), 173 error_status_t *status 174) 175{ 176 rpc_cs_eval_func_p_t eval_func_rep; 177 rpc_cs_eval_list_p_t eval_list_p; 178 rpc_import_rep_p_t import_p; 179 rpc_lkup_rep_p_t lookup_p; 180 unsigned_char_p_t client_codesets_file_p; 181 rpc_codeset_mgmt_p_t client_codeset_p; 182 183 CODING_ERROR (status); 184 RPC_NS_VERIFY_INIT(); 185 186 import_p = (rpc_import_rep_p_t)*import_ctx; 187 lookup_p = (rpc_lkup_rep_p_t)import_p->lookup_context; 188 189 if (lookup_p == NULL) 190 { 191 *status = rpc_s_invalid_ns_handle; 192 return; 193 } 194 195 switch (func_type) 196 { 197 case RPC_EVAL_TYPE_CODESETS: 198 case RPC_CUSTOM_EVAL_TYPE_CODESETS: 199 200 /* 201 * Check if import func context is already allocated 202 */ 203 204 if (lookup_p->eval_routines == NULL) /* no list exists yet */ 205 { 206 /* 207 * Allocate the new import func context. 208 */ 209 RPC_MEM_ALLOC ( 210 eval_func_rep, 211 rpc_cs_eval_func_p_t, 212 sizeof (rpc_cs_eval_func_t), 213 RPC_C_MEM_FUNC, 214 RPC_C_MEM_WAITOK); 215 216 /* 217 * Allocate a list 218 */ 219 RPC_MEM_ALLOC ( 220 eval_list_p, 221 rpc_cs_eval_list_p_t, 222 sizeof (rpc_cs_eval_list_t), 223 RPC_C_MEM_LIST, 224 RPC_C_MEM_WAITOK); 225 226 /* 227 * set up the contents of the stack 228 */ 229 eval_list_p->type = func_type; 230 eval_list_p->eval_func = eval_func; 231 eval_list_p->cs_free_func = cs_free_func; 232 eval_list_p->cntx = NULL; 233 eval_list_p->next = NULL; 234 235 /* Get client's supported code sets */ 236 rpc_rgy_get_codesets ( &client_codeset_p, 237 status ); 238 239 if (*status != rpc_s_ok) 240 { 241 RPC_MEM_FREE (eval_func_rep, RPC_C_MEM_FUNC); 242 RPC_MEM_FREE (eval_list_p, RPC_C_MEM_LIST); 243 return; 244 } 245 eval_list_p->args = (void *)client_codeset_p; 246 247 /* 248 * set the list to import func context 249 */ 250 eval_func_rep->list = eval_list_p; 251 252 eval_func_rep->num = 1; 253 254 /* 255 * set the list into import context 256 */ 257 lookup_p->eval_routines = (rpc_ns_handle_t)eval_func_rep; 258 259 } 260 else 261 { 262 263 /* 264 * Allocate a list 265 */ 266 RPC_MEM_ALLOC ( 267 eval_list_p, 268 rpc_cs_eval_list_p_t, 269 sizeof (rpc_cs_eval_list_t), 270 RPC_C_MEM_LIST, 271 RPC_C_MEM_WAITOK); 272 273 /* 274 * set up the contents of the stack 275 */ 276 eval_list_p->type = func_type; 277 eval_list_p->eval_func = eval_func; 278 eval_list_p->cs_free_func = cs_free_func; 279 eval_list_p->cntx = NULL; 280 eval_list_p->next = NULL; 281 282 /* Get client's supported code sets */ 283 rpc_rgy_get_codesets ( &client_codeset_p, 284 status ); 285 286 if (*status != rpc_s_ok) 287 { 288 RPC_MEM_FREE (eval_func_rep, RPC_C_MEM_FUNC); 289 RPC_MEM_FREE (eval_list_p, RPC_C_MEM_LIST); 290 return; 291 } 292 eval_list_p->args = (rpc_ns_handle_t *)client_codeset_p; 293 294 /* 295 * set the stack pointer to newly allocated stack 296 */ 297 eval_func_rep = (rpc_cs_eval_func_p_t)lookup_p->eval_routines; 298 eval_func_rep->list->next = eval_list_p; 299 300 eval_func_rep->num += 1; 301 } 302 *status = rpc_s_ok; 303 return; 304 305 default: 306 ; 307 308 } 309} 310 311 312/* 313**++ 314** ROUTINE NAME: rpc_cs_eval_with_universal 315** 316** SCOPE: PUBLIC - declared in rpc.idl 317** 318** DESCRIPTION: 319** 320** An evaluation routine to evaluate client's and server's supported 321** code sets. If no code sets match, Universal code set will be used 322** for the wire communication. 323** 324** INPUTS: 325** 326** binding_h 327** RPC binding_handle. 328** 329** args Actually points to 'rpc_cs_codeset_i14y_data_p' 330** data type. 331** 332** INPUT/OUPUTS: 333** 334** cntx Points to 'rpc_cs_codeset_i14y_data_p' data type, 335** and keep track of function execution. 336** 337** OUTPUTS: none 338** 339** IMPLICIT INPUTS: none 340** 341** IMPLICIT OUTPUTS: none 342** 343** FUNCTION VALUE: void 344** 345** SIDE EFFECTS: none 346** 347**-- 348*/ 349 350PUBLIC 351void rpc_cs_eval_with_universal 352( 353 handle_t binding_h, 354 void *args, 355 void **cntx 356) 357{ 358 rpc_cs_codeset_i14y_data_p i14y_data_p; 359 rpc_cs_codeset_i14y_data_p cntx_i14y_data_p; 360 rpc_cs_method_eval_p_t method_p; 361 rpc_ns_handle_t inq_context; 362 unsigned_char_p_t client_codesets_file; 363 unsigned_char_p_t ns_name_p; 364 int i,j; 365 int model_found; 366 int smir_true; 367 int cmir_true; 368 long i_code; 369 int i_max_bytes; 370 error_status_t temp_status; 371 372 i14y_data_p = (rpc_cs_codeset_i14y_data_p)args; 373 374 if (i14y_data_p->cleanup) 375 { 376 cntx_i14y_data_p = (rpc_cs_codeset_i14y_data_p)*cntx; 377 cntx_i14y_data_p->status = rpc_s_ok; 378 return; 379 } 380 381 method_p = i14y_data_p->method_p; 382 if (cntx == NULL) 383 { 384 return; 385 } 386 else 387 cntx_i14y_data_p = (rpc_cs_codeset_i14y_data_p)*cntx; 388 389 /* 390 * Get the client's supported code sets. 391 */ 392 if (method_p->client == NULL) 393 { 394 rpc_rgy_get_codesets ( 395 &method_p->client, 396 &cntx_i14y_data_p->status); 397 398 if (cntx_i14y_data_p->status != rpc_s_ok) 399 return; 400 } 401 402 /* 403 ** Get the server's supported code sets from NSI. 404 */ 405 406 ns_name_p = i14y_data_p->ns_name; 407 408 rpc_ns_mgmt_read_codesets ( 409 rpc_c_ns_syntax_default, 410 ns_name_p, 411 &method_p->server, 412 &cntx_i14y_data_p->status); 413 414 if (cntx_i14y_data_p->status != rpc_s_ok) 415 { 416 rpc_ns_mgmt_free_codesets( &method_p->client, &temp_status); 417 return; 418 } 419 420 /* 421 * Start evaluation 422 */ 423 if (method_p->client->codesets[0].c_set 424 == method_p->server->codesets[0].c_set) 425 { 426 /* 427 * Both client and server are using the same code set 428 */ 429 method_p->method = RPC_EVAL_NO_CONVERSION; 430 method_p->tags.stag = method_p->client->codesets[0].c_set; 431 method_p->tags.drtag = method_p->server->codesets[0].c_set; 432 } 433 else 434 { 435 /* 436 * We check character set compatibility first. 437 */ 438 rpc_cs_char_set_compat_check ( 439 method_p->client->codesets[0].c_set, 440 method_p->server->codesets[0].c_set, 441 &cntx_i14y_data_p->status); 442 443 if (cntx_i14y_data_p->status != rpc_s_ok) 444 { 445 /* 446 * Character set for client and server didn't match. 447 * Mass of data loss could result, so we quit the 448 * evaluation here. 449 */ 450 rpc_ns_mgmt_free_codesets( &method_p->server, &temp_status); 451 return; 452 } 453 else 454 { 455 smir_true = cmir_true = model_found = 0; 456 457 for (i = 1; i <= method_p->server->count; i++) 458 { 459 if (model_found) 460 break; 461 462 if (method_p->client->codesets[0].c_set 463 == method_p->server->codesets[i].c_set) 464 { 465 smir_true = 1; 466 model_found = 1; 467 } 468 469 if (method_p->server->codesets[0].c_set 470 == method_p->client->codesets[i].c_set) 471 { 472 cmir_true = 1; 473 model_found = 1; 474 } 475 } 476 477 if (model_found) 478 { 479 if (smir_true && cmir_true) 480 { 481 /* RMIR model works */ 482 method_p->method = RPC_EVAL_RMIR_MODEL; 483 method_p->tags.stag 484 = method_p->client->codesets[0].c_set; 485 method_p->tags.drtag 486 = method_p->server->codesets[0].c_set; 487 method_p->tags.stag_max_bytes 488 = method_p->client->codesets[0].c_max_bytes; 489 method_p->tags.client_tag 490 = method_p->client->codesets[0].c_set; 491 method_p->tags.client_max_bytes 492 = method_p->client->codesets[0].c_max_bytes; 493 } 494 else if (smir_true) 495 { 496 /* SMIR model */ 497 method_p->method = RPC_EVAL_SMIR_MODEL; 498 method_p->tags.stag 499 = method_p->client->codesets[0].c_set; 500 method_p->tags.drtag 501 = method_p->client->codesets[0].c_set; 502 method_p->tags.stag_max_bytes 503 = method_p->client->codesets[0].c_max_bytes; 504 method_p->tags.client_tag 505 = method_p->client->codesets[0].c_set; 506 method_p->tags.client_max_bytes 507 = method_p->client->codesets[0].c_max_bytes; 508 } 509 else 510 { 511 /* CMIR model */ 512 method_p->method = RPC_EVAL_CMIR_MODEL; 513 method_p->tags.stag 514 = method_p->server->codesets[0].c_set; 515 method_p->tags.drtag 516 = method_p->server->codesets[0].c_set; 517 method_p->tags.stag_max_bytes 518 = method_p->server->codesets[0].c_max_bytes; 519 method_p->tags.client_tag 520 = method_p->client->codesets[0].c_set; 521 method_p->tags.client_max_bytes 522 = method_p->client->codesets[0].c_max_bytes; 523 } 524 } 525 else 526 { 527 /* 528 * We try to find the intermediate code set 529 */ 530 method_p->tags.client_tag 531 = method_p->client->codesets[0].c_set; 532 method_p->tags.client_max_bytes 533 = method_p->client->codesets[0].c_max_bytes; 534 535 for (i = 1; i <= method_p->client->count; i++) 536 { 537 if (model_found) 538 break; 539 for (j = 1; j <= method_p->server->count; j++) 540 { 541 if (method_p->client->codesets[i].c_set 542 == method_p->server->codesets[j].c_set) 543 { 544 i_code = method_p->client->codesets[i].c_set; 545 i_max_bytes = method_p->client->codesets[i].c_max_bytes; 546 method_p->tags.stag_max_bytes 547 = method_p->client->codesets[i].c_max_bytes; 548 model_found = 1; 549 break; 550 } 551 } 552 } 553 if (model_found) 554 { 555 method_p->method = RPC_EVAL_INTERMEDIATE_MODEL; 556 method_p->tags.stag = i_code; 557 method_p->tags.drtag = i_code; 558 } 559 else 560 { 561 /* 562 * We use UNIVERSAL code set 563 */ 564 method_p->method = RPC_EVAL_UNIVERSAL_MODEL; 565 method_p->tags.stag = UCS2_L2; 566 method_p->tags.drtag = UCS2_L2; 567 method_p->tags.client_tag 568 = method_p->client->codesets[0].c_set; 569 method_p->tags.client_max_bytes 570 = method_p->client->codesets[0].c_max_bytes; 571 rpc_rgy_get_max_bytes ( 572 UCS2_L2, 573 &method_p->tags.stag_max_bytes, 574 &cntx_i14y_data_p->status 575 ); 576 if (cntx_i14y_data_p->status != rpc_s_ok) 577 { 578 rpc_ns_mgmt_free_codesets( &method_p->server, &temp_status); 579 return; 580 } 581 } 582 } 583 } 584 } 585 586 method_p->fixed = ndr_true; 587 cntx_i14y_data_p->status = rpc_s_ok; 588 rpc_ns_mgmt_free_codesets( &method_p->server, &temp_status); 589 return; 590} 591 592 593/* 594**++ 595** ROUTINE NAME: rpc_cs_eval_without_universal 596** 597** SCOPE: PUBLIC - declared in rpc.idl 598** 599** DESCRIPTION: 600** 601** An evaluation routine to evaluate client's and server's supported 602** code sets. If no code sets match it fails. Universal code set will 603** not be used for the wire communication. 604** 605** INPUTS: 606** 607** binding_h 608** RPC binding_handle. 609** 610** args Actually points to 'rpc_cs_codeset_i14y_data_p' 611** data type. 612** 613** INPUT/OUPUTS: 614** 615** cntx Points to 'rpc_cs_codeset_i14y_data_p' data type, 616** and keep track of function execution. 617** 618** OUTPUTS: none 619** 620** IMPLICIT INPUTS: none 621** 622** IMPLICIT OUTPUTS: none 623** 624** FUNCTION VALUE: void 625** 626** SIDE EFFECTS: none 627** 628**-- 629*/ 630 631PUBLIC 632void rpc_cs_eval_without_universal 633( 634 handle_t binding_h, 635 void *args, 636 void **cntx 637) 638{ 639 rpc_cs_codeset_i14y_data_p i14y_data_p; 640 rpc_cs_codeset_i14y_data_p cntx_i14y_data_p; 641 rpc_cs_method_eval_p_t method_p; 642 rpc_ns_handle_t inq_context; 643 unsigned_char_p_t ns_name_p; 644 unsigned_char_p_t client_codesets_file; 645 int i,j; 646 int model_found; 647 int smir_true; 648 int cmir_true; 649 long i_code; 650 int i_max_bytes; 651 error_status_t temp_status; 652 653 i14y_data_p = (rpc_cs_codeset_i14y_data_p)args; 654 655 if (i14y_data_p->cleanup) 656 { 657 cntx_i14y_data_p = (rpc_cs_codeset_i14y_data_p)*cntx; 658 cntx_i14y_data_p->status = rpc_s_ok; 659 return; 660 } 661 662 method_p = i14y_data_p->method_p; 663 if (cntx == NULL) 664 { 665 return; 666 } 667 else 668 cntx_i14y_data_p = (rpc_cs_codeset_i14y_data_p)*cntx; 669 670 /* 671 * Get the client's supported code sets if it is not set. 672 method_p->client = (rpc_codeset_mgmt_p_t)i14y_data_p->args; 673 */ 674 if (method_p->client == NULL) 675 { 676 rpc_rgy_get_codesets ( 677 &method_p->client, 678 &cntx_i14y_data_p->status); 679 680 if (cntx_i14y_data_p->status != rpc_s_ok) 681 return; 682 } 683 684 /* 685 ** Get the server's supported code sets from NSI. 686 */ 687 688 ns_name_p = i14y_data_p->ns_name; 689 690 rpc_ns_mgmt_read_codesets ( 691 rpc_c_ns_syntax_default, 692 ns_name_p, 693 &method_p->server, 694 &cntx_i14y_data_p->status); 695 696 if (cntx_i14y_data_p->status != rpc_s_ok) 697 { 698 rpc_ns_mgmt_free_codesets( &method_p->client, &temp_status); 699 return; 700 } 701 702 /* 703 * Start evaluation 704 */ 705 if (method_p->client->codesets[0].c_set 706 == method_p->server->codesets[0].c_set) 707 { 708 /* 709 * Both client and server are using the same code set 710 */ 711 method_p->method = RPC_EVAL_NO_CONVERSION; 712 method_p->tags.stag = method_p->client->codesets[0].c_set; 713 method_p->tags.drtag = method_p->server->codesets[0].c_set; 714 } 715 else 716 { 717 /* 718 * We check character set compatibility first. 719 */ 720 rpc_cs_char_set_compat_check ( 721 method_p->client->codesets[0].c_set, 722 method_p->server->codesets[0].c_set, 723 &cntx_i14y_data_p->status); 724 725 if (cntx_i14y_data_p->status != rpc_s_ok) 726 { 727 /* 728 * Character set for client and server didn't match. 729 * Mass of data loss could result, so we quit the 730 * evaluation here. 731 */ 732 rpc_ns_mgmt_free_codesets( &method_p->server, &temp_status); 733 return; 734 } 735 else 736 { 737 smir_true = cmir_true = model_found = 0; 738 739 for (i = 1; i <= method_p->server->count; i++) 740 { 741 if (model_found) 742 break; 743 744 if (method_p->client->codesets[0].c_set 745 == method_p->server->codesets[i].c_set) 746 { 747 smir_true = 1; 748 model_found = 1; 749 } 750 751 if (method_p->server->codesets[0].c_set 752 == method_p->client->codesets[i].c_set) 753 { 754 cmir_true = 1; 755 model_found = 1; 756 } 757 } 758 759 if (model_found) 760 { 761 if (smir_true && cmir_true) 762 { 763 /* RMIR model works */ 764 method_p->method = RPC_EVAL_RMIR_MODEL; 765 method_p->tags.stag = method_p->client->codesets[0].c_set; 766 method_p->tags.drtag = method_p->server->codesets[0].c_set; 767 method_p->tags.stag_max_bytes 768 = method_p->client->codesets[0].c_max_bytes; 769 method_p->tags.client_tag 770 = method_p->client->codesets[0].c_set; 771 method_p->tags.client_max_bytes 772 = method_p->client->codesets[0].c_max_bytes; 773 } 774 else if (smir_true) 775 { 776 /* SMIR model */ 777 method_p->method = RPC_EVAL_SMIR_MODEL; 778 method_p->tags.stag = method_p->client->codesets[0].c_set; 779 method_p->tags.drtag = method_p->client->codesets[0].c_set; 780 method_p->tags.stag_max_bytes 781 = method_p->client->codesets[0].c_max_bytes; 782 method_p->tags.client_tag 783 = method_p->client->codesets[0].c_set; 784 method_p->tags.client_max_bytes 785 = method_p->client->codesets[0].c_max_bytes; 786 } 787 else 788 { 789 /* CMIR model */ 790 method_p->method = RPC_EVAL_CMIR_MODEL; 791 method_p->tags.stag = method_p->server->codesets[0].c_set; 792 method_p->tags.drtag = method_p->server->codesets[0].c_set; 793 method_p->tags.stag_max_bytes 794 = method_p->server->codesets[0].c_max_bytes; 795 method_p->tags.client_tag 796 = method_p->client->codesets[0].c_set; 797 method_p->tags.client_max_bytes 798 = method_p->client->codesets[0].c_max_bytes; 799 } 800 } 801 else 802 { 803 /* 804 * We try to find intermediate code set 805 */ 806 method_p->tags.client_tag 807 = method_p->client->codesets[0].c_set; 808 method_p->tags.client_max_bytes 809 = method_p->client->codesets[0].c_max_bytes; 810 811 for (i = 1; i <= method_p->client->count; i++) 812 { 813 if (model_found) 814 break; 815 for (j = 1; j <= method_p->server->count; j++) 816 { 817 if (method_p->client->codesets[i].c_set 818 == method_p->server->codesets[j].c_set) 819 { 820 i_code = method_p->client->codesets[i].c_set; 821 i_max_bytes = method_p->client->codesets[i].c_max_bytes; 822 823 method_p->tags.stag_max_bytes 824 = method_p->client->codesets[i].c_max_bytes; 825 model_found = 1; 826 break; 827 } 828 } 829 } 830 if (model_found) 831 { 832 method_p->method 833 = RPC_EVAL_INTERMEDIATE_MODEL; 834 method_p->tags.stag = i_code; 835 method_p->tags.drtag = i_code; 836 } 837 else 838 { 839 /* 840 * We do not use UNIVERSAL code set 841 */ 842 cntx_i14y_data_p->status 843 = rpc_s_ss_no_compat_codeset; 844 rpc_ns_mgmt_free_codesets( &method_p->server, &temp_status); 845 return; 846 } 847 } 848 } 849 } 850 851 method_p->fixed = ndr_true; 852 cntx_i14y_data_p->status = rpc_s_ok; 853 rpc_ns_mgmt_free_codesets( &method_p->server, &temp_status); 854 return; 855} 856 857 858/* 859**++ 860** ROUTINE NAME: rpc_cs_char_set_compat_check 861** 862** SCOPE: PUBLIC - declared in rpc.idl 863** 864** DESCRIPTION: 865** 866** Evaluate the character set compatibility between client and server. 867** Character set matching logic prevents the massive data loss when client 868** and server are connected. 869** 870** INPUTS: 871** 872** client_codeset OSF code set registry value for client's current 873** code set. 874** 875** server_codeset OSF code set registry value for server's current 876** code set. 877** 878** INPUT/OUPUTS: none 879** 880** OUTPUTS: 881** 882** status The result of the operation. One of: 883** rpc_s_ok 884** rpc_s_ss_no_compat_charsets 885** Status from dce_cs_loc_to_rgy() 886** 887** IMPLICIT INPUTS: none 888** 889** IMPLICIT OUTPUTS: none 890** 891** FUNCTION VALUE: void 892** 893** SIDE EFFECTS: none 894** 895**-- 896*/ 897 898PUBLIC 899void rpc_cs_char_set_compat_check 900( 901 unsigned32 client_codeset, 902 unsigned32 server_codeset, 903 error_status_t *status 904) 905{ 906 unsigned_char_t *client_code_set_name; 907 unsigned16 client_char_sets_number; 908 unsigned16 *client_char_sets_value; 909 unsigned_char_t *server_code_set_name; 910 unsigned16 server_char_sets_number; 911 unsigned16 *server_char_sets_value; 912 913 dce_cs_rgy_to_loc ( 914 client_codeset, 915 &client_code_set_name, 916 &client_char_sets_number, 917 &client_char_sets_value, 918 status ); 919 920 if (*status != dce_cs_c_ok) 921 return; 922 923 dce_cs_rgy_to_loc ( 924 server_codeset, 925 &server_code_set_name, 926 &server_char_sets_number, 927 &server_char_sets_value, 928 status ); 929 930 if (*status != dce_cs_c_ok) 931 return; 932 933 if (client_char_sets_number == 1 && server_char_sets_number == 1) 934 { 935 if (*client_char_sets_value == *server_char_sets_value) 936 *status = rpc_s_ok; 937 else 938 *status = rpc_s_ss_no_compat_charsets; 939 } 940 else 941 { 942 int match = 0; 943 unsigned16 server_number_save; 944 unsigned16 *server_value_save; 945 946 server_number_save = server_char_sets_number; 947 server_value_save = server_char_sets_value; 948 949 while (client_char_sets_number--) 950 { 951 while (server_char_sets_number--) 952 { 953 if (*client_char_sets_value 954 == *server_char_sets_value++) 955 match++; 956 } 957 server_char_sets_number = server_number_save; 958 server_char_sets_value = server_value_save; 959 client_char_sets_value++; 960 } 961 if (match >= 2) 962 *status = rpc_s_ok; 963 else 964 *status = rpc_s_ss_no_compat_charsets; 965 } 966 967 return; 968} 969 970 971/* 972**++ 973** ROUTINE NAME: rpc_cs_binding_set_method 974** 975** SCOPE: PRIVATE - declared in cs_s.h 976** 977** DESCRIPTION: 978** 979** An evaluation routine to evaluate client's and server's supported 980** code sets. If no code sets match, Universal code set will be used 981** for the wire communication. 982** 983** INPUTS: 984** method_p pointer to the method structure. 985** 986** 987** INPUT/OUPUTS: 988** 989** h rpc binding handle. rpc_binding_rep_t will be 990** modified to rpc_binding_eval_t data structure. 991** 992** OUTPUTS: 993** 994** status The result of the operation. One of: 995** rpc_s_ok 996** rpc_s_no_memory 997** 998** IMPLICIT INPUTS: none 999** 1000** IMPLICIT OUTPUTS: none 1001** 1002** FUNCTION VALUE: void 1003** 1004** SIDE EFFECTS: none 1005** 1006**-- 1007*/ 1008PRIVATE 1009void rpc_cs_binding_set_method 1010( 1011 rpc_binding_handle_t *h, 1012 rpc_cs_method_eval_p_t method_p, 1013 error_status_t *status 1014) 1015{ 1016 rpc_cs_method_eval_p_t bind_method; 1017 rpc_binding_rep_p_t bind_eval_p; 1018 1019 bind_eval_p = (rpc_binding_rep_p_t)*h; 1020 bind_method = &bind_eval_p->cs_eval.tagged_union.method_key; 1021 1022 bind_eval_p->cs_eval.key = RPC_CS_EVAL_METHOD; 1023 bind_method->method = method_p->method; 1024 bind_method->tags.stag = method_p->tags.stag; 1025 bind_method->tags.drtag = method_p->tags.drtag; 1026 bind_method->tags.stag_max_bytes = method_p->tags.stag_max_bytes; 1027 bind_method->tags.client_tag = method_p->tags.client_tag; 1028 bind_method->tags.client_max_bytes = method_p->tags.client_max_bytes; 1029 bind_method->fixed = method_p->fixed; 1030 bind_method->cs_stub_eval_func = NULL; 1031 bind_method->tags.type_handle = NULL; 1032 bind_method->server = method_p->server; 1033 bind_method->client = method_p->client; 1034 1035 bind_eval_p->extended_bind_flag = RPC_C_BH_EXTENDED_CODESETS; 1036 *status = rpc_s_ok; 1037 return; 1038} 1039 1040 1041/* 1042**++ 1043** ROUTINE NAME: rpc_cs_binding_set_tags 1044** 1045** SCOPE: PUBLIC - declared in rpc.idl 1046** 1047** DESCRIPTION: 1048** 1049** An evaluation routine to evaluate client's and server's supported 1050** code sets. If no code sets match, Universal code set will be used 1051** for the wire communication. 1052** 1053** INPUTS: 1054** stag sending tag 1055** 1056** drtag desired receving tag 1057** 1058** INPUT/OUPUTS: 1059** 1060** h rpc binding handle. rpc_binding_rep_t will be 1061** modified to rpc_binding_eval_t data structure. 1062** 1063** OUTPUTS: 1064** 1065** status The result of the operation. One of: 1066** rpc_s_ok 1067** Status from rpc_rgy_get_codesets() 1068** 1069** IMPLICIT INPUTS: none 1070** 1071** IMPLICIT OUTPUTS: none 1072** 1073** FUNCTION VALUE: void 1074** 1075** SIDE EFFECTS: none 1076** 1077**-- 1078*/ 1079 1080PUBLIC 1081void rpc_cs_binding_set_tags 1082( 1083 rpc_binding_handle_t *h, 1084 unsigned32 stag, 1085 unsigned32 drtag, 1086 unsigned16 stag_max_bytes, 1087 error_status_t *status 1088) 1089{ 1090 rpc_cs_tags_eval_p_t bind_tags; 1091 rpc_binding_rep_p_t bind_eval_p; 1092 rpc_codeset_mgmt_p_t client; 1093 1094 bind_eval_p = (rpc_binding_rep_p_t)*h; 1095 bind_tags = &bind_eval_p->cs_eval.tagged_union.tags_key; 1096 1097 bind_eval_p->cs_eval.key = RPC_CS_EVAL_TAGS; 1098 bind_tags->stag = stag; 1099 bind_tags->drtag = drtag; 1100 if (stag_max_bytes != 0) 1101 bind_tags->stag_max_bytes = stag_max_bytes; 1102 else 1103 bind_tags->stag_max_bytes = 0; 1104 /* 1105 * Get the client's supported code sets 1106 */ 1107 rpc_rgy_get_codesets ( 1108 &client, 1109 status ); 1110 1111 if (*status != rpc_s_ok) 1112 return; 1113 1114 bind_tags->client_tag = client->codesets[0].c_set; 1115 bind_tags->client_max_bytes = client->codesets[0].c_max_bytes; 1116 1117 bind_tags->type_handle = NULL; 1118 1119 bind_eval_p->extended_bind_flag = RPC_C_BH_EXTENDED_CODESETS; 1120 1121 *status = rpc_s_ok; 1122 return; 1123} 1124 1125 1126/* 1127**++ 1128** ROUTINE NAME: rpc_cs_binding_set_eval 1129** 1130** SCOPE: PUBLIC - declared in rpc.idl 1131** 1132** DESCRIPTION: 1133** 1134** Add in-stub evaluation routine to a binding handle. 1135** When this method is used, every single RPC call will perform code set 1136** compatibility evaluation, which can be a big impact to RPC call performance. 1137** 1138** INPUTS: 1139** cs_stub_eval_func pointer to an in-stub evaluation routine. 1140** 1141** INPUT/OUPUTS: 1142** 1143** h rpc binding handle. rpc_binding_rep_t will be 1144** modified to rpc_binding_eval_t data structure. 1145** 1146** OUTPUTS: 1147** 1148** status The result of the operation. One of: 1149** rpc_s_ok 1150** 1151** IMPLICIT INPUTS: none 1152** 1153** IMPLICIT OUTPUTS: none 1154** 1155** FUNCTION VALUE: void 1156** 1157** SIDE EFFECTS: none 1158** 1159**-- 1160*/ 1161 1162PUBLIC 1163void rpc_cs_binding_set_eval 1164( 1165 rpc_binding_handle_t *h, 1166 void (*cs_stub_eval_func)(unsigned32 *p_stag, unsigned32 *p_drtag, error_status_t *status), 1167 error_status_t *status 1168) 1169{ 1170 rpc_cs_method_eval_p_t bind_method; 1171 rpc_binding_rep_p_t bind_eval_p; 1172 1173 bind_eval_p = (rpc_binding_rep_p_t)*h; 1174 bind_method = &bind_eval_p->cs_eval.tagged_union.method_key; 1175 1176 bind_eval_p->cs_eval.key = RPC_CS_EVAL_METHOD; 1177 bind_method->fixed = ndr_false; 1178 bind_method->cs_stub_eval_func = cs_stub_eval_func; 1179 bind_method->tags.type_handle = NULL; 1180 1181 bind_eval_p->extended_bind_flag = RPC_C_BH_IN_STUB_EVALUATION; 1182 *status = rpc_s_ok; 1183 return; 1184} 1185