Q931mes.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   FileName:     Q931mes.c
00004 
00005   Contents:     Pack/Unpack functions. These functions will unpack a Q931 
00006                 message from the bit packed original format into structs
00007                 that contains variables sized by the user. It will also pack
00008                 the struct back into a Q.931 message as required.
00009 
00010                 See q931.h for description. 
00011 
00012   License/Copyright:
00013 
00014   Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved.
00015   email:janvb@caselaboratories.com  
00016 
00017   Redistribution and use in source and binary forms, with or without 
00018   modification, are permitted provided that the following conditions are 
00019   met:
00020 
00021         * Redistributions of source code must retain the above copyright notice, 
00022           this list of conditions and the following disclaimer.
00023         * Redistributions in binary form must reproduce the above copyright notice, 
00024           this list of conditions and the following disclaimer in the documentation 
00025           and/or other materials provided with the distribution.
00026         * Neither the name of the Case Labs, Ltd nor the names of its contributors 
00027           may be used to endorse or promote products derived from this software 
00028           without specific prior written permission.
00029 
00030   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
00031   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
00032   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
00033   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
00034   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00035   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
00036   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00037   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
00038   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
00039   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
00040   POSSIBILITY OF SUCH DAMAGE.
00041 
00042 *****************************************************************************/
00043 
00044 #include <assert.h>
00045 
00046 #define Q931PRIVATE
00047 #include "Q931.h"
00048 
00049 /* 
00050  * TODO: Convert this into something like:
00051  *
00052  * { Q931mes_ALERTING,
00053  *                       { Q931ie_BEARER_CAPABILITY, 4, 12, Q931_IEF_TO_BOTH },
00054  *                       { Q931ie_CHANNEL_ID,        2,  0, Q931_IEF_TO_BOTH },
00055  *                       ...
00056  * },
00057  */
00058 
00059 struct Q931MessageIE Q931MessageIEs[] = {
00060         /*
00061          * ITU-T Q.931 IE table
00062          */
00063 
00064         /* ALERTING */
00065         { Q931mes_ALERTING, 8, {
00066                         { Q931ie_BEARER_CAPABILITY,        4, 12, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00067                         { Q931ie_CHANNEL_IDENTIFICATION,   2,  0, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00068                         { Q931ie_PROGRESS_INDICATOR,       2,  4, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00069                         { Q931ie_DISPLAY,                  2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00070                         { Q931ie_SIGNAL,                   2,  3, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00071                         { Q931ie_HIGH_LAYER_COMPATIBILITY, 2,  5, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00072 
00073                         { Q932ie_FACILITY,                 2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00074                         { Q932ie_EXTENDED_FACILITY,        2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00075 
00076                         { 0, 0, 0, 0 },
00077         }},
00078 
00079         /* CALL PROCEEDING */
00080         { Q931mes_CALL_PROCEEDING, 8, {
00081                         { Q931ie_BEARER_CAPABILITY,        4, 12, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00082                         { Q931ie_CHANNEL_IDENTIFICATION,   2,  0, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00083                         { Q931ie_PROGRESS_INDICATOR,       2,  4, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00084                         { Q931ie_DISPLAY,                  2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00085                         { Q931ie_HIGH_LAYER_COMPATIBILITY, 2,  5, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00086 
00087                         { Q932ie_FACILITY,                 2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00088                         { Q932ie_EXTENDED_FACILITY,        2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00089 
00090                         { 0, 0, 0, 0 },
00091         }},
00092 
00093         /* CONNECT */
00094         { Q931mes_CONNECT, 8, {
00095                         { Q931ie_BEARER_CAPABILITY,        4, 12, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00096                         { Q931ie_CHANNEL_IDENTIFICATION,   2,  0, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00097                         { Q931ie_PROGRESS_INDICATOR,       2,  4, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00098                         { Q931ie_DISPLAY,                  2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00099                         { Q931ie_DATETIME,                 8,  8, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00100                         { Q931ie_SIGNAL,                   2,  3, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00101                         { Q931ie_LOW_LAYER_COMPATIBILITY,  2, 18, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00102                         { Q931ie_HIGH_LAYER_COMPATIBILITY, 2,  5, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00103 
00104                         { Q931ie_CONNECTED_NUMBER,         4, 24, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00105 /* Q.951.5 */           { Q931ie_CONNECTED_SUBADDRESS,     2, 23, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00106 
00107                         { Q932ie_FACILITY,                 2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00108                         { Q932ie_EXTENDED_FACILITY,        2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00109 
00110                         { 0, 0, 0, 0 },
00111         }},
00112 
00113         /* CONNECT ACKNOWLEDGE */
00114         { Q931mes_CONNECT_ACKNOWLEDGE, 8, {
00115                         { Q931ie_DISPLAY,           2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00116                         { Q931ie_SIGNAL,            2,  3, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00117 
00118                         { Q932ie_FACILITY,          2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00119                         { Q932ie_EXTENDED_FACILITY, 2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00120 
00121                         { 0, 0, 0, 0 },
00122         }},
00123 
00124         /* DISCONNECT */
00125         { Q931mes_DISCONNECT, 8, {
00126                         { Q931ie_CAUSE,              4, 32, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH | Q931_IEF_MANDATORY },
00127                         { Q931ie_PROGRESS_INDICATOR, 2,  4, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00128                         { Q931ie_DISPLAY,            2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00129                         { Q931ie_SIGNAL,             2,  3, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00130 
00131                         { Q932ie_FACILITY,           2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00132                         { Q932ie_EXTENDED_FACILITY,  2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00133 
00134                         { 0, 0, 0, 0 },
00135         }},
00136 
00137         /* INFORMATION */
00138         { Q931mes_INFORMATION, 8, {
00139                         { Q931ie_SENDING_COMPLETE,    1,  1, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00140                         { Q931ie_DISPLAY,             2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00141                         { Q931ie_KEYPAD_FACILITY,     2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_NET },
00142                         { Q931ie_SIGNAL,              2,  3, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00143                         { Q931ie_CALLED_PARTY_NUMBER, 2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00144                         { 0, 0, 0, 0 },
00145         }},
00146 
00147         /* NOTIFY */
00148         { Q931mes_NOTIFY, 8, {
00149                         { Q931ie_BEARER_CAPABILITY,      2, 12, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00150                         { Q931ie_NOTIFICATION_INDICATOR, 3,  3, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH | Q931_IEF_MANDATORY },
00151                         { Q931ie_DISPLAY,                2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00152                         { 0, 0, 0, 0 },
00153         }},
00154 
00155         /* PROGRESS */
00156         { Q931mes_PROGRESS, 8, {
00157                         { Q931ie_BEARER_CAPABILITY,        4, 12, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00158                         { Q931ie_CAUSE,                    4, 32, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00159                         { Q931ie_PROGRESS_INDICATOR,       2,  4, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH | Q931_IEF_MANDATORY },
00160                         { Q931ie_DISPLAY,                  2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00161                         { Q931ie_HIGH_LAYER_COMPATIBILITY, 2,  5, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00162 
00163                         { Q932ie_FACILITY,                 2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00164                         { Q932ie_EXTENDED_FACILITY,        2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00165 
00166                         { 0, 0, 0, 0 },
00167         }},
00168 
00169         /* RELEASE */
00170         { Q931mes_RELEASE, 8, {
00171                         { Q931ie_CAUSE,             4, 32, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00172                         { Q931ie_DISPLAY,           2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00173                         { Q931ie_SIGNAL,            2,  3, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00174 
00175                         { Q932ie_FACILITY,          2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00176                         { Q932ie_EXTENDED_FACILITY, 2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00177 
00178                         { 0, 0, 0, 0 },
00179         }},
00180 
00181         /* RELEASE COMPLETE */
00182         { Q931mes_RELEASE_COMPLETE, 8, {
00183                         { Q931ie_CAUSE,             4, 32, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00184                         { Q931ie_DISPLAY,           2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00185                         { Q931ie_SIGNAL,            2,  3, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00186 
00187                         { Q932ie_FACILITY,          2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00188                         { Q932ie_EXTENDED_FACILITY, 2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00189 
00190                         { 0, 0, 0, 0 },
00191         }},
00192 
00193         /* RESUME */
00194         { Q931mes_RESUME, 8, {
00195                         { Q931ie_CALL_IDENTITY, 2, 10, Q931_IE_CODESET_0, Q931_IEF_TO_NET },
00196                         { 0, 0, 0, 0 },
00197         }},
00198 
00199         /* RESUME ACKNOWLEDGE */
00200         { Q931mes_RESUME_ACKNOWLEDGE, 8, {
00201                         { Q931ie_CHANNEL_IDENTIFICATION, 3,  0, Q931_IE_CODESET_0, Q931_IEF_TO_USER | Q931_IEF_MANDATORY },
00202                         { Q931ie_DISPLAY,                2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00203                         { 0, 0, 0, 0 },
00204         }},
00205 
00206         /* RESUME REJECT */
00207         { Q931mes_RESUME_REJECT, 8, {
00208                         { Q931ie_CAUSE,    4, 32, Q931_IE_CODESET_0, Q931_IEF_TO_USER | Q931_IEF_MANDATORY },
00209                         { Q931ie_DISPLAY,  4, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00210                         { 0, 0, 0, 0 },
00211         }},
00212 
00213         /* SETUP */
00214         { Q931mes_SETUP, 8, {
00215                         { Q931ie_SENDING_COMPLETE,            1,  1, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00216                         { Q931ie_REPEAT_INDICATOR,            1,  1, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },             /* Multiple occurrences possible, context! */
00217                         { Q931ie_BEARER_CAPABILITY,           4, 12, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH | Q931_IEF_MANDATORY },
00218                         { Q931ie_CHANNEL_IDENTIFICATION,      3,  0, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00219                         { Q931ie_PROGRESS_INDICATOR,          2,  4, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00220                         { Q931ie_NETWORK_SPECIFIC_FACILITIES, 2,  0, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00221                         { Q931ie_DISPLAY,                     2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00222                         { Q931ie_DATETIME,                    8,  8, Q931_IE_CODESET_0, Q931_IEF_TO_NET },
00223                         { Q931ie_KEYPAD_FACILITY,             2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_NET },
00224                         { Q931ie_SIGNAL,                      2,  3, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00225                         { Q931ie_CALLING_PARTY_NUMBER,        2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00226                         { Q931ie_CALLING_PARTY_SUBADDRESS,    2, 23, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00227                         { Q931ie_CALLED_PARTY_NUMBER,         2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00228                         { Q931ie_CALLED_PARTY_SUBADDRESS,     2, 23, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00229                         { Q931ie_TRANSIT_NETWORK_SELECTION,   2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_NET },
00230                         { Q931ie_LOW_LAYER_COMPATIBILITY,     2, 18, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00231                         { Q931ie_HIGH_LAYER_COMPATIBILITY,    2,  5, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00232 
00233                         { Q932ie_FACILITY,                    2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00234                         { Q932ie_EXTENDED_FACILITY,           2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00235 
00236                         { 0, 0, 0, 0 },
00237         }},
00238 
00239         /* SETUP ACKNOWLEDGE */
00240         { Q931mes_SETUP_ACKNOWLEDGE, 8, {
00241                         { Q931ie_CHANNEL_IDENTIFICATION, 3,  0, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00242                         { Q931ie_PROGRESS_INDICATOR,     2,  4, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00243                         { Q931ie_DISPLAY,                2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00244                         { Q931ie_SIGNAL,                 2,  3, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00245 
00246                         { Q932ie_FACILITY,               2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00247                         { Q932ie_EXTENDED_FACILITY,      2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00248 
00249                         { 0, 0, 0, 0 },
00250         }},
00251 
00252         /* STATUS */
00253         { Q931mes_STATUS, 8, {
00254                         { Q931ie_CAUSE,      4, 32, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH | Q931_IEF_MANDATORY },
00255                         { Q931ie_CALL_STATE, 3,  3, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH | Q931_IEF_MANDATORY },
00256                         { Q931ie_DISPLAY,    2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00257                         { 0, 0, 0, 0 },
00258         }},
00259 
00260         /* STATUS ENQUIRY */
00261         { Q931mes_STATUS_ENQUIRY, 8, {
00262                         { Q931ie_DISPLAY, 2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00263                         { 0, 0, 0, 0 },
00264         }},
00265 
00266         /* SUSPEND */
00267         { Q931mes_SUSPEND, 8, {
00268                         { Q931ie_CALL_IDENTITY, 2, 10, Q931_IE_CODESET_0, Q931_IEF_TO_NET },
00269                         { 0, 0, 0, 0 },
00270         }},
00271 
00272         /* SUSPEND ACKNOWLEDGE */
00273         { Q931mes_SUSPEND_ACKNOWLEDGE, 8, {
00274                         { Q931ie_DISPLAY, 2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00275                         { 0, 0, 0, 0 },
00276         }},
00277 
00278         /* SUSPEND REJECT */
00279         { Q931mes_SUSPEND_REJECT, 8, {
00280                         { Q931ie_CAUSE,   4, 32, Q931_IE_CODESET_0, Q931_IEF_TO_USER | Q931_IEF_MANDATORY },
00281                         { Q931ie_DISPLAY, 4, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00282                         { 0, 0, 0, 0 },
00283         }},
00284 
00285         /* RESTART */
00286         { Q931mes_RESTART, 8, {
00287                         { Q931ie_RESTART_INDICATOR,      3,  3, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH | Q931_IEF_MANDATORY },
00288                         { Q931ie_CHANNEL_IDENTIFICATION, 3,  0, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00289                         { Q931ie_DISPLAY,                4, 34, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00290                         { 0, 0, 0, 0 },
00291         }},
00292 
00293         /* RESTART ACKNOWLEDGE */
00294         { Q931mes_RESTART_ACKNOWLEDGE, 8, {
00295                         { Q931ie_RESTART_INDICATOR,      3,  3, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH | Q931_IEF_MANDATORY },
00296                         { Q931ie_CHANNEL_IDENTIFICATION, 3,  0, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00297                         { Q931ie_DISPLAY,                4, 34, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00298                         { 0, 0, 0, 0 },
00299         }},
00300 
00301 
00302         /*
00303          * ITU-T Q.932 IE table
00304          */
00305 
00306         /* HOLD */
00307         { Q932mes_HOLD, 8, {
00308                         { Q931ie_DISPLAY,           2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00309 
00310                         { Q932ie_FACILITY,          2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00311                         { Q932ie_EXTENDED_FACILITY, 2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00312                         { 0, 0, 0, 0 },
00313         }},
00314 
00315         /* HOLD ACKNOWLEDGE */
00316         { Q932mes_HOLD_ACKNOWLEDGE, 8, {
00317                         { Q931ie_DISPLAY,           2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00318 
00319                         { Q932ie_FACILITY,          2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00320                         { Q932ie_EXTENDED_FACILITY, 2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00321                         { 0, 0, 0, 0 },
00322         }},
00323 
00324         /* HOLD REJECT */
00325         { Q932mes_HOLD_REJECT, 8, {
00326                         { Q931ie_CAUSE,             4, 32, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH | Q931_IEF_MANDATORY },
00327                         { Q931ie_DISPLAY,           2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00328 
00329                         { Q932ie_FACILITY,          2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00330                         { Q932ie_EXTENDED_FACILITY, 2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00331                         { 0, 0, 0, 0 },
00332         }},
00333 
00334         /* REGISTER */
00335         { Q932mes_REGISTER, 8, {
00336                         { Q932ie_FACILITY,          2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH | Q931_IEF_MANDATORY },
00337                         { Q932ie_EXTENDED_FACILITY, 2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00338                         { Q931ie_DISPLAY,           2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00339 
00340                         { 0, 0, 0, 0 },
00341         }},
00342 
00343         /* RETRIEVE */
00344         { Q932mes_RETRIEVE, 8, {
00345                         { Q931ie_CHANNEL_IDENTIFICATION, 3,  0, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00346                         { Q931ie_DISPLAY,                2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00347 
00348                         { Q932ie_FACILITY,               2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00349                         { Q932ie_EXTENDED_FACILITY,      2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00350                         { 0, 0, 0, 0 },
00351         }},
00352 
00353         /* RETRIEVE ACKNOWLEDGE */
00354         { Q932mes_RETRIEVE_ACKNOWLEDGE, 8, {
00355                         { Q931ie_CHANNEL_IDENTIFICATION, 3,  0, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00356                         { Q931ie_DISPLAY,                2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00357 
00358                         { Q932ie_FACILITY,               2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00359                         { Q932ie_EXTENDED_FACILITY,      2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00360                         { 0, 0, 0, 0 },
00361         }},
00362 
00363         /* RETRIEVE REJECT */
00364         { Q932mes_RETRIEVE_REJECT, 8, {
00365                         { Q931ie_CAUSE,             4, 32, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH | Q931_IEF_MANDATORY },
00366                         { Q931ie_DISPLAY,           2, 34, Q931_IE_CODESET_0, Q931_IEF_TO_USER },
00367 
00368                         { Q932ie_FACILITY,          2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00369                         { Q932ie_EXTENDED_FACILITY, 2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00370                         { 0, 0, 0, 0 },
00371         }},
00372 
00373         /* FACILITY */
00374         { Q932mes_FACILITY, 8, {
00375                         { Q932ie_FACILITY,          8, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH | Q931_IEF_MANDATORY },
00376                         { Q932ie_EXTENDED_FACILITY, 2, 99, Q931_IE_CODESET_0, Q931_IEF_TO_BOTH },
00377                         { 0, 0, 0, 0 },
00378         }},
00379 
00380         /* TODO... */
00381 
00382         { 0, 0, {{ 0, 0, 0, 0 }}},
00383 };
00384 
00394 static struct Q931MessageIEEntry *Q931MesgIEsGetEntry(struct Q931Dialect *dialect, L3INT MesType, L3UCHAR ProtDisc, L3UCHAR id, L3UCHAR *index)
00395 {
00396         struct Q931MessageIE *mes = NULL;
00397         struct Q931MessageIE *map = NULL;
00398         struct Q931MessageIEEntry *ie;
00399         int i, offset = 0;
00400 
00401         assert(dialect);
00402 
00403         map = Q931DialectGetMesIEMap(dialect);
00404         if (!map) {
00405                 return NULL;
00406         }
00407 
00408         if (index) {
00409                 offset = *index;
00410         }
00411 
00412         for (i = offset; map[i].id; i++) {
00413                 if(map[i].id == MesType && map[i].protdisc == ProtDisc) {
00414                         mes = &map[i];
00415                         break;
00416                 }
00417         }
00418         if (!mes) {
00419                 /* Message not found */
00420                 return NULL;
00421         }
00422 
00423         if (index) {
00424                 *index = i;
00425         }
00426 
00427         ie = mes->ies;
00428         while (ie->id) {
00429                 if (ie->id == id) {
00430                         return ie;
00431                 }
00432                 ie++;
00433         }
00434         return NULL;
00435 }
00436 
00444 static struct Q931MessageIEEntry *Q931MesgIEsGetFirstEntry(struct Q931Dialect *dialect, L3INT MesType, L3UCHAR ProtDisc)
00445 {
00446         struct Q931MessageIE *map = NULL;
00447 
00448         assert(dialect);
00449 
00450         map = Q931DialectGetMesIEMap(dialect);
00451         if (!map) {
00452                 return NULL;
00453         }
00454 
00455         while (map->id) {
00456                 if(map->id == MesType && map->protdisc == ProtDisc)
00457                         break;
00458                 map++;
00459         }
00460         if (!map->id) {
00461                 /* Message not found */
00462                 return NULL;
00463         }
00464         return map->ies;
00465 }
00466 
00477 static L3INT Q931MesgIEsGetMandatory(struct Q931Dialect *dialect, L3INT MesType, L3UCHAR ProtDisc, L3UCHAR *list, L3INT size)
00478 {
00479         struct Q931MessageIE *map = NULL;
00480         struct Q931MessageIEEntry *ie;
00481         int i = 0;
00482 
00483         assert(dialect);
00484 
00485         map = Q931DialectGetMesIEMap(dialect);
00486         if (!map) {
00487                 return -1;
00488         }
00489 
00490         while (map->id) {
00491                 if(map->id == MesType && map->protdisc == ProtDisc)
00492                         break;
00493                 map++;
00494         }
00495         if (!map->id) {
00496                 /* Message not found */
00497                 return -1;
00498         }
00499 
00500         ie = map->ies;
00501         while (ie->id) {
00502                 if (ie->flags & Q931_IEF_MANDATORY) {
00503                         if (i >= size) {
00504                                 return -1;
00505                         }
00506                         list[i++] = ie->id;
00507                 }
00508                 ie++;
00509         }
00510         return i;
00511 }
00512 
00520 static L3INT Q931MesgIEsMandatoryMissing(L3UCHAR *list, L3INT size)
00521 {
00522         int count = 0;
00523         int i;
00524 
00525         for (i = 0; i < size; i++) {
00526                 if (list[i]) {
00527                         count++;
00528                 }
00529         }
00530         return count;
00531 }
00532 
00540 static void Q931MesgIEsMandatoryClear(L3UCHAR *list, L3INT size, L3UCHAR id)
00541 {
00542         int i;
00543 
00544         for (i = 0; i < size; i++) {
00545                 if (list[i] == id) {
00546                         list[i] = 0;
00547                         return;
00548                 }
00549         }
00550 }
00551 
00560 static L3BOOL Q931MesgIEIsDirectionValid(struct Q931MessageIEEntry *ie, L3INT mode, L3BOOL outgoing)
00561 {
00562         L3INT flags = Q931_IEF_NONE;
00563 
00564         if (mode == Q931_NT) {
00565                 flags |= (outgoing) ? Q931_IEF_TO_USER : Q931_IEF_TO_NET;
00566         } else {
00567                 flags |= (outgoing) ? Q931_IEF_TO_NET : Q931_IEF_TO_USER;
00568         }
00569 
00570         if (!(ie->flags & flags)) {     /* IE not allowed in this direction */
00571                 return L3FALSE;
00572         }
00573         return L3TRUE;
00574 }
00575 
00583 static L3BOOL Q931MesgIEIsCodesetValid(struct Q931MessageIEEntry *ie, L3INT codeset)
00584 {
00585         L3INT flags = Q931_IE_CODESET_0;
00586 
00587         /* only check if any codesets have been specified at all */
00588         if (ie->codeset & Q931_IE_CODESET_ALL) {
00589                 flags <<= codeset;
00590 
00591                 if (!(ie->codeset & flags)) {   /* IE not allowed in this codeset */
00592                         return L3FALSE;
00593                 }
00594         }
00595         return L3TRUE;
00596 }
00597 
00604 static L3UCHAR Q931MesgIEGetCodeset(struct Q931MessageIEEntry *ie)
00605 {
00606         L3INT mask = Q931_IE_CODESET_0;
00607         L3UCHAR codeset = 0;
00608 
00609         while (mask <= Q931_IE_CODESET_7) {
00610                 if (ie->codeset & mask) {
00611                         return codeset;
00612                 }
00613 
00614                 mask <<= 1;
00615                 codeset++;
00616         }
00617         return 0;
00618 }
00619 
00627 static L3BOOL Q931MesgIEIsSizeValid(struct Q931MessageIEEntry *ie, L3UCHAR size)
00628 {
00629         if (ie->id & 0x80) {    /* Fixed size IE */
00630                 return (L3BOOL)(size == 1);
00631         }
00632 
00633         return (L3BOOL)(ie->minsize <= size || ie->maxsize >= size);
00634 }
00635 
00642 static L3BOOL Q931MesgIEIsMandatory(struct Q931MessageIEEntry *ie)
00643 {
00644         return (L3BOOL)((ie->flags & Q931_IEF_MANDATORY) != 0);
00645 }
00646 
00651 L3INT Q931MesgHeader(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *mes, L3UCHAR *OBuf, L3INT Size, L3INT *IOff)
00652 {
00653         L3INT Octet = *IOff;
00654 
00655         Q931Log(pTrunk, Q931_LOG_DEBUG, "Creating Q.931 Message Header:\n    ProtDisc %d (%#x), CRV %d (%#x), CRVflag: %d (%#x), MesType: %d (%#x)\n",
00656                          mes->ProtDisc, mes->ProtDisc, mes->CRV, mes->CRV, mes->CRVFlag, mes->CRVFlag, mes->MesType, mes->MesType);
00657 
00658         OBuf[Octet++] = mes->ProtDisc;                          /* Protocol discriminator */
00659         if (!Q931_IS_BRI(pTrunk)) {
00660                 OBuf[Octet++] = 2;                                                                      /* length is 2 octets */
00661                 OBuf[Octet++] = (L3UCHAR)((mes->CRV >> 8) & 0x7f) | ((mes->CRVFlag << 7) & 0x80);       /* msb */
00662                 OBuf[Octet++] = (L3UCHAR) (mes->CRV & 0xff);                                            /* lsb */
00663         } else {
00664                 OBuf[Octet++] = 1;                                                                      /* length is 1 octet */
00665                 OBuf[Octet++] = (L3UCHAR) (mes->CRV & 0x7f) | ((mes->CRVFlag << 7) & 0x80);             /* CRV & flag */
00666         }
00667         OBuf[Octet++] = mes->MesType;                           /* message header */
00668 
00669         *IOff = Octet;
00670         return 0;
00671 }
00672 
00673 /*****************************************************************************
00674  *
00675  * Muahahaha, a generic Q931Umes implementation!!!
00676  *
00677  *****************************************************************************/
00678 
00690 L3INT Q931Umes_Generic(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size)
00691 {
00692         L3INT ir = 0;
00693         L3INT OOff = 0;
00694         L3INT rc = Q931E_NO_ERROR;
00695         L3UCHAR last_codeset = 0, codeset = 0;
00696         L3UCHAR shift_nolock = 1;
00697         L3UCHAR mandatoryIEs[Q931MAXIE];
00698         L3UCHAR msgidx = 0;
00699         L3INT   mandsize = 0, missing_count;
00700 
00701         if (!mes->MesType) {
00702                 Q931Log(pTrunk, Q931_LOG_ERROR, "Nationally specified message types not supported\n");
00703                 return Q931E_UNEXPECTED_MESSAGE;
00704         }
00705 
00706         memset(mandatoryIEs, 0, sizeof(mandatoryIEs));
00707 
00708         mandsize = Q931MesgIEsGetMandatory(pTrunk->Dialect, mes->MesType, mes->ProtDisc, mandatoryIEs, sizeof(mandatoryIEs));
00709         if (mandsize < 0) {
00710                 Q931Log(pTrunk, Q931_LOG_DEBUG, "Unable to load mandatory IEs for message\n");
00711                 return Q931E_UNKNOWN_MESSAGE;   /* this one ok?? */
00712         }
00713 
00714         /* TODO: handle codeset shifts (more) correctly */
00715         /* TODO: improve error handling... */
00716 
00717         while (IOff < Size) {
00718                 struct Q931MessageIEEntry *entry;
00719                 L3UCHAR id, size;
00720 
00721                 /* Codeset shift */
00722                 if ((IBuf[IOff] & 0xf0) == Q931ie_SHIFT) {
00723                         shift_nolock = (IBuf[IOff] & 0x08);
00724                         if (shift_nolock) {
00725                                 last_codeset = codeset;
00726                         }
00727                         codeset = (IBuf[IOff++] & 0x07);
00728 #ifdef __TODO__
00729                         /* TODO: Check if target codeset is valid */
00730                         if (!Q931MesgCodesetIsValid(pTrunk, codeset)) {
00731                                 Q931Log(pTrunk, Q931_LOG_ERROR, "Shift to invalid codeset %d\n", codeset);
00732                         }
00733 #endif
00734                         continue;
00735                 }
00736 
00737                 /* Grab IE */
00738                 id = IBuf[IOff];
00739 
00740                 if (!(id & 0x80)) {
00741                         /* Variable size IE, get length */
00742                         size = IBuf[IOff + 1] + 2;      /* header + body */
00743                 } else {
00744                         /* Single octet IE */
00745                         size = 1;
00746                 }
00747 
00748                 /* IE supported? */
00749                 if (Q931UieIsNull(pTrunk, id)) {
00750                         /* congrats, no idea how to cope with this */
00751                         Q931Log(pTrunk, Q931_LOG_DEBUG, "Unhandled IE %hhu (%#hhx)\n", id, id);
00752 
00753                         if (Q931TrunkIsSetFlag(pTrunk, Q931_TFLAG_IGNORE_UNKNOWN_IE)) {
00754                                 IOff += size;   /* "consume" IE */                              
00755                                 goto skip;
00756                         } else
00757                                 return Q931E_UNKNOWN_IE;
00758                 }
00759 
00760                 /* Lookup IE in table and perform checks */
00761                 entry = Q931MesgIEsGetEntry(pTrunk->Dialect, mes->MesType, mes->ProtDisc, id, &msgidx);
00762                 if (!entry) {
00763                         /* aww, not found */
00764                         Q931Log(pTrunk, Q931_LOG_DEBUG, "IE %hhu (%#hhx) not allowed for message type\n", id, id);
00765 
00766                         if (Q931TrunkIsSetFlag(pTrunk, Q931_TFLAG_IGNORE_ILLEGAL_IE)) {
00767                                 IOff += size;   /* "consume" IE */                              
00768                                 goto skip;
00769                         } else
00770                                 return Q931E_ILLEGAL_IE;
00771                 }
00772 
00773                 if (!Q931MesgIEIsDirectionValid(entry, pTrunk->NetUser, 0)) {
00774                         /* oops, we shouldn't be getting this ie from our peer in this mode of operation */
00775                         Q931Log(pTrunk, Q931_LOG_DEBUG, "IE %hhu (%#hhx) in wrong direction (flags: 0x%x, mode: %d, incoming)\n", id, id, entry->flags, pTrunk->NetUser);
00776                         return Q931E_ILLEGAL_IE;
00777                 }
00778 
00779                 if (!Q931MesgIEIsSizeValid(entry, size)) {
00780                         /* oops, IE is too large or short */
00781                         Q931Log(pTrunk, Q931_LOG_DEBUG, "IE %hhu (%#hhx) size error\n", id, id);
00782                         return Q931E_ILLEGAL_IE;        /* meh, s*cks */
00783                 }
00784 
00785                 if (!Q931MesgIEIsCodesetValid(entry, codeset)) {
00786                         /* arrrr, IE is not allowed in this codest */
00787                         Q931Log(pTrunk, Q931_LOG_DEBUG, "IE %hhu (%#hhx) not allowed in codeset %d\n", id, id, codeset);
00788                         return Q931E_ILLEGAL_IE;
00789                 }
00790 
00791                 switch (id) {
00792                 case Q931ie_REPEAT_INDICATOR:   /* TODO: handle this one better... */
00793                         if (ir < 2) {
00794                                 rc = Q931Uie(pTrunk, id, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
00795                                 ir++;
00796                         } else {
00797                                 return Q931E_ILLEGAL_IE;
00798                         }
00799                         break;
00800                 default:
00801                         rc = Q931Uie(pTrunk, id, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
00802                         if (rc != Q931E_NO_ERROR) 
00803                                 return rc;
00804                         break;
00805                 }
00806 
00807                 /* Remove mandatory IE from list, if we've found one */
00808                 if (Q931MesgIEIsMandatory(entry)) {
00809                         Q931MesgIEsMandatoryClear(mandatoryIEs, mandsize, id);
00810                 }
00811 
00812 skip:
00813                 /* drop back to old codeset!? */
00814                 if (shift_nolock) {
00815                         codeset = last_codeset;
00816                 }
00817         }
00818 
00819         if ((missing_count = Q931MesgIEsMandatoryMissing(mandatoryIEs, mandsize)) > 0) {
00820                 /* tadaa, at least one of the mandatory IEs is missing */
00821                 Q931Log(pTrunk, Q931_LOG_ERROR, "%d Mandatory IEs missing in this incoming message\n", missing_count);
00822 
00823                 return Q931E_MANDATORY_IE_MISSING;
00824         }
00825 
00826         mes->Size = sizeof(Q931mes_Generic) - 1 + OOff;
00827         return Q931E_NO_ERROR;
00828 }
00829 
00830 /*
00831  * BIG FAT TODO:
00832  *
00833  * Yeah, this _IS_ ugly, but it's needed until we change the way IEs refs are handled in the message
00834  * (or we're going to do a full (= slow) lookup in the buffer...)
00835  *
00836  */
00837 static Q931ie_Generic * Q931MesgGetIE(Q931_TrunkInfo_t *trunk, Q931mes_Generic *mes, L3UCHAR id)
00838 {
00839         ie ie = 0;
00840 
00841         switch(id) {
00842         case Q931ie_SENDING_COMPLETE:
00843                 ie = mes->SendComplete;
00844                 break;
00845         case Q931ie_REPEAT_INDICATOR:
00846                 ie = mes->RepeatInd;
00847                 break;
00848         case Q931ie_BEARER_CAPABILITY:
00849                 ie = mes->BearerCap;
00850                 break;
00851         case Q931ie_CHANNEL_IDENTIFICATION:
00852                 ie = mes->ChanID;
00853                 break;
00854         case Q931ie_NETWORK_SPECIFIC_FACILITIES:
00855                 ie = mes->NetFac;
00856                 break;
00857         case Q931ie_DISPLAY:
00858                 ie = mes->Display;
00859                 break;
00860         case Q931ie_DATETIME:
00861                 ie = mes->DateTime;
00862                 break;
00863         case Q931ie_KEYPAD_FACILITY:
00864                 ie = mes->KeypadFac;
00865                 break;
00866         case Q931ie_SIGNAL:
00867                 ie = mes->Signal;
00868                 break;
00869         case Q931ie_CALLING_PARTY_NUMBER:
00870                 ie = mes->CallingNum;
00871                 break;
00872         case Q931ie_CALLING_PARTY_SUBADDRESS:
00873                 ie = mes->CallingSub;
00874                 break;
00875         case Q931ie_CALLED_PARTY_NUMBER:
00876                 ie = mes->CalledNum;
00877                 break;
00878         case Q931ie_CALLED_PARTY_SUBADDRESS:
00879                 ie = mes->CalledSub;
00880                 break;
00881         case Q931ie_TRANSIT_NETWORK_SELECTION:
00882                 ie = mes->TransNetSel;
00883                 break;
00884         case Q931ie_LOW_LAYER_COMPATIBILITY:
00885                 ie = mes->LLComp;
00886                 break;
00887         case Q931ie_HIGH_LAYER_COMPATIBILITY:
00888                 ie = mes->HLComp;
00889                 break;
00890         case Q931ie_PROGRESS_INDICATOR:
00891                 ie = mes->ProgInd;
00892                 break;
00893         case Q931ie_CAUSE:
00894                 ie = mes->Cause;
00895                 break;
00896         case Q931ie_CHANGE_STATUS:
00897                 ie = mes->ChangeStatus;
00898                 break;
00899         case Q931ie_RESTART_INDICATOR:
00900                 ie = mes->RestartInd;
00901                 break;
00902         case Q931ie_CALL_STATE:
00903                 ie = mes->CallState;
00904                 break;
00905         default:
00906                 Q931Log(trunk, Q931_LOG_NOTICE, "Unable to get reference for IE %hhu (%#hhx)\n", id, id);
00907                 return NULL;
00908         }
00909 
00910         if(Q931IsIEPresent(ie)) {
00911                 return Q931GetIEPtr(ie, mes->buf);
00912         }
00913 
00914         return NULL;
00915 }
00916 
00917 L3INT Q931Pmes_Generic(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize)
00918 {
00919         Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf;
00920         struct Q931MessageIEEntry *entry;
00921         L3UCHAR mandatoryIEs[Q931MAXIE];
00922         L3UCHAR codeset = 0;
00923         L3INT rc = Q931E_NO_ERROR;
00924         L3INT Octet = 0;
00925         L3INT mandsize = 0, missing_count;
00926 
00927         memset(mandatoryIEs, 0, sizeof(mandatoryIEs));
00928 
00929         /* Q931 Message Header */
00930         Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet);
00931 
00932         /* Get mandatory IE list */
00933         mandsize = Q931MesgIEsGetMandatory(pTrunk->Dialect, pMes->MesType, pMes->ProtDisc, mandatoryIEs, sizeof(mandatoryIEs));
00934         if (mandsize < 0) {
00935                 Q931Log(pTrunk, Q931_LOG_DEBUG, "Unable to load mandatory IEs for message\n");
00936                 return Q931E_UNKNOWN_MESSAGE;   /* TODO: this one ok?? */
00937         }
00938 
00939         /* Walk list of allowed IEs */
00940         entry = Q931MesgIEsGetFirstEntry(pTrunk->Dialect, pMes->MesType, pMes->ProtDisc);
00941 
00942         while (entry && entry->id) {
00943                 L3UCHAR ie_codeset = 0;
00944                 Q931ie_Generic *pIE;
00945 
00946                 pIE = Q931MesgGetIE(pTrunk, pMes, entry->id);
00947 
00948                 /* Check + encode IE */
00949                 if (pIE) {
00950                         L3UCHAR size = 1;
00951 
00952                         if (!(entry->id & 0x80)) {
00953                                 size = pIE->Size + 2;
00954                         }
00955 
00956                         /* Direction check */
00957                         if (!Q931MesgIEIsDirectionValid(entry, pTrunk->NetUser, 1)) {
00958                                 /* oops, we shouldn't be getting this ie from our peer in this mode of operation */
00959                                 Q931Log(pTrunk, Q931_LOG_DEBUG, "IE %hhu (%#hhx) in wrong direction\n", entry->id, entry->id);
00960                                 return Q931E_ILLEGAL_IE;
00961                         }
00962 
00963                         /* Check size */
00964                         if (!Q931MesgIEIsSizeValid(entry, size)) {
00965                                 /* oops, IE is too large or short */
00966                                 Q931Log(pTrunk, Q931_LOG_DEBUG, "IE %hhu (%#hhx) size error\n", entry->id, entry->id);
00967                                 return Q931E_ILLEGAL_IE;        /* meh, s*cks */
00968                         }
00969 
00970                         /* IE supported? */
00971                         if (Q931PieIsNull(pTrunk, entry->id)) {
00972                                 /* congrats, no idea how to cope with this */
00973                                 Q931Log(pTrunk, Q931_LOG_DEBUG, "Unhandled IE %hhu (%#hhx)\n", entry->id, entry->id);
00974                                 return Q931E_UNKNOWN_IE;
00975                         }
00976 
00977                         /* Check IEs codeset and change codeset if neccessary (non-locking shift only!) */
00978                         ie_codeset = Q931MesgIEGetCodeset(entry);
00979                         if (ie_codeset != codeset) {
00980 #ifdef __TODO__
00981                                 if (dialect->flags & Q931_DIALECT_LOCKING_SHIFT_ONLY) {
00982                                         /* emit locking shift to target codeset */
00983                                         codeset       = rc;
00984                                         OBuf[Octet++] = Q931ie_SHIFT | (codeset & 0x07);
00985                                 } else {
00986 #endif
00987                                         /* emit non-locking shift to target codeset */
00988                                         OBuf[Octet++] = Q931ie_SHIFT | 0x08 | (rc & 0x07);
00989 #ifdef __TODO__
00990                                 }
00991 #endif
00992                         }
00993 
00994                         /* TODO: repeat indicator? */
00995 
00996                         if ((rc = Q931Pie(pTrunk, entry->id, (L3UCHAR *)pIE, OBuf, &Octet)) != Q931E_NO_ERROR) {
00997                                 return rc;
00998                         }
00999 
01000                         /* Remove mandatory IE from list, if we've found one */
01001                         if (Q931MesgIEIsMandatory(entry)) {
01002                                 Q931MesgIEsMandatoryClear(mandatoryIEs, mandsize, entry->id);
01003                         }
01004                 }
01005 
01006                 entry++;
01007         }
01008 
01009         if ((missing_count = Q931MesgIEsMandatoryMissing(mandatoryIEs, mandsize)) > 0) {
01010                 /* tadaa, at least one of the mandatory IEs is missing */
01011                 Q931Log(pTrunk, Q931_LOG_ERROR, "%d Mandatory IEs missing in this outgoing message\n", missing_count);
01012 
01013                 return Q931E_MANDATORY_IE_MISSING;
01014         }
01015 
01016         *OSize = Octet;
01017         return rc;
01018 }

Generated on Tue Apr 7 17:38:19 2009 for mod_ssh by  doxygen 1.5.4