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** cnpkt.c 82** 83** FACILITY: 84** 85** Remote Procedure Call (RPC) 86** 87** ABSTRACT: 88** 89** Connection-based protocol packet packing/unpacking routines. 90** 91** 92*/ 93 94#include <commonp.h> /* Common declarations for all RPC runtime */ 95#include <com.h> /* Common communications services */ 96#include <comprot.h> /* Common protocol services */ 97#include <ndrp.h> /* System (machine architecture) dependent definitions */ 98#include <cnp.h> /* NCA Connection private declarations */ 99#include <cnpkt.h> /* NCA Connection packet encoding */ 100 101/* 102 * R P C _ G _ C N _ C O M M O N _ H D R 103 * 104 * This is a template of the common part of all NCA connection 105 * packet headers. It is statically initialized where possible. This 106 * is used by the rpc__cn_pkt_format_common routine. 107 */ 108GLOBAL rpc_cn_common_hdr_t rpc_g_cn_common_hdr = 109{ 110 111 RPC_C_CN_PROTO_VERS, /* rpc_vers */ 112 RPC_C_CN_PROTO_VERS_MINOR, /* rpc_vers_minor */ 113 RPC_C_CN_PKT_INVALID, /* ptype */ 114 0, /* flags */ 115 { /* drep[4] */ 116 (NDR_LOCAL_INT_REP << 4) | NDR_LOCAL_CHAR_REP, 117 NDR_LOCAL_FLOAT_REP, 118 0, 119 0 120 }, 121 0, /* frag_len */ 122 0, /* auth_len */ 123 0 /* call_id */ 124}; 125 126 127INTERNAL rpc_cn_pres_result_list_p_t unpack_port_any ( 128 rpc_cn_port_any_t *port_any_p, 129 unsigned8 *drepp, 130 unsigned8 *end_of_pkt, 131 unsigned32 *st 132 ); 133 134INTERNAL rpc_cn_auth_tlr_p_t unpack_pres_context_list ( 135 rpc_cn_pres_cont_list_p_t pcontp, 136 boolean32 swap, 137 unsigned8 *end_of_pkt, 138 unsigned32 *st 139 ); 140 141INTERNAL rpc_cn_auth_tlr_p_t unpack_pres_result_list ( 142 rpc_cn_pres_result_list_p_t presp, 143 boolean32 swap, 144 unsigned8 *end_of_pkt, 145 unsigned32 *st 146 ); 147 148INTERNAL rpc_cn_auth_tlr_p_t unpack_versions_supported ( 149 rpc_cn_versions_supported_p_t /*versp*/ 150 ); 151 152void SWAP_INPLACE_UUID 153( 154 idl_uuid_t *uuid_p, 155 unsigned8 *end_of_pkt, 156 unsigned32 *st 157) 158{ 159 SWAP_INPLACE_32(&uuid_p->time_low, end_of_pkt, st); 160 if (*st == rpc_s_ok) 161 { 162 SWAP_INPLACE_16(&uuid_p->time_mid, end_of_pkt, st); 163 } 164 if (*st == rpc_s_ok) 165 { 166 SWAP_INPLACE_16(&uuid_p->time_hi_and_version, end_of_pkt, st); 167 } 168} 169 170void SWAP_INPLACE_SYNTAX 171( 172 rpc_cn_pres_syntax_id_p_t syntax_p, 173 unsigned8 *end_of_pkt, 174 unsigned32 *st 175) 176{ 177 SWAP_INPLACE_UUID(&syntax_p->id, end_of_pkt, st); 178 if (*st == rpc_s_ok) 179 { 180 SWAP_INPLACE_32(&syntax_p->version, end_of_pkt, st); 181 } 182} 183 184/* 185**++ 186** 187** ROUTINE NAME: unpack_port_any 188** 189** SCOPE: INTERNAL - declared in cnpkt.c 190** 191** DESCRIPTION: 192** 193** This routine unpacks the 'port_any' secondary address field of an 194** RPC connection packet and returns a pointer to the next octet following 195** the port_any field. 196** 197** INPUTS: 198** 199** port_any_p pointer to the 'port_any' field within the packet 200** drepp pointer to the data representation 201** swap boolean indicating we need to perform byte swapping 202** end_of_pkt ptr to 1 byte past end of packet 203** 204** INPUTS/OUTPUTS: none 205** 206** OUTPUTS: 207** st The return status of this routine 208** 209** IMPLICIT INPUTS: none 210** 211** IMPLICIT OUTPUTS: none 212** 213** FUNCTION VALUE: 214** 215** return pointer to the next octet after the 'port_any' field 216** 217** SIDE EFFECTS: none 218** 219**-- 220**/ 221 222INTERNAL rpc_cn_pres_result_list_p_t unpack_port_any 223( 224 rpc_cn_port_any_t *port_any_p, 225 unsigned8 *drepp, 226 unsigned8 *end_of_pkt, 227 unsigned32 *st 228) 229{ 230 unsigned8 * string_end; 231 union 232 { /* a "proper" union to shut up lint */ 233 unsigned8 *string; /* a string pointer */ 234 rpc_cn_pres_result_list_p_t rtn; /* a return value */ 235 } ptr; 236 237 *st = rpc_s_ok; 238 239 ptr.string = port_any_p->s; /* init our string pointer */ 240 241 /* 242 * byte-swap the length field if the endian's are different 243 */ 244 if (NDR_LOCAL_INT_REP != NDR_DREP_INT_REP (drepp)) 245 { 246 SWAP_INPLACE_16 (&port_any_p->length, end_of_pkt, st); 247 if (*st != rpc_s_ok) 248 { 249 return (NULL); 250 } 251 } 252 253 /* 254 * only do the inplace string conversion if the two drep's are different 255 */ 256 if (NDR_LOCAL_CHAR_REP != NDR_DREP_CHAR_REP (drepp)) 257 { 258 string_end = ptr.string + port_any_p->length; 259 if ( (string_end < ptr.string) || (end_of_pkt < string_end) ) 260 { 261 *st = rpc_s_bad_pkt; 262 return (NULL); 263 } 264 265 rpc_util_strcvt ( NDR_LOCAL_CHAR_REP == ndr_c_char_ascii, 266 port_any_p->length, 267 ptr.string, 268 ptr.string ); 269 } 270 271 /* 272 * point to just beyond the end of the string and return that value 273 * as our return value 274 */ 275 ptr.string += port_any_p->length; 276 return (ptr.rtn); 277} 278 279 280/* 281**++ 282** 283** ROUTINE NAME: unpack_pres_context_list 284** 285** SCOPE: INTERNAL - declared in cnpkt.c 286** 287** DESCRIPTION: 288** 289** This routine unpacks a presentation context list in an RPC connection 290** packet and returns a pointer to the next octet following the list. 291** 292** INPUTS: 293** 294** pcontp pointer to the presentation context list 295** swap boolean indicating we need to perform byte swapping 296** end_of_pkt ptr to 1 byte past end of packet 297** 298** INPUTS/OUTPUTS: none 299** 300** OUTPUTS: 301** st The return status of this routine 302** 303** IMPLICIT INPUTS: none 304** 305** IMPLICIT OUTPUTS: none 306** 307** FUNCTION VALUE: none 308** 309** return pointer to the next octet following the presentation 310** context list 311** 312** SIDE EFFECTS: none 313** 314**-- 315**/ 316 317INTERNAL rpc_cn_auth_tlr_p_t unpack_pres_context_list 318( 319 rpc_cn_pres_cont_list_p_t pcontp, 320 boolean32 swap, 321 unsigned8 *end_of_pkt, 322 unsigned32 *st 323) 324{ 325 unsigned8 n; /* presentation context list element 326 * loop count */ 327 unsigned8 id; /* transfer syntax list loop count */ 328 unsigned8 tsn; /* number of transfer syntaxes */ 329 union 330 { /* a "proper" union to shutup lint */ 331 rpc_cn_pres_cont_elem_p_t ep; /* ptr to presentation context list 332 * element */ 333 rpc_cn_pres_syntax_id_p_t sp; /* ptr to a transfer syntax id */ 334 rpc_cn_auth_tlr_p_t rtn; /* return value */ 335 } ptrs; 336 337 *st = rpc_s_ok; 338 339 /* 340 * Get a pointer to the first element. 341 * 342 * NB: The elements and lists that we are parsing are all variable length. 343 */ 344 ptrs.ep = &(pcontp->pres_cont_elem[0]); 345 346 /* 347 * Process each element of the presentation context list. 348 */ 349 for (n = 0; n < pcontp->n_context_elem; n++) 350 { 351 /* 352 * Get the number of transfer syntaxes in this element. 353 */ 354 tsn = (ptrs.ep)->n_transfer_syn; 355 356 /* 357 * Unpack the abstract and transfer syntaxes. 358 */ 359 if (swap) 360 { 361 /* 362 * Convert the presentation context id. 363 */ 364 SWAP_INPLACE_16 (&(ptrs.ep)->pres_context_id, end_of_pkt, st); 365 if (*st != rpc_s_ok) 366 { 367 return (NULL); 368 } 369 370 /* 371 * Convert the abstract syntax. 372 */ 373 SWAP_INPLACE_SYNTAX (&(ptrs.ep)->abstract_syntax, end_of_pkt, st); 374 if (*st != rpc_s_ok) 375 { 376 return (NULL); 377 } 378 379 /* 380 * Process each transfer syntax id of this element. 381 */ 382 for (id = 0; id < tsn; id++) 383 { 384 SWAP_INPLACE_SYNTAX (&(ptrs.ep)->transfer_syntaxes[id], end_of_pkt, st); 385 if (*st != rpc_s_ok) 386 { 387 return (NULL); 388 } 389 } 390 } 391 392 /* 393 * Point to the next context element. 394 */ 395 (ptrs.sp) = &((ptrs.ep)->transfer_syntaxes[tsn]); 396 } 397 398 /* 399 * We return a pointer to the next byte. 400 */ 401 return (ptrs.rtn); 402} 403 404 405/* 406**++ 407** 408** ROUTINE NAME: unpack_pres_result_list 409** 410** SCOPE: INTERNAL - declared in cnpkt.c 411** 412** DESCRIPTION: 413** 414** This routine unpacks a presentation result list in an RPC connection 415** packet and returns a pointer to the next octet following the list. 416** 417** INPUTS: 418** 419** presp pointer to the presentation result list 420** swap boolean indicating we need to perform byte swapping 421** swap boolean indicating we need to perform byte swapping 422** end_of_pkt ptr to 1 byte past end of packet 423** 424** INPUTS/OUTPUTS: none 425** 426** OUTPUTS: 427** st The return status of this routine 428** 429** IMPLICIT INPUTS: none 430** 431** IMPLICIT OUTPUTS: none 432** 433** FUNCTION VALUE: 434** 435** return pointer to the next octet following the presentation 436** result list 437** 438** SIDE EFFECTS: none 439** 440**-- 441**/ 442 443INTERNAL rpc_cn_auth_tlr_p_t unpack_pres_result_list 444( 445 rpc_cn_pres_result_list_p_t presp, 446 boolean32 swap, 447 unsigned8 *end_of_pkt, 448 unsigned32 *st 449) 450{ 451 unsigned8 n; /* presentation result list element loop 452 * count */ 453 unsigned8 prn; /* number of presentation results */ 454 455 *st = rpc_s_ok; 456 457 /* 458 * Process each element of the presentation result list. 459 */ 460 prn = presp->n_results; 461 for (n = 0; (n < prn) && swap; n++) 462 { 463 SWAP_INPLACE_16 (&presp->pres_results[n].result, end_of_pkt, st); 464 if (*st != rpc_s_ok) 465 { 466 return (NULL); 467 } 468 469 SWAP_INPLACE_16 (&presp->pres_results[n].reason, end_of_pkt, st); 470 if (*st != rpc_s_ok) 471 { 472 return (NULL); 473 } 474 475 SWAP_INPLACE_SYNTAX (&presp->pres_results[n].transfer_syntax, end_of_pkt, st); 476 if (*st != rpc_s_ok) 477 { 478 return (NULL); 479 } 480 } 481 482 /* 483 * We return a pointer to the next byte. 484 */ 485 return ((rpc_cn_auth_tlr_p_t) &presp->pres_results[prn]); 486} 487 488 489/* 490**++ 491** 492** ROUTINE NAME: unpack_versions_supported 493** 494** SCOPE: INTERNAL - declared in cnpkt.c 495** 496** DESCRIPTION: 497** 498** This routine unpacks a 'rpc_cn_versions_supported_t' structure 499** in an RPC connection packet and returns a pointer to the next 500** octet following the versions structure. 501** 502** INPUTS: 503** 504** versions_p pointer to versions supported field 505** 506** INPUTS/OUTPUTS: none 507** 508** OUTPUTS: none 509** 510** IMPLICIT INPUTS: none 511** 512** IMPLICIT OUTPUTS: none 513** 514** FUNCTION VALUE: 515** 516** return pointer to the next octet after the 517** 'versions_supported' 518** 519** SIDE EFFECTS: 520** 521**-- 522**/ 523 524INTERNAL rpc_cn_auth_tlr_p_t unpack_versions_supported 525( 526 rpc_cn_versions_supported_p_t versions_p 527) 528{ 529 union 530 { 531 rpc_cn_version_p_t versp; 532 rpc_cn_auth_tlr_p_t rtn; 533 } ptrs; 534 int i; 535 536 for (ptrs.versp = &versions_p->protocols[0], i = 0; 537 i<versions_p->n_protocols; 538 i++, ptrs.versp++) 539 ; 540 541 return (ptrs.rtn); 542} 543 544 545/* 546**++ 547** 548** ROUTINE NAME: force_alignment 549** 550** SCOPE: INTERNAL - declared in cnpkt.c 551** 552** DESCRIPTION: 553** 554** This routine takes as in put a pointer which is to be aligned on a 555** requested byte boundary. Note well that this routine is a potential 556** source of portability problems since we are performing math operations 557** on pointers. 558** 559** INPUTS: 560** 561** boundary number of octets of forced alignment 562** 563** INPUTS/OUTPUTS: 564** 565** ptr pointer to be aligned 566** 567** OUTPUTS: none 568** 569** IMPLICIT INPUTS: none 570** 571** IMPLICIT OUTPUTS: none 572** 573** FUNCTION VALUE: none 574** 575** SIDE EFFECTS: none 576** 577**-- 578**/ 579 580INTERNAL void force_alignment 581( 582 unsigned32 boundary, 583 unsigned8 **ptr 584) 585{ 586 union 587 { 588 unsigned8 **as_ptr; 589 unsigned32 *as_int; 590 } anyptr; 591 592 anyptr.as_ptr = ptr; 593 594 if (*anyptr.as_int & (boundary-1)) 595 { 596 *anyptr.as_int += boundary; 597 *anyptr.as_int &= ~(boundary-1); 598 } 599} 600 601 602/* 603**++ 604** 605** ROUTINE NAME: end_of_stub_data 606** 607** SCOPE: INTERNAL - declared in cnpkt.c 608** 609** DESCRIPTION: 610** 611** This routine returns a pointer to the octet just following the stub data. 612** 613** INPUTS: 614** 615** pkt_p a pointer to the packet being unpacked 616** 617** INPUTS/OUTPUTS: none 618** 619** OUTPUTS: none 620** 621** IMPLICIT INPUTS: none 622** 623** IMPLICIT OUTPUTS: none 624** 625** FUNCTION VALUE: none 626** 627** SIDE EFFECTS: none 628** 629**-- 630**/ 631 632INTERNAL rpc_cn_auth_tlr_p_t end_of_stub_data 633( 634 rpc_cn_packet_p_t pkt_p 635) 636{ 637 union 638 { 639 unsigned8 *any; 640 rpc_cn_packet_p_t pkt; 641 rpc_cn_auth_tlr_p_t rtn; 642 } ptrs; 643 unsigned32 stub_data_length; 644 unsigned32 packet_header_overhead = 0; 645 646 /* 647 * Figure out our packet overhead. 648 */ 649 switch (RPC_CN_PKT_PTYPE (pkt_p)) 650 { 651 case RPC_C_CN_PKT_REQUEST: 652 653 if (RPC_CN_PKT_OBJ_UUID_PRESENT (pkt_p)) 654 { 655 packet_header_overhead = RPC_CN_PKT_SIZEOF_RQST_HDR_W_OBJ; 656 } 657 else 658 { 659 packet_header_overhead = RPC_CN_PKT_SIZEOF_RQST_HDR_NO_OBJ; 660 } 661 break; 662 663 case RPC_C_CN_PKT_RESPONSE: 664 665 packet_header_overhead = RPC_CN_PKT_SIZEOF_RESP_HDR; 666 break; 667 668 case RPC_C_CN_PKT_FAULT: 669 670 packet_header_overhead = RPC_CN_PKT_SIZEOF_FAULT_HDR; 671 break; 672 default: 673 /* FIXME */ 674 fprintf(stderr, "%s, unhandled case in switch: aborting\n", __PRETTY_FUNCTION__); 675 raise(SIGILL); 676 } 677 678#ifdef AUTH_QUESTIONS 679 This is going to need some work based on what steve says about 680 padding of stub data for auth trailers. 681#endif 682 683 /* 684 * calculate our stub data length 685 */ 686 stub_data_length = RPC_CN_PKT_FRAG_LEN(pkt_p) - 687 RPC_CN_PKT_AUTH_LEN(pkt_p) - 688 packet_header_overhead; 689 690 /* 691 * 1 - init our union of pointers to the start of the packet 692 * 2 - bump to point to start of stub data in packet 693 * 3 - bump to point to end of stub data 694 */ 695 ptrs.pkt = pkt_p; 696 ptrs.any += packet_header_overhead; 697 ptrs.any += stub_data_length; 698 699 return (ptrs.rtn); 700} 701 702 703/* 704**++ 705** 706** ROUTINE NAME: rpc__cn_unpack_hdr 707** 708** SCOPE: PRIVATE - declared in cnpkt.h 709** 710** DESCRIPTION: 711** 712** This routine is called by the network receiver thread to unpack an 713** RPC connection packet. Basically, this routine does all the byte 714** swapping required between different endian machines as well as any 715** ebcdic <-> ascii translation required. 716** 717** INPUTS: 718** 719** pkt_p a pointer to the packet to be unpacked 720** data_size length of packet to ensure do not go past end of packet 721** 722** INPUTS/OUTPUTS: none 723** 724** OUTPUTS: unsigned32 error 725** 726** IMPLICIT INPUTS: none 727** 728** IMPLICIT OUTPUTS: none 729** 730** FUNCTION VALUE: none 731** 732** SIDE EFFECTS: none 733** 734**-- 735**/ 736 737PRIVATE unsigned32 rpc__cn_unpack_hdr 738( 739 rpc_cn_packet_p_t pkt_p, 740 unsigned32 data_size 741) 742{ 743 rpc_cn_auth_tlr_p_t authp; /* ptr to pkt authentication data */ 744 rpc_cn_pres_cont_list_p_t pconp; /* ptr to pkt presentation context lists */ 745 rpc_cn_pres_result_list_p_t presp; /* ptr to pkt presentation result lists */ 746 rpc_cn_port_any_p_t secadrp; /* ptr to pkt secondary address data */ 747 rpc_cn_versions_supported_p_t versp; /* ptr to pkt versions supported data */ 748 unsigned8 *drepp; /* ptr to pkt drep[] data */ 749 boolean swap; /* boolean says we swap bytes/words */ 750 boolean authenticate; /* boolean says authentication data is valid */ 751 boolean has_uuid; /* boolean says an OBJECT uuid is present */ 752 unsigned32 st; /* status variable */ 753 unsigned8 *end_of_pkt; /* ptr to 1 byte past end of packet */ 754 755 end_of_pkt = (unsigned8 *) pkt_p; 756 end_of_pkt += data_size; 757 758 /* 759 * Get the DREP and see if we need to do byte/word swapping. 760 */ 761 drepp = RPC_CN_PKT_DREP (pkt_p); 762 swap = (NDR_DREP_INT_REP (drepp) != NDR_LOCAL_INT_REP); 763 764 /* 765 * RPC_CN_COMMON_HDR_T 766 * 767 * Unpack the common part of the packet header. 768 */ 769 if (swap) 770 { 771 SWAP_INPLACE_16 (&RPC_CN_PKT_FRAG_LEN (pkt_p), end_of_pkt, &st); 772 if (st != rpc_s_ok) 773 { 774 return (st); 775 } 776 777 SWAP_INPLACE_16 (&RPC_CN_PKT_AUTH_LEN (pkt_p), end_of_pkt, &st); 778 if (st != rpc_s_ok) 779 { 780 return (st); 781 } 782 783 SWAP_INPLACE_32 (&RPC_CN_PKT_CALL_ID (pkt_p), end_of_pkt, &st); 784 if (st != rpc_s_ok) 785 { 786 return (st); 787 } 788 } 789 790 /* 791 * See if the authentication data is valid. 792 */ 793 authenticate = RPC_CN_PKT_AUTH_LEN(pkt_p) != 0; 794 authp = NULL; 795 796 /* 797 * Check for the presence of an OBJECT uuid. 798 */ 799 has_uuid = (RPC_CN_PKT_FLAGS (pkt_p) & RPC_C_CN_FLAGS_OBJECT_UUID) != 0; 800 801 /* 802 * Unpack the packet-type specific part of the packet. We also find the 803 * start of the authentication data if there is any. 804 */ 805 switch (RPC_CN_PKT_PTYPE (pkt_p)) 806 { 807 /* 808 * RPC_CN_BIND_HDR_T 809 */ 810 case RPC_C_CN_PKT_BIND: 811 case RPC_C_CN_PKT_ALTER_CONTEXT: 812 if (swap) 813 { 814 SWAP_INPLACE_16 (&RPC_CN_PKT_MAX_XMIT_FRAG (pkt_p), end_of_pkt, &st); 815 if (st != rpc_s_ok) 816 { 817 return (st); 818 } 819 820 SWAP_INPLACE_16 (&RPC_CN_PKT_MAX_RECV_FRAG (pkt_p), end_of_pkt, &st); 821 if (st != rpc_s_ok) 822 { 823 return (st); 824 } 825 826 SWAP_INPLACE_32 (&RPC_CN_PKT_ASSOC_GROUP_ID (pkt_p), end_of_pkt, &st); 827 if (st != rpc_s_ok) 828 { 829 return (st); 830 } 831 } 832 pconp = (rpc_cn_pres_cont_list_p_t)((unsigned8 *)(&RPC_CN_PKT_ASSOC_GROUP_ID (pkt_p)) + 4); 833 authp = unpack_pres_context_list (pconp, swap, end_of_pkt, &st); 834 if (st != rpc_s_ok) 835 { 836 return (st); 837 } 838 break; 839 840 /* 841 * RPC_CN_BIND_ACK_HDR_T 842 */ 843 case RPC_C_CN_PKT_BIND_ACK: 844 case RPC_C_CN_PKT_ALTER_CONTEXT_RESP: 845 if (swap) 846 { 847 SWAP_INPLACE_16 (&RPC_CN_PKT_MAX_XMIT_FRAG (pkt_p), end_of_pkt, &st); 848 if (st != rpc_s_ok) 849 { 850 return (st); 851 } 852 853 SWAP_INPLACE_16 (&RPC_CN_PKT_MAX_RECV_FRAG (pkt_p), end_of_pkt, &st); 854 if (st != rpc_s_ok) 855 { 856 return (st); 857 } 858 859 SWAP_INPLACE_32 (&RPC_CN_PKT_ASSOC_GROUP_ID (pkt_p), end_of_pkt, &st); 860 if (st != rpc_s_ok) 861 { 862 return (st); 863 } 864 } 865 secadrp = (rpc_cn_port_any_t *) 866 ((unsigned8 *)(pkt_p) + RPC_CN_PKT_SIZEOF_BIND_ACK_HDR); 867 presp = unpack_port_any (secadrp, drepp, end_of_pkt, &st); 868 if (st != rpc_s_ok) 869 { 870 return (st); 871 } 872 873 force_alignment (4, (unsigned8 **)&presp); 874 authp = unpack_pres_result_list (presp, swap, end_of_pkt, &st); 875 if (st != rpc_s_ok) 876 { 877 return (st); 878 } 879 break; 880 881 /* 882 * RPC_CN_BIND_NACK_HDR_T 883 */ 884 case RPC_C_CN_PKT_BIND_NAK: 885 if (swap) 886 { 887 SWAP_INPLACE_16 (&RPC_CN_PKT_PROV_REJ_REASON (pkt_p), end_of_pkt, &st); 888 if (st != rpc_s_ok) 889 { 890 return (st); 891 } 892 } 893 versp = &RPC_CN_PKT_VERSIONS (pkt_p); 894 authp = unpack_versions_supported (versp); 895 break; 896 897 /* 898 * RPC_CN_REQUEST_HDR_T 899 */ 900 case RPC_C_CN_PKT_REQUEST: 901 if (swap) 902 { 903 SWAP_INPLACE_32 (&RPC_CN_PKT_ALLOC_HINT (pkt_p), end_of_pkt, &st); 904 if (st != rpc_s_ok) 905 { 906 return (st); 907 } 908 909 SWAP_INPLACE_16 (&RPC_CN_PKT_PRES_CONT_ID (pkt_p), end_of_pkt, &st); 910 if (st != rpc_s_ok) 911 { 912 return (st); 913 } 914 915 SWAP_INPLACE_16 (&RPC_CN_PKT_OPNUM (pkt_p), end_of_pkt, &st); 916 if (st != rpc_s_ok) 917 { 918 return (st); 919 } 920 921 if (has_uuid) 922 { 923 SWAP_INPLACE_UUID (&RPC_CN_PKT_OBJECT (pkt_p), end_of_pkt, &st); 924 if (st != rpc_s_ok) 925 { 926 return (st); 927 } 928 } 929 } 930 authp = end_of_stub_data (pkt_p); 931 break; 932 933 /* 934 * RPC_CN_RESPONSE_HDR_T 935 */ 936 case RPC_C_CN_PKT_RESPONSE: 937 if (swap) 938 { 939 SWAP_INPLACE_32 (&RPC_CN_PKT_ALLOC_HINT (pkt_p), end_of_pkt, &st); 940 if (st != rpc_s_ok) 941 { 942 return (st); 943 } 944 945 SWAP_INPLACE_16 (&RPC_CN_PKT_PRES_CONT_ID (pkt_p), end_of_pkt, &st); 946 if (st != rpc_s_ok) 947 { 948 return (st); 949 } 950 } 951 authp = end_of_stub_data (pkt_p); 952 break; 953 954 /* 955 * RPC_CN_FAULT_HDR_T 956 */ 957 case RPC_C_CN_PKT_FAULT: 958 if (swap) 959 { 960 SWAP_INPLACE_32 (&RPC_CN_PKT_ALLOC_HINT (pkt_p), end_of_pkt, &st); 961 if (st != rpc_s_ok) 962 { 963 return (st); 964 } 965 966 SWAP_INPLACE_16 (&RPC_CN_PKT_PRES_CONT_ID (pkt_p), end_of_pkt, &st); 967 if (st != rpc_s_ok) 968 { 969 return (st); 970 } 971 972 SWAP_INPLACE_32 (&RPC_CN_PKT_STATUS (pkt_p), end_of_pkt, &st); 973 if (st != rpc_s_ok) 974 { 975 return (st); 976 } 977 } 978 authp = end_of_stub_data (pkt_p); 979 break; 980 981 /* 982 * RPC_CN_AUTH3_HDR_T 983 */ 984 case RPC_C_CN_PKT_SHUTDOWN: 985 case RPC_C_CN_PKT_AUTH3: 986 case RPC_C_CN_PKT_REMOTE_ALERT: 987 case RPC_C_CN_PKT_ORPHANED: 988 break; 989 990 default: 991 /* "(%s) Illegal or unknown packet type: %x\n" */ 992 rpc_dce_svc_printf ( 993 __FILE__, __LINE__, 994 "%s %x", 995 rpc_svc_cn_pkt, 996 svc_c_sev_warning, 997 rpc_m_bad_pkt_type, 998 "rpc__cn_unpack_hdr", 999 RPC_CN_PKT_PTYPE(pkt_p) ); 1000 return (rpc_s_bad_pkt); 1001 } 1002 1003 /* 1004 * Unpack the authentication part of the packet if it exists. 1005 */ 1006 if (authenticate && swap) 1007 { 1008 switch (RPC_CN_PKT_PTYPE (pkt_p)) 1009 { 1010 case RPC_C_CN_PKT_BIND: 1011 case RPC_C_CN_PKT_ALTER_CONTEXT: 1012 case RPC_C_CN_PKT_BIND_ACK: 1013 case RPC_C_CN_PKT_ALTER_CONTEXT_RESP: 1014 case RPC_C_CN_PKT_BIND_NAK: 1015 case RPC_C_CN_PKT_AUTH3: 1016 { 1017#ifdef DEBUG 1018 char *p; 1019#endif 1020 rpc_authn_protocol_id_t authn_protocol; 1021 1022 authp = RPC_CN_PKT_AUTH_TLR (pkt_p, RPC_CN_PKT_FRAG_LEN (pkt_p)); 1023#ifdef DEBUG 1024 p = (char *)authp; 1025 force_alignment(4, (unsigned8 **)&authp); 1026 if (p != (char *)authp) 1027 { 1028 /* 1029 * rpc_m_unalign_authtrl 1030 * "(%s) Unaligned RPC_CN_PKT_AUTH_TRL" 1031 */ 1032 rpc_dce_svc_printf ( 1033 __FILE__, __LINE__, 1034 "%s", 1035 rpc_svc_cn_pkt, 1036 svc_c_sev_fatal | svc_c_action_abort, 1037 rpc_m_unalign_authtrl, 1038 "rpc__cn_unpack_hdr" ); 1039 return (rpc_s_bad_pkt); 1040 } 1041#endif 1042 authn_protocol = RPC_CN_AUTH_CVT_ID_WIRE_TO_API (authp->auth_type, &st); 1043 if (st == rpc_s_ok) 1044 { 1045 RPC_CN_AUTH_TLR_UNPACK (authn_protocol, 1046 pkt_p, RPC_CN_PKT_AUTH_LEN (pkt_p), drepp); 1047 } 1048 break; 1049 } 1050 1051 default: 1052 /* 1053 * We do not need the auth trailer of the other packet 1054 * types since they are thrown away after recv_check. 1055 * So don't bother to unpack them in these cases. 1056 */ 1057 break; 1058 } 1059 } 1060 1061 return (rpc_s_ok); 1062} 1063 1064 1065/* 1066**++ 1067** 1068** ROUTINE NAME: rpc__cn_pkt_format_common 1069** 1070** SCOPE: PRIVATE - declared in cnpkt.h 1071** 1072** DESCRIPTION: 1073** 1074** This routine will format the fields common to all packet 1075** types in the NCA connection protocol. 1076** 1077** INPUTS: 1078** 1079** pkt_p a pointer to the packet to be formatted 1080** ptype the packet type 1081** flags the packet flags 1082** frag_len the length of the packet (header and body) 1083** auth_len the length of the authentication trailer 1084** call_id call identifier 1085** 1086** INPUTS/OUTPUTS: none 1087** 1088** OUTPUTS: none 1089** 1090** IMPLICIT INPUTS: none 1091** 1092** IMPLICIT OUTPUTS: none 1093** 1094** FUNCTION VALUE: none 1095** 1096** SIDE EFFECTS: none 1097** 1098**-- 1099**/ 1100 1101PRIVATE void rpc__cn_pkt_format_common 1102( 1103 rpc_cn_packet_p_t pkt_p, 1104 unsigned32 ptype, 1105 unsigned32 flags, 1106 unsigned32 frag_len, 1107 unsigned32 auth_len, 1108 unsigned32 call_id, 1109 unsigned8 minor_version 1110) 1111{ 1112 /* 1113 * First copy the template common packet header. 1114 */ 1115 memcpy (pkt_p, &rpc_g_cn_common_hdr, sizeof (rpc_g_cn_common_hdr)); 1116 1117 /* 1118 * Now fill in the fields based on the input args to this 1119 * routine. 1120 */ 1121 RPC_CN_PKT_PTYPE (pkt_p) = (unsigned8)ptype; 1122 RPC_CN_PKT_FLAGS (pkt_p) = (unsigned8)flags; 1123 RPC_CN_PKT_FRAG_LEN (pkt_p) = (unsigned16)frag_len; 1124 RPC_CN_PKT_AUTH_LEN (pkt_p) = (unsigned16)auth_len; 1125 RPC_CN_PKT_CALL_ID (pkt_p) = call_id; 1126 RPC_CN_PKT_VERS_MINOR (pkt_p) = minor_version; 1127} 1128 1129 1130/* 1131**++ 1132** 1133** ROUTINE NAME: rpc__cn_stats_print 1134** 1135** SCOPE: PRIVATE - declared in cnpkt.h 1136** 1137** DESCRIPTION: 1138** 1139** This routine will dump all statistics kept by the CN protocol. 1140** 1141** INPUTS: none 1142** 1143** INPUTS/OUTPUTS: none 1144** 1145** OUTPUTS: none 1146** 1147** IMPLICIT INPUTS: none 1148** 1149** IMPLICIT OUTPUTS: none 1150** 1151** FUNCTION VALUE: none 1152** 1153** SIDE EFFECTS: none 1154** 1155**-- 1156**/ 1157 1158PRIVATE void rpc__cn_stats_print (void) 1159{ 1160 unsigned16 i; 1161 1162 RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, 1163 ("RPC CN Protocol Statistics")); 1164 RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, 1165 ("--------------------------------------------------------")); 1166 RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, 1167 ("Calls sent: %9u", rpc_g_cn_mgmt.calls_sent)); 1168 RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, 1169 ("Calls rcvd: %9u", rpc_g_cn_mgmt.calls_rcvd)); 1170 RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, 1171 ("Pkts sent: %9u", rpc_g_cn_mgmt.pkts_sent)); 1172 RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, 1173 ("Pkts rcvd: %9u", rpc_g_cn_mgmt.pkts_rcvd)); 1174 RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, 1175 ("Connects established: %9u", rpc_g_cn_mgmt.connections)); 1176 RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, 1177 ("Connects broken: %9u", rpc_g_cn_mgmt.closed_connections)); 1178 RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, 1179 ("Associations alloced: %9u", rpc_g_cn_mgmt.alloced_assocs)); 1180 RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, 1181 ("Associations dealloced:%9u", rpc_g_cn_mgmt.dealloced_assocs)); 1182 RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, 1183 ("Associations aborted: %9u", rpc_g_cn_mgmt.aborted_assocs)); 1184 RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, 1185 ("Association groups: %9u", rpc_g_cn_mgmt.assoc_grps)); 1186 1187 RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, 1188 ("Breakdown by packet type sent rcvd")); 1189 RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, 1190 ("-------------------------------------------------------------------")); 1191 1192 for (i = 0; i <= RPC_C_CN_PKT_MAX_TYPE; i++) 1193 { 1194 RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, 1195 ("(%02u) %-10s %9u %9u", 1196 i, rpc__cn_pkt_name(i), 1197 rpc_g_cn_mgmt.pstats[i].sent, 1198 rpc_g_cn_mgmt.pstats[i].rcvd)); 1199 } 1200} 1201 1202 1203/* 1204**++ 1205** 1206** ROUTINE NAME: rpc__cn_pkt_name 1207** 1208** SCOPE: PRIVATE - declared in cnpkt.h 1209** 1210** DESCRIPTION: 1211** 1212** Return the string name for a type of packet. This can't simply be 1213** a variable because of the vagaries of global libraries. 1214** 1215** INPUTS: 1216** 1217** ptype The packet type. 1218** 1219** INPUTS/OUTPUTS: none 1220** 1221** OUTPUTS: none 1222** 1223** IMPLICIT INPUTS: none 1224** 1225** IMPLICIT OUTPUTS: none 1226** 1227** FUNCTION VALUE: none 1228** 1229** SIDE EFFECTS: none 1230** 1231**-- 1232**/ 1233 1234PRIVATE const char *rpc__cn_pkt_name 1235( 1236 unsigned32 ptype ATTRIBUTE_UNUSED 1237) 1238{ 1239#ifndef DEBUG 1240 1241 return(""); 1242 1243#else 1244 1245 static const char *names[RPC_C_CN_PKT_MAX_TYPE + 1] = 1246 { 1247 "REQUEST ", 1248 "PING ", 1249 "RESPONSE ", 1250 "FAULT ", 1251 "WORKING ", 1252 "NOCALL ", 1253 "REJECT ", 1254 "ACK ", 1255 "QUIT ", 1256 "FACK ", 1257 "QUACK ", 1258 "BIND ", 1259 "BIND_ACK ", 1260 "BIND_NAK ", 1261 "ALT_CTXT ", 1262 "ALT_CTXT_RESP", 1263 "AUTH3 ", 1264 "SHUTDOWN ", 1265 "REMOTE_ALERT ", 1266 "ORPHANED " 1267 }; 1268 1269 return((int) ptype > RPC_C_CN_PKT_MAX_TYPE ? "BOGUS PACKET TYPE" : names[(int) ptype]); 1270 1271#endif 1272} 1273 1274 1275/* 1276**++ 1277** 1278** ROUTINE NAME: rpc__cn_pkt_crc_compute 1279** 1280** SCOPE: PRIVATE - declared in cnpkt.h 1281** 1282** DESCRIPTION: 1283** 1284** Compute a CRC-32/AUTODIN-II. 1285** 1286** First, the polynomial itself and its table of feedback terms. The 1287** polynomial is 1288** X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 1289** Note that we take it "backwards" and put the highest-order term in 1290** the lowest-order bit. The X^32 term is "implied"; the LSB is the 1291** X^31 term, etc. The X^0 term (usually shown as "+1") results in 1292** the MSB being 1. 1293 1294** Note that the usual hardware shift register implementation, which 1295** is what we're using (we're merely optimizing it by doing eight-bit 1296** chunks at a time) shifts bits into the lowest-order term. In our 1297** implementation, that means shifting towards the right. Why do we 1298** do it this way? Because the calculated CRC must be transmitted in 1299** order from highest-order term to lowest-order term. UARTs transmit 1300** characters in order from LSB to MSB. By storing the CRC this way, 1301** we hand it to the UART in the order low-byte to high-byte; the UART 1302** sends each low-bit to hight-bit; and the result is transmission bit 1303** by bit from highest- to lowest-order term without requiring any bit 1304** shuffling on our part. Reception works similarly. 1305 1306** The feedback terms table consists of 256, 32-bit entries. Notes: 1307** 1308** 1. The table can be generated at runtime if desired; code to do so 1309** is shown later. It might not be obvious, but the feedback 1310** terms simply represent the results of eight shift/xor opera- 1311** tions for all combinations of data and CRC register values. 1312** 1313** 2. The CRC accumulation logic is the same for all CRC polynomials, 1314** be they sixteen or thirty-two bits wide. You simply choose the 1315** appropriate table. Alternatively, because the table can be 1316** generated at runtime, you can start by generating the table for 1317** the polynomial in question and use exactly the same "updcrc", 1318** if your application needn't simultaneously handle two CRC 1319** polynomials. (Note, however, that XMODEM is strange.) 1320** 1321** 3. For 16-bit CRCs, the table entries need be only 16 bits wide; 1322** of course, 32-bit entries work OK if the high 16 bits are zero. 1323** 1324** 4. The values must be right-shifted by eight bits by the "updcrc" 1325** logic; the shift must be unsigned (bring in zeroes). On some 1326** hardware you could probably optimize the shift in assembler by 1327** using byte-swap instructions. 1328** 1329** INPUTS: 1330** 1331** block The block whose checksum is to be computed. 1332** block_len The length, in bytes, of the block. 1333** 1334** INPUTS/OUTPUTS: none 1335** 1336** OUTPUTS: none 1337** 1338** IMPLICIT INPUTS: none 1339** 1340** IMPLICIT OUTPUTS: none 1341** 1342** FUNCTION VALUE: unsigned32 1343** 1344** The 32-bit CRC of the block. 1345** 1346** SIDE EFFECTS: none 1347** 1348**-- 1349**/ 1350 1351PRIVATE unsigned32 rpc__cn_pkt_crc_compute 1352( 1353 unsigned8 *block, 1354 unsigned32 block_len 1355) 1356{ 1357 register unsigned_char_t *data; 1358 register unsigned32 c = 0; 1359 register unsigned32 idx; 1360 unsigned32 i; 1361 static unsigned32 crc_table[256] = 1362 { 1363 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 1364 0x076dc419U, 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 1365 0x0edb8832U, 0x79dcb8a4U, 0xe0d5e91eU, 0x97d2d988U, 1366 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, 0x90bf1d91U, 1367 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, 1368 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 1369 0x136c9856U, 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 1370 0x14015c4fU, 0x63066cd9U, 0xfa0f3d63U, 0x8d080df5U, 1371 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, 0xa2677172U, 1372 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, 1373 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 1374 0x32d86ce3U, 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 1375 0x26d930acU, 0x51de003aU, 0xc8d75180U, 0xbfd06116U, 1376 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, 0xb8bda50fU, 1377 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, 1378 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 1379 0x76dc4190U, 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 1380 0x71b18589U, 0x06b6b51fU, 0x9fbfe4a5U, 0xe8b8d433U, 1381 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, 0xe10e9818U, 1382 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U, 1383 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 1384 0x6c0695edU, 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 1385 0x65b0d9c6U, 0x12b7e950U, 0x8bbeb8eaU, 0xfcb9887cU, 1386 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, 0xfbd44c65U, 1387 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, 1388 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 1389 0x4369e96aU, 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 1390 0x44042d73U, 0x33031de5U, 0xaa0a4c5fU, 0xdd0d7cc9U, 1391 0x5005713cU, 0x270241aaU, 0xbe0b1010U, 0xc90c2086U, 1392 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU, 1393 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 1394 0x59b33d17U, 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 1395 0xedb88320U, 0x9abfb3b6U, 0x03b6e20cU, 0x74b1d29aU, 1396 0xead54739U, 0x9dd277afU, 0x04db2615U, 0x73dc1683U, 1397 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U, 1398 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 1399 0xf00f9344U, 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 1400 0xf762575dU, 0x806567cbU, 0x196c3671U, 0x6e6b06e7U, 1401 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, 0x67dd4accU, 1402 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U, 1403 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 1404 0xd1bb67f1U, 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 1405 0xd80d2bdaU, 0xaf0a1b4cU, 0x36034af6U, 0x41047a60U, 1406 0xdf60efc3U, 0xa867df55U, 0x316e8eefU, 0x4669be79U, 1407 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U, 1408 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 1409 0xc5ba3bbeU, 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 1410 0xc2d7ffa7U, 0xb5d0cf31U, 0x2cd99e8bU, 0x5bdeae1dU, 1411 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, 0x026d930aU, 1412 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U, 1413 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 1414 0x92d28e9bU, 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 1415 0x86d3d2d4U, 0xf1d4e242U, 0x68ddb3f8U, 0x1fda836eU, 1416 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, 0x18b74777U, 1417 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, 1418 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 1419 0xa00ae278U, 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 1420 0xa7672661U, 0xd06016f7U, 0x4969474dU, 0x3e6e77dbU, 1421 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U, 0x37d83bf0U, 1422 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U, 1423 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 1424 0xbad03605U, 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 1425 0xb3667a2eU, 0xc4614ab8U, 0x5d681b02U, 0x2a6f2b94U, 1426 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, 0x2d02ef8dU 1427 }; 1428 1429 data = (unsigned_char_t *) block; 1430 for (i = 0; i < block_len; i++) 1431 { 1432 idx = (data[i] ^ c); 1433 idx &= 0xff; 1434 c >>= 8; 1435 c ^= crc_table[idx]; 1436 } 1437 1438 return (c); 1439} 1440