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