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** cnrcvr.c 82** 83** FACILITY: 84** 85** Remote Procedure Call (RPC) 86** 87** ABSTRACT: 88** 89** The NCA Connection Protocol Service's Receiver Service. 90** 91** 92*/ 93 94#include <commonp.h> /* Common declarations for all RPC runtime */ 95#include <com.h> /* Common communications services */ 96#include <ndrp.h> /* System (machine architecture) dependent definitions */ 97#include <cnp.h> /* NCA Connection private declarations */ 98#include <cnnet.h> /* NCA Connection network service */ 99#include <cnsm.h> /* NCA Connection state machine service */ 100#include <cnassm.h> /* NCA Connection association state machine */ 101#include <cnclsm.h> /* NCA Connection call state machine */ 102#include <cnpkt.h> /* NCA Connection packet encoding */ 103#include <cnfbuf.h> /* NCA Connection fragment buffer service */ 104#include <cnassoc.h> /* NCA Connection association service */ 105#include <cnrcvr.h> /* NCA Connection receiver service */ 106#include <comauth.h> /* Externals for Auth. Services sub-component */ 107#include <cncall.h> /* NCA connection call service */ 108#include <comcthd.h> /* Externals for call thread services component */ 109#include <cncthd.h> /* NCA Connection call executor service */ 110 111/******************************************************************************/ 112/* 113 * Internal variables 114 */ 115/******************************************************************************/ 116/* 117 * P A C K E T _ I N F O _ T A B L E 118 * 119 * Call and Association packet event information table. 120 * This table is indexed by packet type. 121 */ 122 123typedef struct 124{ 125 unsigned8 class; 126 unsigned8 event; 127} rpc_cn_pkt_info_t, *rpc_cn_pkt_info_p_t; 128 129#define CALL_CLASS_PKT 0 /* packet is a call related packet */ 130#define ASSOC_CLASS_PKT 1 /* packet is an association related packet */ 131#define DGRAM_CLASS_PKT 2 /* packet is a datagram related packet (illegal) */ 132 133#ifndef RPC_C_DGRAM_TYPE_PKT 134#define RPC_C_DGRAM_TYPE_PKT 0xff /* this is an arbitrary value */ 135#endif 136 137INTERNAL rpc_cn_pkt_info_t packet_info_table[] = 138{ 139 { CALL_CLASS_PKT, RPC_C_CALL_RPC_IND }, /* 00 - request */ 140 { DGRAM_CLASS_PKT, RPC_C_DGRAM_TYPE_PKT }, /* 01 - ping */ 141 { CALL_CLASS_PKT, RPC_C_CALL_RPC_CONF }, /* 02 - response */ 142 { CALL_CLASS_PKT, RPC_C_CALL_FAULT }, /* 03 - fault */ 143 { DGRAM_CLASS_PKT, RPC_C_DGRAM_TYPE_PKT }, /* 04 - working */ 144 { DGRAM_CLASS_PKT, RPC_C_DGRAM_TYPE_PKT }, /* 05 - nocall */ 145 { DGRAM_CLASS_PKT, RPC_C_DGRAM_TYPE_PKT }, /* 06 - reject */ 146 { DGRAM_CLASS_PKT, RPC_C_DGRAM_TYPE_PKT }, /* 07 - ack */ 147 { DGRAM_CLASS_PKT, RPC_C_DGRAM_TYPE_PKT }, /* 08 - quit */ 148 { DGRAM_CLASS_PKT, RPC_C_DGRAM_TYPE_PKT }, /* 09 - fack */ 149 { DGRAM_CLASS_PKT, RPC_C_DGRAM_TYPE_PKT }, /* 10 - quack */ 150 { ASSOC_CLASS_PKT, RPC_C_ASSOC_IND }, /* 11 - bind */ 151 { ASSOC_CLASS_PKT, RPC_C_ASSOC_ACCEPT_CONF }, /* 12 - bind ack */ 152 { ASSOC_CLASS_PKT, RPC_C_ASSOC_REJECT_CONF }, /* 13 - bind nak */ 153 { ASSOC_CLASS_PKT, RPC_C_ASSOC_ALTER_CONTEXT_IND }, /* 14 - alter context */ 154 { ASSOC_CLASS_PKT, RPC_C_ASSOC_ALTER_CONTEXT_CONF },/* 15 - alter context response */ 155 { ASSOC_CLASS_PKT, RPC_C_ASSOC_AUTH3_IND }, /* 16 - auth3 */ 156 { ASSOC_CLASS_PKT, RPC_C_ASSOC_SHUTDOWN_IND }, /* 17 - shutdown */ 157 { CALL_CLASS_PKT, RPC_C_CALL_REMOTE_ALERT_IND }, /* 18 - remote alert */ 158 { CALL_CLASS_PKT, RPC_C_CALL_ORPHANED } /* 19 - orphaned */ 159}; 160 161 162/******************************************************************************/ 163/* 164 * Internal routine declarations 165 */ 166/******************************************************************************/ 167/* 168 * R E C E I V E _ D I S P A T C H 169 */ 170INTERNAL void receive_dispatch ( 171 rpc_cn_assoc_p_t /*assoc*/ 172 ); 173 174/* 175 * R E C E I V E _ P A C K E T 176 */ 177INTERNAL void receive_packet ( 178 rpc_cn_assoc_p_t /*assoc*/, 179 rpc_cn_fragbuf_p_t * /*fragbuf_p*/, 180 rpc_cn_fragbuf_p_t * /*ovf_fragbuf_p*/, 181 unsigned32 * /*st*/ 182 ); 183 184/* 185 * R P C _ C N _ S E N D _ F A U L T 186 * 187 * This macro will cause a fault PDU to be sent back to the client 188 * and will terminate the RPC. 189 */ 190#define RPC_CN_SEND_FAULT(call_r, st) \ 191{\ 192 rpc_binding_rep_t *binding_r; \ 193\ 194 rpc__cn_call_reject ((rpc_call_rep_p_t) call_r, st);\ 195 binding_r = (rpc_binding_rep_t *) (call_r)->binding_rep; \ 196 RPC_CN_UNLOCK (); \ 197 rpc__cn_call_end ((rpc_call_rep_p_t *) &(call_r), &st); \ 198 RPC_CN_LOCK (); \ 199 RPC_BINDING_RELEASE (&binding_r, \ 200 &st); \ 201} 202 203 204/* 205**++ 206** ROUTINE NAME: rpc__cn_network_receiver 207** 208** SCOPE: PRIVATE - declared in cnrcvr.h 209** 210** DESCRIPTION: 211** 212** This routine constitutes the top-level receiver thread (both client and 213** server) and is invoked by "thread create" in "association 214** lookaside alloc" routine to process incoming packets. 215** 216** It receives packets on an association until terminated by a 217** cancel, the connection breaks or a resource exhaustion problem 218** is hit. 219** 220** INPUTS: 221** 222** assoc pointer to an association control block 223** 224** INPUTS/OUTPUTS: none 225** 226** OUTPUTS: none 227** 228** IMPLICIT INPUTS: none 229** 230** IMPLICIT OUTPUTS: none 231** 232** FUNCTION VALUE: none 233** 234** SIDE EFFECTS: Posts events to the association and call state machines. 235** 236**-- 237*/ 238 239PRIVATE void rpc__cn_network_receiver 240( 241 rpc_cn_assoc_p_t assoc 242) 243{ 244 rpc_socket_error_t serr; 245 volatile boolean done = false; 246 247 //DO_NOT_CLOBBER(done); 248 249 RPC_CN_DBG_RTN_PRINTF (rpc__cn_network_receiver); 250 251 RPC_DBG_PRINTF (rpc_e_dbg_threads, RPC_C_CN_DBG_THREADS, 252 ("####### assoc->%p Entered receiver thread \n", assoc)); 253 254 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 255 ("CN: assoc->%p call_rep->none Receiver thread starting...\n", 256 assoc)); 257 258 /* 259 * Loop until a cancel is sent to this thread. 260 */ 261 while (!done && !assoc->cn_ctlblk.exit_rcvr) 262 { 263 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 264 ("CN: assoc->%p call_rep->none Entering receive loop...\n", 265 assoc)); 266 267 /* 268 * Lock the global connection mutex to prevent other threads 269 * from running while the receiver thread is. This mutex will be 270 * released when we block (either explicitly or implicitly by a 271 * condition variable wait). 272 */ 273 /* XXX is there any advantage to using a per-association mutex? */ 274 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 275 ("CN: Attemping to lock global mutex\n")); 276 RPC_CN_LOCK (); 277 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 278 ("CN: Global mutex locked\n")); 279 280 /* 281 * Wait for a session/transport connection to be established. 282 */ 283 DCETHREAD_TRY 284 { 285 while (assoc->cn_ctlblk.cn_state != RPC_C_CN_OPEN) 286 { 287 /* 288 * XXX this check is to mask a race condition where the 289 * assoc appears to be freed under us. Of course, we are 290 * in this test relying on the fact that it is zeroed 291 * upon deallocation and the memory isn't overwritten 292 * which is completely bogus. 293 * 294 * Not sure why this is happening as rpc__cn_assoc_acb_free() 295 * should be waiting to join this thread. 296 */ 297 if (assoc->cn_ctlblk.cn_rcvr_thread_id == (dcethread*)0) 298 { 299 done = true; 300 break; 301 } 302 assoc->cn_ctlblk.cn_rcvr_waiters++; 303 RPC_DBG_PRINTF (rpc_e_dbg_threads, RPC_C_CN_DBG_THREADS, 304 ("####### assoc->%p Waiting for new connection \n", assoc)); 305 DCETHREAD_TRY 306 { 307 RPC_COND_WAIT (assoc->cn_ctlblk.cn_rcvr_cond, 308 rpc_g_global_mutex); 309 } 310 DCETHREAD_CATCH(dcethread_interrupt_e) 311 { 312 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 313 ("CN: assoc->%p rcvr free'ed by acb_free\n", 314 assoc)); 315 done = true; 316 } 317 DCETHREAD_CATCH_ALL(THIS_CATCH) 318 { 319 /* 320 * rpc_m_unexpected_exc 321 * "(%s) Unexpected exception was raised" 322 */ 323 rpc_dce_svc_printf ( 324 __FILE__, __LINE__, 325 "%s", 326 rpc_svc_recv, 327 svc_c_sev_fatal | svc_c_action_abort, 328 rpc_m_unexpected_exc, 329 "rpc__cn_network_receiver" ); 330 } 331 DCETHREAD_ENDTRY 332 333 assoc->cn_ctlblk.cn_rcvr_waiters--; 334 335 if (done == true) 336 break; 337 RPC_DBG_PRINTF (rpc_e_dbg_threads, RPC_C_CN_DBG_THREADS, 338 ("####### assoc->%p Got a new connection \n", assoc)); 339 } 340 341 if (done) 342 { 343 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 344 ("CN: assoc->%p call_rep->none Receiver awake ... free'ed\n", 345 assoc)); 346 } 347 else 348 { 349 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 350 ("CN: assoc->%p call_rep->none Receiver awake ... Connection established\n", 351 assoc)); 352 353 /* 354 * Increment the association control block's reference count since we 355 * are now using it and receive packets as long as the 356 * connection is open. 357 */ 358 RPC_CN_ASSOC_ACB_INC_REF (assoc); 359 360 /* 361 * A connection has been established. 362 */ 363 RPC_CN_STATS_INCR (connections); 364 rpc__server_incr_clients (); 365 DCETHREAD_TRY 366 { 367 receive_dispatch (assoc); 368 } 369 DCETHREAD_CATCH(dcethread_interrupt_e) 370 { 371 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 372("CN: call_rep->%p assoc->%p desc->%p receiver canceled, caught in rpc__cn_network_receiver()\n", 373 assoc->call_rep, 374 assoc, 375 assoc->cn_ctlblk.cn_sock)); 376 } 377 DCETHREAD_CATCH_ALL(THIS_CATCH) 378 { 379 /* 380 * rpc_m_unexpected_exc 381 * "(%s) Unexpected exception was raised" 382 */ 383 rpc_dce_svc_printf ( 384 __FILE__, __LINE__, 385 "%s", 386 rpc_svc_recv, 387 svc_c_sev_fatal | svc_c_action_abort, 388 rpc_m_unexpected_exc, 389 "rpc__cn_network_receiver" ); 390 } 391 DCETHREAD_ENDTRY 392 393 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 394 ("CN: assoc->%p call_rep->none No longer receiving...Close socket\n", 395 assoc)); 396 /* 397 * Either the connection was broken or another 398 * thread has sent us a cancel indicating the 399 * connection should be broken. In either case 400 * close the socket and set the connection state 401 * to closed. 402 */ 403 rpc__server_decr_clients(); 404 RPC_CN_STATS_INCR (closed_connections); 405 serr = RPC_SOCKET_CLOSE (assoc->cn_ctlblk.cn_sock); /* must not be a cancellation point */ 406 if (RPC_SOCKET_IS_ERR(serr)) 407 { 408 /* 409 * The socket close failed. 410 */ 411 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_ERRORS, 412("(rpc__cn_network_receiver) assoc->%p desc->%p RPC_SOCKET_CLOSE failed, error = %d\n", 413 assoc, 414 assoc->cn_ctlblk.cn_sock, 415 RPC_SOCKET_ETOI(serr))); 416 } 417 418 assoc->cn_ctlblk.cn_state = RPC_C_CN_CLOSED; 419 420 /* 421 * Remove any pending cancel on this assoc. Otherwise, it's 422 * possible that the receiver thread will see this cancel after 423 * the next call begins. 424 */ 425 DCETHREAD_TRY 426 { 427 dcethread_checkinterrupt(); 428 } 429 DCETHREAD_CATCH_ALL(THIS_CATCH) 430 { 431 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 432 ("CN: assoc->%p rcvr cancel found at acb_dealloc\n", 433 assoc)); 434 } 435 DCETHREAD_ENDTRY 436 437 /* 438 * Deallocate the association control block. 439 */ 440 rpc__cn_assoc_acb_dealloc (assoc); 441 442 /* 443 * Check if rpc__cn_assoc_acb_free() posted the cancel. 444 */ 445 DCETHREAD_TRY 446 { 447 dcethread_checkinterrupt(); 448 } 449 DCETHREAD_CATCH(dcethread_interrupt_e) 450 { 451 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 452 ("CN: assoc->%p rcvr free'ed by acb_dealloc\n", 453 assoc)); 454 done = true; 455 } 456 DCETHREAD_CATCH_ALL(THIS_CATCH) 457 { 458 /* 459 * rpc_m_unexpected_exc 460 * "(%s) Unexpected exception was raised" 461 */ 462 rpc_dce_svc_printf ( 463 __FILE__, __LINE__, 464 "%s", 465 rpc_svc_recv, 466 svc_c_sev_fatal | svc_c_action_abort, 467 rpc_m_unexpected_exc, 468 "rpc__cn_network_receiver" ); 469 } 470 DCETHREAD_ENDTRY 471 } 472 } 473 DCETHREAD_CATCH(dcethread_interrupt_e) 474 { 475 /* 476 * rpc_m_unexpected_exc 477 * "(%s) Unexpected exception was raised" 478 */ 479 rpc_dce_svc_printf ( 480 __FILE__, __LINE__, 481 "%s", 482 rpc_svc_recv, 483 svc_c_sev_fatal | svc_c_action_abort, 484 rpc_m_unexpected_exc, 485 "rpc__cn_network_receiver" ); 486 } 487 DCETHREAD_CATCH_ALL(THIS_CATCH) 488 { 489 } 490 DCETHREAD_ENDTRY 491 492 /* 493 * Unlock the global connection mutex. 494 */ 495 DCETHREAD_TRY 496 { 497 RPC_CN_UNLOCK (); 498 } 499 DCETHREAD_CATCH_ALL(THIS_CATCH) 500 { 501 /* 502 * rpc_m_unexpected_exc 503 * "(%s) Unexpected exception was raised" 504 */ 505 rpc_dce_svc_printf ( 506 __FILE__, __LINE__, 507 "%s", 508 rpc_svc_recv, 509 svc_c_sev_fatal | svc_c_action_abort, 510 rpc_m_unexpected_exc, 511 "rpc__cn_network_receiver" ); 512 } 513 DCETHREAD_ENDTRY 514 } /* end while (!done && !assoc->cn_ctlblk.exit_rcvr) */ 515 516 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 517 ("CN: assoc->%p call_rep->none Receiver thread exiting...\n", 518 assoc)); 519} 520 521 522/******************************************************************************/ 523/* 524**++ 525** 526** ROUTINE NAME: receive_dispatch 527** 528** SCOPE: INTERNAL - declared locally 529** 530** DESCRIPTION: 531** 532** This is the low-level routine for receiving and dispatching packets. 533** 534** This routine is called once per "connection" and will continue to 535** receive and dispatch packets until some kind of error is encountered. 536** 537** INPUTS: 538** 539** assoc pointer to an association control block 540** 541** INPUTS/OUTPUTS: none 542** 543** OUTPUTS: none 544** 545** IMPLICIT INPUTS: none 546** 547** IMPLICIT OUTPUTS: none 548** 549** FUNCTION VALUE: none 550** 551** SIDE EFFECTS: none 552** 553**-- 554**/ 555 556INTERNAL void receive_dispatch 557( 558 rpc_cn_assoc_p_t assoc 559) 560{ 561 rpc_cn_fragbuf_p_t fragbuf_p; 562 rpc_cn_fragbuf_p_t ovf_fragbuf_p; 563 rpc_cn_call_rep_p_t call_r; 564 unsigned32 st; 565 rpc_cn_packet_p_t pktp; 566 unsigned8 ptype; 567 volatile boolean unpack_ints = false; 568 volatile unsigned32 i; 569 rpc_cn_syntax_t *pres_context; 570 unsigned32 auth_st; 571 rpc_cn_sec_context_t *sec_context; 572 boolean already_unpacked; 573 574 //DO_NOT_CLOBBER(unpack_ints); 575 //DO_NOT_CLOBBER(i); 576 577 /* 578 * Onetime (auto) initialization. 579 */ 580 st = rpc_s_ok; 581 fragbuf_p = NULL; 582 ovf_fragbuf_p = NULL; 583 call_r = NULL; 584 sec_context = NULL; 585 586 /* 587 * Main receive processing. 588 * 589 * We loop, receiving and processing packets until some kind of error 590 * is encountered. 591 */ 592 for (i = 0;; i++) 593 { 594 RPC_LOG_CN_PROCESS_PKT_NTR; 595 596 /* 597 * Increment the per-association security context next receive 598 * sequence number. 599 */ 600 assoc->security.assoc_next_rcv_seq = i; 601 602 /* 603 * Receive a packet from the network. 604 */ 605 DCETHREAD_TRY 606 { 607 receive_packet (assoc, &fragbuf_p, &ovf_fragbuf_p, &st); 608 } 609 DCETHREAD_CATCH(dcethread_interrupt_e) 610 { 611 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 612 ("CN: call_rep->%p assoc->%p desc->%p receiver canceled, caught in receive_dispatch()\n", 613 assoc->call_rep, 614 assoc, 615 assoc->cn_ctlblk.cn_sock)); 616 st = rpc_s_connection_closed; 617 } 618 DCETHREAD_CATCH_ALL(THIS_CATCH) 619 { 620 /* 621 * rpc_m_unexpected_exc 622 * "(%s) Unexpected exception was raised" 623 */ 624 rpc_dce_svc_printf ( 625 __FILE__, __LINE__, 626 "%s", 627 rpc_svc_recv, 628 svc_c_sev_fatal | svc_c_action_abort, 629 rpc_m_unexpected_exc, 630 "receive_dispatch" ); 631 } 632 DCETHREAD_ENDTRY 633 634 if (st != rpc_s_ok) 635 { 636 break; 637 } 638 639 already_unpacked = false; 640 641 /* 642 * Point to the packet header. 643 */ 644 assert(fragbuf_p != NULL); 645 pktp = (rpc_cn_packet_p_t) fragbuf_p->data_p; 646 647 /* 648 * Trace the incoming packet. 649 */ 650 RPC_CN_PKT_TRC (pktp); 651 RPC_CN_PKT_DUMP (pktp, fragbuf_p->data_size); 652 653 /* 654 * Keep some stats on the packets received. 655 */ 656 RPC_CN_STATS_INCR (pstats[RPC_CN_PKT_PTYPE (pktp)].rcvd); 657 RPC_CN_STATS_INCR (pkts_rcvd); 658 659 /* 660 * Setup some local variables. 661 */ 662 ptype = RPC_CN_PKT_PTYPE (pktp); 663 664 /* 665 * Make sure that we have a valid packet type. 666 * If not, we return an error, and the caller will close 667 * the connection. 668 */ 669 if (/* (ptype < 0) ||*/ (ptype > RPC_C_CN_PKT_MAX_TYPE) || 670 (packet_info_table[ptype].class == DGRAM_CLASS_PKT)) 671 { 672 st = rpc_s_protocol_error; 673 break; 674 } 675 676 /* 677 * Do some first packet only processing... 678 */ 679 if (i == 0) 680 { 681 /* 682 * Stash the remote NDR format away. Also create boolean 683 * to determine whether we have to bother unpacking the 684 * packet header. 685 */ 686 NDR_UNPACK_DREP (&(RPC_CN_ASSOC_NDR_FORMAT (assoc)), 687 RPC_CN_PKT_DREP (pktp)); 688 if ((NDR_DREP_INT_REP (RPC_CN_PKT_DREP (pktp)) != 689 NDR_LOCAL_INT_REP)) 690 { 691 unpack_ints = true; 692 } 693 else 694 { 695 unpack_ints = false; 696 } 697 } 698 else 699 { 700 /* 701 * Sanity check the major and minor version numbers. 702 * We let the association state machine do this check 703 * in the case BIND packets because the 704 * protocol calls for a call reject if the versions 705 * do not match at that point. 706 * For subsequent packets, we do the check here. 707 */ 708 if (!(ptype == RPC_C_CN_PKT_BIND) && 709 ((RPC_CN_PKT_VERS (pktp) != RPC_C_CN_PROTO_VERS) || 710 (RPC_CN_PKT_VERS_MINOR (pktp) > RPC_C_CN_PROTO_VERS_MINOR))) 711 { 712 st = rpc_s_rpc_prot_version_mismatch; 713 break; 714 } 715 } 716 717 auth_st = rpc_s_ok; 718 719 /* 720 * Determine whether the received PDU contains an 721 * authentication trailer. We don't care about byte 722 * ordering in the following macro invocation because 723 * the trailer length is compared with zero to determine 724 * whether or not the trailer is present. 725 */ 726 if (RPC_CN_PKT_AUTH_TLR_PRESENT (pktp)) 727 { 728 rpc_cn_auth_tlr_t *auth_tlr; 729 unsigned16 auth_len; 730 unsigned32 key_id; 731 unsigned16 frag_len; 732 733 /* 734 * If the pdu is a bind or alter-context pdu and we need to 735 * unpack the packet, save the raw form of the pdu so that 736 * the checksum can be computed correctly later. Do this by 737 * allocating a fragbuf and chaining it to the association 738 * control block, then copying the packet to it. The fragbuf 739 * will be deallocated in the state machine after invoking 740 * recv_check. 741 */ 742 if ((unpack_ints) && 743 ((ptype == RPC_C_CN_PKT_BIND) || 744 (ptype == RPC_C_CN_PKT_BIND_ACK) || 745 (ptype == RPC_C_CN_PKT_ALTER_CONTEXT) || 746 (ptype == RPC_C_CN_PKT_ALTER_CONTEXT_RESP) || 747 (ptype == RPC_C_CN_PKT_BIND_NAK) || 748 (ptype == RPC_C_CN_PKT_AUTH3))) 749 { 750 assoc->raw_packet_p = rpc__cn_fragbuf_alloc (true); 751 assoc->raw_packet_p->data_size = fragbuf_p->data_size; 752 memcpy (assoc->raw_packet_p->data_p, 753 fragbuf_p->data_p, 754 fragbuf_p->data_size); 755 } 756 757 /* 758 * Locate the authentication trailer in the PDU. 759 */ 760 auth_len = RPC_CN_PKT_AUTH_LEN (pktp); 761 if (unpack_ints) 762 { 763 /* no need to check end_of_pkt since its a copy of pkt data */ 764 SWAB_INPLACE_16 (auth_len); 765 } 766 767 auth_tlr = (rpc_cn_auth_tlr_t *) ((unsigned8 *)(pktp) + 768 fragbuf_p->data_size - 769 (auth_len + RPC_CN_PKT_SIZEOF_COM_AUTH_TLR)); 770 if ( ((unsigned8 *)(auth_tlr) < (unsigned8 *)(pktp)) || 771 ((unsigned8 *)(auth_tlr) > (unsigned8 *)(pktp) + fragbuf_p->data_size) || 772 ((unsigned8 *)(auth_tlr) + auth_len < (unsigned8 *)(pktp)) || 773 ((unsigned8 *)(auth_tlr) + auth_len > (unsigned8 *)(pktp) + fragbuf_p->data_size) ) 774 { 775 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 776 ("CN: call_rep->%p assoc->%p desc->%p invalid auth_tlr\n", 777 assoc->call_rep, 778 assoc, 779 assoc->cn_ctlblk.cn_sock)); 780 st = rpc_s_protocol_error; 781 break; 782 } 783 784 /* 785 * Find the appropriate security context element using the key ID 786 * contained in the auth_value part of the trailer. Also obtain 787 * the size of the credentials in the proper format. 788 */ 789 key_id = auth_tlr->key_id; 790 if (unpack_ints) 791 { 792 /* no need to check end_of_pkt since its a copy of pkt data */ 793 SWAB_INPLACE_32 (key_id); 794 } 795 796 if ((ptype != RPC_C_CN_PKT_BIND) && 797 (ptype != RPC_C_CN_PKT_ALTER_CONTEXT) && 798 (ptype != RPC_C_CN_PKT_BIND_ACK) && 799 (ptype != RPC_C_CN_PKT_ALTER_CONTEXT_RESP)) 800 { 801 rpc_authn_protocol_id_t authn_protocol = rpc_c_authn_none; 802 803 rpc__cn_assoc_sec_lkup_by_id (assoc, 804 key_id, 805 &sec_context, 806 &auth_st); 807 808 if (auth_st == rpc_s_ok) 809 { 810 authn_protocol = RPC_CN_AUTH_CVT_ID_WIRE_TO_API (auth_tlr->auth_type, &auth_st); 811 } 812 813 /* 814 * If a security context was located apply the 815 * per-packet security check. Any errors found in either 816 * locating the security context or during the check will 817 * be handled below according to the type of PDU received. 818 */ 819 if (auth_st == rpc_s_ok) 820 { 821 822 /* 823 * Note that cred_len is zero for all per-message 824 * packets. 825 */ 826 RPC_CN_AUTH_RECV_CHECK (authn_protocol, 827 &assoc->security, 828 sec_context, 829 (rpc_cn_common_hdr_t *)pktp, 830 fragbuf_p->data_size, 831 0, /* cred_len */ 832 auth_tlr, 833 unpack_ints, 834 &auth_st); 835 if (auth_st == rpc_s_ok) 836 { 837 /* 838 * Unpack the header part of the packet. 839 * This will make it easier to remove from the frag 840 * length any padding that was required to 841 * get the auth trailer 4-byte aligned at 842 * the sender. 843 * 844 * Since recv_check may have moved the auth_tlr, 845 * we get the pointer again. 846 */ 847 if (unpack_ints) 848 { 849 st = rpc__cn_unpack_hdr (pktp, fragbuf_p->data_size); 850 if (st != rpc_s_ok) 851 { 852 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 853 ("CN: call_rep->%p assoc->%p desc->%p auth rpc__cn_unpack_hdr failed\n", 854 assoc->call_rep, 855 assoc, 856 assoc->cn_ctlblk.cn_sock)); 857 break; 858 } 859 already_unpacked = true; 860 } 861 auth_len = RPC_CN_PKT_AUTH_LEN (pktp); 862 auth_tlr = (rpc_cn_auth_tlr_t *) ((unsigned8 *)(pktp) + 863 fragbuf_p->data_size - 864 (auth_len 865 + 866 RPC_CN_PKT_SIZEOF_COM_AUTH_TLR)); 867 if ( ((unsigned8 *)(auth_tlr) < (unsigned8 *)(pktp)) || 868 ((unsigned8 *)(auth_tlr) > (unsigned8 *)(pktp) + fragbuf_p->data_size) || 869 ((unsigned8 *)(auth_tlr) + auth_len < (unsigned8 *)(pktp)) || 870 ((unsigned8 *)(auth_tlr) + auth_len > (unsigned8 *)(pktp) + fragbuf_p->data_size) ) 871 { 872 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 873 ("CN: call_rep->%p assoc->%p desc->%p invalid auth_tlr in sec context\n", 874 assoc->call_rep, 875 assoc, 876 assoc->cn_ctlblk.cn_sock)); 877 st = rpc_s_protocol_error; 878 break; 879 } 880 881 frag_len = RPC_CN_PKT_FRAG_LEN (pktp); 882 if ( (frag_len > fragbuf_p->data_size) || (frag_len < auth_tlr->stub_pad_length) ) 883 { 884 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 885 ("CN: call_rep->%p assoc->%p desc->%p invalid frag_len\n", 886 assoc->call_rep, 887 assoc, 888 assoc->cn_ctlblk.cn_sock)); 889 st = rpc_s_protocol_error; 890 break; 891 } 892 893 frag_len -= auth_tlr->stub_pad_length; 894 RPC_CN_PKT_FRAG_LEN (pktp) = frag_len; 895 896 if (fragbuf_p->data_size < auth_tlr->stub_pad_length) 897 { 898 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 899 ("CN: call_rep->%p assoc->%p desc->%p invalid stub_pad_length\n", 900 assoc->call_rep, 901 assoc, 902 assoc->cn_ctlblk.cn_sock)); 903 st = rpc_s_protocol_error; 904 break; 905 } 906 fragbuf_p->data_size -= auth_tlr->stub_pad_length; 907 } 908 else 909 { 910 /* 911 * Handle any error which occured while performing 912 * either the recv check or key ID lookup. Errors which 913 * occur on the server for a call class PDU will be 914 * handled later by sending a fault PDU back. 915 * 916 * On the client side this error should just be 917 * handed back to the client thread waiting, if 918 * any. 919 * 920 * On the server side the error should be reflected 921 * back to the client on either a FAULT 922 * PDU if the recv_check failed on a call class 923 * PDU. If it failed on an assoc class PDU then the 924 * best we can probably do is close the association 925 * (it may be possible to respond with a BIND_NAK 926 * if the recv_check failed on a BIND). 927 */ 928 if (assoc->assoc_flags & RPC_C_CN_ASSOC_CLIENT) 929 { 930 (*fragbuf_p->fragbuf_dealloc)(fragbuf_p); 931 assert(sec_context != NULL); 932 sec_context->sec_status = auth_st; 933 RPC_CN_ASSOC_WAKEUP (assoc); 934 continue; 935 } 936 else 937 { 938 dce_error_string_t error_text; 939 int temp_status; 940 941 dce_error_inq_text(auth_st, error_text, &temp_status); 942 /* 943 * rpc_m_call_failed_s 944 * "%s on server failed: %s" 945 */ 946 rpc_dce_svc_printf ( 947 __FILE__, __LINE__, 948 "%s %x", 949 rpc_svc_recv, 950 svc_c_sev_error, 951 rpc_m_call_failed_s, 952 "RPC_CN_AUTH_RECV_CHECK", 953 error_text ); 954 955 if (packet_info_table[ptype].class == ASSOC_CLASS_PKT) 956 { 957 break; 958 } 959 } 960 } 961 } 962 } 963 } 964 else 965 { 966 if ((assoc->assoc_flags & RPC_C_CN_ASSOC_CLIENT) && 967 (ptype == RPC_C_CN_PKT_RESPONSE) && 968 (RPC_CN_PKT_AUTH_REQUIRED(assoc->call_rep->binding_rep->auth_info))) 969 { 970 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 971 ("CN: auth_info %p\n", assoc->call_rep->binding_rep->auth_info)); 972 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 973 ("CN: should not continue further with this PDU\n")); 974 (*fragbuf_p->fragbuf_dealloc)(fragbuf_p); 975 st = rpc_s_authn_level_mismatch; 976 RPC_CN_ASSOC_WAKEUP (assoc); 977 break; 978 } 979 } 980 981 /* 982 * Unpack the packet header, if necessary, and check to see 983 * if the packet type is within the legal range of values. 984 */ 985 if (unpack_ints && !already_unpacked) 986 { 987 st = rpc__cn_unpack_hdr (pktp, fragbuf_p->data_size); 988 if (st != rpc_s_ok) 989 { 990 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 991 ("CN: call_rep->%p assoc->%p desc->%p rpc__cn_unpack_hdr failed\n", 992 assoc->call_rep, 993 assoc, 994 assoc->cn_ctlblk.cn_sock)); 995 st = rpc_s_connection_closed; 996 break; 997 } 998 } 999 1000 /* 1001 * Finally, post the event to the appropriate state machine 1002 */ 1003 if (packet_info_table[ptype].class == CALL_CLASS_PKT) 1004 { 1005 if (assoc->assoc_flags & RPC_C_CN_ASSOC_CLIENT && 1006 assoc->alter_call_id >= 0 && 1007 assoc->alter_call_id == RPC_CN_PKT_CALL_ID (pktp)) 1008 { 1009 /* We got a call-level response to a network-level request. 1010 Neither the association state machine nor the call 1011 state machine are prepared to handle this. Abort the 1012 association */ 1013 RPC_CN_ASSOC_EVAL_NETWORK_EVENT (assoc, 1014 RPC_C_ASSOC_ABORT_REQ, 1015 fragbuf_p, 1016 st); 1017 } 1018 else if ((ptype == RPC_C_CN_PKT_REQUEST) 1019 && 1020 (RPC_CN_PKT_FLAGS (pktp) & RPC_C_CN_FLAGS_FIRST_FRAG)) 1021 { 1022 /* 1023 * This is the first fragment of a call request packet. 1024 * Allocate a call rep and mark it as being a server 1025 * call rep. 1026 */ 1027 call_r = (rpc_cn_call_rep_t *) 1028 rpc__list_element_alloc (&rpc_g_cn_call_lookaside_list, 1029 true); 1030 if (call_r == NULL) 1031 { 1032 st = rpc_s_no_memory; 1033 break; 1034 } 1035 call_r->common.is_server = true; 1036 1037 /* 1038 * Place the new call rep in the association for 1039 * use in cancel processing. 1040 */ 1041 rpc__cn_assoc_push_call (assoc, call_r, &st); 1042 if (st != rpc_s_ok) 1043 { 1044 assoc->call_rep = NULL; 1045 rpc__list_element_free (&rpc_g_cn_call_lookaside_list, 1046 (dce_pointer_t) call_r); 1047 break; 1048 } 1049 1050 /* 1051 * Initialize the server call state machine. 1052 */ 1053 rpc__cn_sm_init (rpc_g_cn_server_call_sm, 1054 rpc_g_cn_server_call_action_tbl, 1055 &(call_r->call_state), 1056 rpc_c_cn_svr_call); 1057 1058 call_r->num_pkts = 0; 1059 call_r->sec = sec_context; 1060 call_r->cn_call_status = rpc_s_ok; 1061 call_r->last_frag_received = false; 1062 call_r->call_executed = false; 1063 call_r->common.u.server.cthread.is_queued = false; 1064 call_r->prot_tlr = NULL; 1065 1066 { 1067 int i; 1068 for( i=1; i<RPC_C_MAX_IOVEC_LEN; i++ ) { 1069 call_r->buffered_output.iov.elt[i].buff_addr = NULL; 1070 call_r->buffered_output.iov.elt[i].buff_dealloc = NULL; 1071 } 1072 } 1073 1074 /* 1075 * Initialize some cancel state information. 1076 */ 1077 call_r->common.u.server.cancel.accepting = true; 1078 call_r->common.u.server.cancel.queuing = true; 1079 call_r->common.u.server.cancel.had_pending = false; 1080 call_r->common.u.server.cancel.count = 0; 1081 call_r->u.server.cancel.local_count = 0; 1082 1083 /* 1084 * Allocate a binding rep and put either a nil UUID 1085 * or the object UUID in the request packet header in 1086 * it, if present. 1087 */ 1088 if (RPC_CN_PKT_FLAGS (pktp) & RPC_C_CN_FLAGS_OBJECT_UUID) 1089 { 1090 call_r->binding_rep = 1091 rpc__binding_alloc (true, 1092 &RPC_CN_PKT_OBJECT (pktp), 1093 RPC_C_PROTOCOL_ID_NCACN, 1094 NULL, 1095 &st); 1096 } 1097 else 1098 { 1099 call_r->binding_rep = 1100 rpc__binding_alloc (true, 1101 &uuid_g_nil_uuid, 1102 RPC_C_PROTOCOL_ID_NCACN, 1103 NULL, 1104 &st); 1105 } 1106 1107 /* 1108 * If the binding_alloc failed, simply break out of 1109 * the loop to close the connection. 1110 */ 1111 if (st != rpc_s_ok) 1112 { 1113 break; 1114 } 1115 1116 /* 1117 * Put the association group id in the binding rep. 1118 */ 1119 ((rpc_cn_binding_rep_t *)call_r->binding_rep)->grp_id 1120 = assoc->assoc_grp_id; 1121 call_r->assoc = assoc; 1122 1123 /* 1124 * If auth protection level is rpc_c_protect_level_connect 1125 * the request pdu does not include auth tlr and so auth_len 1126 * field is set to zero. This disables security context lookup 1127 * by its key_id (transferred in auth_tlr). 1128 * In such case pass security context from association itself. 1129 */ 1130 if (!sec_context) 1131 { 1132 sec_context = assoc->security.assoc_current_sec_context; 1133 } 1134 1135 /* 1136 * Attach the auth info, if any, to the new binding 1137 * rep. Make sure to add a reference to it. 1138 */ 1139 if (sec_context) 1140 { 1141 call_r->binding_rep->auth_info = sec_context->sec_info; 1142 RPC_CN_AUTH_ADD_REFERENCE(sec_context->sec_info); 1143 } 1144 1145 /* 1146 * Attach transport info to the bindng rep 1147 */ 1148 call_r->binding_rep->transport_info = assoc->transport_info; 1149 rpc__transport_info_retain(assoc->transport_info); 1150 1151 /* 1152 * Post the event to the call state machine. 1153 */ 1154 RPC_CN_POST_FIRST_CALL_SM_EVENT (call_r, 1155 assoc, 1156 packet_info_table[ptype].event, 1157 fragbuf_p, 1158 st); 1159 1160 /* 1161 * Now that we have a call rep set up and are in the 1162 * call_request state see whether the security PDU 1163 * receive check or key ID lookup performed earlier in this routine, 1164 * if required, passed. If it failed a fault PDU 1165 * will be sent back to the client. 1166 */ 1167 if (st != rpc_s_ok) 1168 { 1169 RPC_CN_SEND_FAULT (call_r, st); 1170 fragbuf_p = NULL; 1171 continue; 1172 } 1173 if (auth_st != rpc_s_ok) 1174 { 1175 RPC_CN_SEND_FAULT (call_r, auth_st); 1176 fragbuf_p = NULL; 1177 continue; 1178 } 1179 1180 /* 1181 * Get the i/f id and version using the presentation 1182 * context id in the header. 1183 */ 1184 rpc__cn_assoc_syntax_lkup_by_id (assoc, 1185 RPC_CN_PKT_PRES_CONT_ID (pktp), 1186 &pres_context, 1187 &st); 1188 if (st != rpc_s_ok) 1189 { 1190 RPC_CN_SEND_FAULT (call_r, st); 1191 fragbuf_p = NULL; 1192 continue; 1193 } 1194 1195 call_r->u.server.if_id = &pres_context->syntax_abstract_id.id; 1196 call_r->u.server.if_vers = pres_context->syntax_abstract_id.version; 1197 call_r->transfer_syntax.index = pres_context->syntax_vector_index; 1198 call_r->transfer_syntax.convert_epv = pres_context->syntax_epv; 1199 call_r->u.server.ihint = pres_context->syntax_ihint; 1200 call_r->context_id = pres_context->syntax_pres_id; 1201 1202 /* 1203 * Invoke a call thread. 1204 */ 1205 rpc__cthread_invoke_null ((rpc_call_rep_p_t) call_r, 1206 &call_r->binding_rep->obj, 1207 call_r->u.server.if_id, 1208 call_r->u.server.if_vers, 1209 (unsigned32) call_r->opnum, 1210 rpc__cn_call_executor, 1211 (dce_pointer_t) call_r, 1212 &st); 1213 1214 /* 1215 * Check whether the call was queued. If it was, just 1216 * set the status code to "ok". 1217 */ 1218 if (st == rpc_s_call_queued) 1219 { 1220 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 1221 ("CN: call_rep->%p assoc->%p desc->%p call queued\n", 1222 call_r, 1223 assoc, 1224 assoc->cn_ctlblk.cn_sock)); 1225 st = rpc_s_ok; 1226 } 1227 else 1228 { 1229 /* 1230 * If we get an error back, then we were unable to 1231 * create the call thread. Send a fault PDU. 1232 */ 1233 if (st != rpc_s_ok) 1234 { 1235 RPC_CN_SEND_FAULT (call_r, st); 1236 fragbuf_p = NULL; 1237 continue; 1238 } 1239 } 1240 1241 /* 1242 * Keep some stats on the number of calls received. 1243 */ 1244 RPC_CN_STATS_INCR (calls_rcvd); 1245 } 1246 else 1247 { 1248 RPC_CN_POST_CALL_SM_EVENT (assoc, 1249 packet_info_table[ptype].event, 1250 fragbuf_p, 1251 st); 1252 } 1253 } 1254 else 1255 { 1256 RPC_CN_ASSOC_EVAL_NETWORK_EVENT (assoc, 1257 packet_info_table[ptype].event, 1258 fragbuf_p, 1259 st); 1260 } 1261 1262 /* 1263 * Unlock the CN global mutex, yield the processor to allow 1264 * another thread to run and re-acquire the CN global mutex. 1265 */ 1266 RPC_CN_UNLOCK (); 1267 dcethread_yield (); 1268 RPC_CN_LOCK (); 1269 1270 /* 1271 * NULL our pointer to the fragment buffer so we'll be forced to get 1272 * a new one. 1273 */ 1274 fragbuf_p = NULL; 1275 RPC_LOG_CN_PROCESS_PKT_XIT; 1276 } /* end-for (i = 0;; i++) */ 1277 1278 /* 1279 * Some failure occured while receiving packets. Indicate this 1280 * failure to the association state machine. 1281 */ 1282 rpc__cn_assoc_post_error (assoc, st); 1283 1284 /* 1285 * If we still have a fragbufs, then deallocate them. 1286 */ 1287 if (fragbuf_p) 1288 { 1289 (*fragbuf_p->fragbuf_dealloc)(fragbuf_p); 1290 } 1291 if (ovf_fragbuf_p) 1292 { 1293 (*ovf_fragbuf_p->fragbuf_dealloc)(ovf_fragbuf_p); 1294 } 1295} 1296 1297 1298/******************************************************************************/ 1299/* 1300**++ 1301** 1302** ROUTINE NAME: receive_packet 1303** 1304** SCOPE: INTERNAL - declared locally 1305** 1306** DESCRIPTION: 1307** 1308** This is a (large) wrapper around the socket recvmsg() routine. 1309** 1310** We do this since stream sockets don't guarantee the preservation of RPC 1311** packet boundaries. If we receive partial packets, we have to piece them 1312** back together again. Also, if we receive more than one packet during a 1313** read operation, we preserve the excess bytes read and return them the next 1314** time we are called. 1315** 1316** INPUTS: 1317** 1318** assoc pointer to an association control block 1319** 1320** INPUTS/OUTPUTS: 1321** 1322** fragbuf_p pointer to a fragbuf pointer 1323** ovf_fragbuf_p pointer to a overflow fragbuf pointer 1324** 1325** OUTPUTS: 1326** 1327** st the return status of this routine 1328** 1329** IMPLICIT INPUTS: none 1330** 1331** IMPLICIT OUTPUTS: none 1332** 1333** FUNCTION VALUE: none 1334** 1335** SIDE EFFECTS: none 1336** 1337**-- 1338**/ 1339 1340INTERNAL void receive_packet 1341( 1342 rpc_cn_assoc_p_t assoc, 1343 rpc_cn_fragbuf_p_t *fragbuf_p, 1344 rpc_cn_fragbuf_p_t *ovf_fragbuf_p, 1345 unsigned32 *st 1346) 1347{ 1348 rpc_cn_fragbuf_t * volatile fbp; 1349 volatile unsigned16 frag_length; 1350 size_t bytes_rcvd = 0; 1351 rpc_socket_iovec_t iov; 1352 volatile rpc_socket_error_t serr = 0; 1353 signed32 need_bytes; 1354 static rpc_addr_p_t addr = NULL; 1355 1356 //DO_NOT_CLOBBER(fbp); 1357 //DO_NOT_CLOBBER(frag_length); 1358 1359 RPC_LOG_CN_RCV_PKT_NTR; 1360 CODING_ERROR (st); 1361 1362 /* 1363 * One time (auto) initialization. 1364 */ 1365 fbp = NULL; 1366 1367 /* 1368 * Assume the worst is going to happen and zap our return value. 1369 */ 1370 *fragbuf_p = NULL; 1371 1372 /* 1373 * If we have a left over fragment buffer (overflow), then use it. 1374 */ 1375 if (*ovf_fragbuf_p != NULL) 1376 { 1377 fbp = *ovf_fragbuf_p; 1378 *ovf_fragbuf_p = NULL; 1379 } 1380 1381 /* 1382 * If we need a fragment buffer, then allocate one. 1383 */ 1384 if (fbp == NULL) 1385 { 1386 fbp = rpc__cn_fragbuf_alloc (true); 1387 } 1388 1389 /* 1390 ****************************************************************** 1391 * At this point we must determine which of the following 3 1392 * situations we are faced with: 1393 * 1394 * 1) The fragbuf is empty. 1395 * 2) The fragbuf contains a partial RPC packet. 1396 * 3) The fragbuf contains a complete RPC packet. 1397 * 1398 * The first thing we do is to check whether or not we have 1399 * enough data in the current fragbuf to determine the complete 1400 * RPC packet length. Note that in the 3rd case, the fragbuf may 1401 * actually contain more than one RPC packet. 1402 * 1403 ****************************************************************** 1404 */ 1405 1406 /* 1407 * Do we have enough data in the fragbuf to determine the RPC packet 1408 * length? 1409 * 1410 * If we do, we can figure out exactly how many bytes to request on our 1411 * next read. If we don't, we just ask for the maximum number of bytes 1412 * that our fragbuf will hold. 1413 */ 1414 if (fbp->data_size >= RPC_C_CN_FRAGLEN_HEADER_BYTES) 1415 { 1416 /* 1417 * Okay, we have enough of the header to figure out how big 1418 * this fragment is. 1419 */ 1420 frag_length = RPC_CN_PKT_FRAG_LEN ((rpc_cn_packet_p_t)(fbp->data_p)); 1421 1422 /* 1423 * Swap bytes if our integer formats are different. 1424 */ 1425 if (NDR_DREP_INT_REP(RPC_CN_PKT_DREP((rpc_cn_packet_p_t)fbp->data_p)) 1426 != NDR_LOCAL_INT_REP) 1427 { 1428 SWAB_INPLACE_16 (frag_length); 1429 } 1430 1431 /* 1432 * Figure out how many bytes we need. 1433 */ 1434 need_bytes = frag_length - fbp->data_size; 1435 } 1436 else 1437 { 1438 /* 1439 * We don't have enough data to compute the fragment length. 1440 */ 1441 frag_length = 0; 1442 1443 /* 1444 * Ask for as many bytes as our fragbuf will hold. 1445 */ 1446 need_bytes = fbp->max_data_size - fbp->data_size; 1447 } 1448 1449 /* 1450 * Read from the socket until we've read at least one entire packet. 1451 */ 1452 while (need_bytes > 0) 1453 { 1454 1455 /* 1456 * Initialize our iovector. 1457 */ 1458 iov.iov_base = (byte_p_t)((unsigned8 *)(fbp->data_p) + fbp->data_size); 1459 iov.iov_len = need_bytes; 1460 1461 /* 1462 * Release the CN global mutex before reading from the 1463 * socket. This will allow other threads to run if we have to 1464 * block here. 1465 */ 1466 RPC_CN_UNLOCK (); 1467 DCETHREAD_TRY 1468 { 1469#ifdef NON_CANCELLABLE_IO 1470 /* 1471 * By POSIX definition dcethread_enableasync_throw is not a "cancel 1472 * point" because it must return an error status and an errno. 1473 * dcethread_enableasync_throw(1) will not deliver 1474 * a pending cancel nor will the cancel be delivered asynchronously, 1475 * thus the need for dcethread_checkinterrupt. 1476 */ 1477 dcethread_enableasync_throw(1); 1478 dcethread_checkinterrupt(); 1479#endif /* NON_CANCELLABLE_IO */ 1480 serr = rpc__socket_recvmsg( 1481 assoc->cn_ctlblk.cn_sock, 1482 &iov, 1483 1, 1484 addr, 1485 &bytes_rcvd); 1486#ifdef NON_CANCELLABLE_IO 1487 dcethread_enableasync_throw(0); 1488#endif /* NON_CANCELLABLE_IO */ 1489 } 1490 DCETHREAD_CATCH (dcethread_interrupt_e) 1491 { 1492#ifdef NON_CANCELLABLE_IO 1493 dcethread_enableasync_throw(0); 1494#endif /* NON_CANCELLABLE_IO */ 1495 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 1496("CN: call_rep->%p assoc->%p desc->%p receiver canceled, caught in receive_packet()\n", 1497 assoc->call_rep, 1498 assoc, 1499 assoc->cn_ctlblk.cn_sock)); 1500 1501 /* 1502 * Re-acquire the CN global mutex and free any fragment 1503 * buffers we have outstanding. 1504 */ 1505 RPC_CN_LOCK (); 1506 if (fbp) 1507 { 1508 (*(fbp)->fragbuf_dealloc)(fbp); 1509 } 1510 DCETHREAD_RERAISE; 1511 } 1512 DCETHREAD_CATCH_ALL(THIS_CATCH) 1513 { 1514 /* 1515 * rpc_m_unexpected_exc 1516 * "(%s) Unexpected exception was raised" 1517 */ 1518 rpc_dce_svc_printf ( 1519 __FILE__, __LINE__, 1520 "%s", 1521 rpc_svc_recv, 1522 svc_c_sev_fatal | svc_c_action_abort, 1523 rpc_m_unexpected_exc, 1524 "receive_packet" ); 1525 } 1526 DCETHREAD_ENDTRY 1527 1528 /* 1529 * Re-acquire the CN global mutex. 1530 */ 1531 RPC_CN_LOCK (); 1532 1533 /* 1534 * Hold off on processing the packet if the sending thread for this 1535 * connection is currently in a sendmsg. 1536 */ 1537 while (assoc->cn_ctlblk.in_sendmsg) 1538 { 1539 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 1540 ("CN: call_rep->%p assoc->%p desc->%p waiting for sendmsg to complete...\n", 1541 assoc->call_rep, 1542 assoc, 1543 assoc->cn_ctlblk.cn_sock)); 1544 assoc->cn_ctlblk.waiting_for_sendmsg_complete = true; 1545 RPC_COND_WAIT (assoc->cn_ctlblk.cn_rcvr_cond, 1546 rpc_g_global_mutex); 1547 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 1548 ("CN: call_rep->%p assoc->%p desc->%p sendmsg complete\n", 1549 assoc->call_rep, 1550 assoc, 1551 assoc->cn_ctlblk.cn_sock)); 1552 assoc->cn_ctlblk.waiting_for_sendmsg_complete = false; 1553 } 1554 1555 /* 1556 * Process any errors reading the socket or any errors detected by 1557 * other threads using this association. These other threads will have 1558 * cleaned up the assoc state and the receiver thread just has to close 1559 * the connection now. 1560 */ 1561 if ((RPC_SOCKET_IS_ERR (serr)) 1562 || 1563 (bytes_rcvd == 0) 1564 || 1565 (assoc->assoc_local_status != rpc_s_ok) 1566 || 1567 (assoc->assoc_status != rpc_s_ok)) 1568 { 1569 /* 1570 * Make sure the connection is really closed. It could 1571 * be a zero length sequenced packet socket packet. 1572 */ 1573 if (rpc__naf_is_connect_closed (assoc->cn_ctlblk.cn_sock, st)) 1574 { 1575 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 1576 ("CN: call_rep->%p assoc->%p desc->%p connection closed recvmsg failed serr = %x, bytes_rcvd = %ld\n", 1577 assoc->call_rep, 1578 assoc, 1579 assoc->cn_ctlblk.cn_sock, 1580 serr, 1581 bytes_rcvd)); 1582 1583 /* 1584 * Deallocate the fragbuf which we were using. 1585 */ 1586 (*fbp->fragbuf_dealloc)(fbp); 1587 1588 *st = rpc_s_connection_closed; 1589 return; 1590 } 1591 } 1592 1593 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 1594 ("CN: call_rep->%p assoc->%p desc->%p received %ld bytes\n", 1595 assoc->call_rep, 1596 assoc, 1597 assoc->cn_ctlblk.cn_sock, 1598 bytes_rcvd)); 1599 1600 /* 1601 * Update the number of bytes received. 1602 */ 1603 fbp->data_size += bytes_rcvd; 1604 1605 /* 1606 * If we don't already know the fragment length, then we now have to go 1607 * through the same gymnastics that we did before vis a vis determining 1608 * whether or not we've read enough of this fragment to determine the 1609 * complete fragment length. 1610 */ 1611 if ((frag_length == 0) && (fbp->data_size >= RPC_C_CN_FRAGLEN_HEADER_BYTES)) 1612 { 1613 /* 1614 * We don't know the fragment length and we have enough bytes to 1615 * determine it so compute the fragment length. 1616 */ 1617 frag_length = RPC_CN_PKT_FRAG_LEN ((rpc_cn_packet_p_t)(fbp->data_p)); 1618 1619 /* 1620 * Swap bytes if our integer formats are different. 1621 */ 1622 if (NDR_DREP_INT_REP( RPC_CN_PKT_DREP((rpc_cn_packet_p_t)fbp->data_p) ) != NDR_LOCAL_INT_REP) 1623 { 1624 SWAB_INPLACE_16 (frag_length); 1625 } 1626 1627 /* 1628 * Sanity check the protocol versions in the header. 1629 * Except for BIND and BIND_NAK packets. 1630 */ 1631 { 1632 unsigned32 ptype; 1633 ptype = RPC_CN_PKT_PTYPE((rpc_cn_packet_p_t)fbp->data_p); 1634 1635 if ((ptype != RPC_C_CN_PKT_BIND) && 1636 (ptype != RPC_C_CN_PKT_BIND_NAK) && 1637 ((RPC_CN_PKT_VERS ((rpc_cn_packet_p_t)fbp->data_p) != RPC_C_CN_PROTO_VERS) || 1638 (RPC_CN_PKT_VERS_MINOR ((rpc_cn_packet_p_t)fbp->data_p) != assoc->assoc_vers_minor))) 1639 { 1640 /* 1641 * We have incompatible protocol versions. 1642 */ 1643 /* 1644 * "(receive_packet) assoc->%p %s: Protocol version mismatch - 1645 * major->%x minor->%x" 1646 */ 1647 rpc_dce_svc_printf ( 1648 __FILE__, __LINE__, 1649 "%x %s %x %x", 1650 rpc_svc_cn_pkt, 1651 svc_c_sev_warning, 1652 rpc_m_prot_mismatch, 1653 assoc, 1654 rpc__cn_pkt_name(ptype), 1655 RPC_CN_PKT_VERS ((rpc_cn_packet_p_t)fbp->data_p), 1656 RPC_CN_PKT_VERS_MINOR ((rpc_cn_packet_p_t)fbp->data_p) ); 1657 } 1658 } 1659 1660 /* 1661 * Sanity check the fragment size. 1662 * Signal an error if this fragment is bigger than a fragbuf. 1663 */ 1664 if (frag_length > rpc_g_cn_large_frag_size) 1665 { 1666 unsigned32 ptype; 1667 ptype = RPC_CN_PKT_PTYPE((rpc_cn_packet_p_t)fbp->data_p); 1668 1669 /* 1670 * "(receive_packet) assoc->%p frag_length %d in header > 1671 * fragbuf data size %d" 1672 */ 1673 rpc_dce_svc_printf ( 1674 __FILE__, __LINE__, 1675 "%x %d %d", 1676 rpc_svc_cn_pkt, 1677 svc_c_sev_warning, 1678 rpc_m_frag_toobig, 1679 assoc, 1680 frag_length, 1681 rpc_g_cn_large_frag_size ); 1682 1683 /* 1684 * BIND and ALTER_CONTEXT are allowed to be larger 1685 */ 1686 if ((ptype == RPC_C_CN_PKT_BIND) || 1687 (ptype == RPC_C_CN_PKT_ALTER_CONTEXT)) 1688 { 1689 rpc_cn_fragbuf_t * volatile tmp; 1690 1691 tmp = rpc__cn_fragbuf_alloc_dyn(frag_length); 1692 tmp->data_size = fbp->data_size; 1693 memcpy(tmp->data_p, fbp->data_p, fbp->data_size); 1694 1695 (*fbp->fragbuf_dealloc)(fbp); 1696 fbp = tmp; 1697 } 1698 else 1699 { 1700 *st = rpc_s_protocol_error; 1701 1702 /* 1703 * Deallocate the fragbuf which we were using. 1704 */ 1705 (*fbp->fragbuf_dealloc)(fbp); 1706 return; 1707 } 1708 } 1709 } 1710 1711 /* 1712 * Recalculate how many bytes we need to complete this fragment. 1713 */ 1714 if (frag_length == 0) 1715 { 1716 need_bytes = fbp->max_data_size - fbp->data_size; 1717 } 1718 else 1719 { 1720 need_bytes = frag_length - fbp->data_size; 1721 } 1722 } /* end of while(need_bytes > 0) */ 1723 1724 /* 1725 * Handle the situation where we have read too much data. 1726 * This means that we have read into the next packet. 1727 * So, get an "overflow" fragment buffer and copy the excess data into it. 1728 */ 1729 1730 /* 1731 * There is room for some optimization here. If we have enough bytes to 1732 * determine the length of the next packet and the whole thing will fit into 1733 * a small fragbuf, then we should probably use a small one. For now, we're 1734 * going to apply the KISS principle. 1735 */ 1736 if (need_bytes < 0) 1737 { 1738 /* 1739 * Get an overflow fragment buffer. 1740 */ 1741 *ovf_fragbuf_p = rpc__cn_fragbuf_alloc (true); 1742 (*ovf_fragbuf_p)->data_size = abs(need_bytes); 1743 1744 /* 1745 * Set the fragbuf data size to the fragment length and copy the 1746 * excess data to the overflow fragment buffer. 1747 */ 1748 fbp->data_size = frag_length; 1749 memcpy ((*ovf_fragbuf_p)->data_p, 1750 (dce_pointer_t)((unsigned8 *)(fbp->data_p) + fbp->data_size), 1751 (*ovf_fragbuf_p)->data_size); 1752 } 1753 1754 /* 1755 * Return a pointer to the just-received packet along with okay status. 1756 */ 1757 *fragbuf_p = fbp; 1758 *st = rpc_s_ok; 1759 RPC_LOG_CN_RCV_PKT_XIT; 1760} 1761