libisdn
Q931ie.c
Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   FileName:      Q931ie.c
00004 
00005   Contents:      Information Element Pack/Unpack functions.
00006 
00007                 These functions will pack out a Q931 message from the bit
00008                 packed original format into structs that are easier to process
00009                 and pack the same structs back into bit fields when sending
00010                 messages out.
00011 
00012                 The messages contains a short for each possible IE. The MSB
00013                 bit flags the precense of an IE, while the remaining bits
00014                 are the offset into a buffer to find the actual IE.
00015 
00016                 Each IE are supported by 3 functions:
00017 
00018                 Q931Pie_XXX      Pack struct into Q.931 IE
00019                 Q931Uie_XXX      Unpack Q.931 IE into struct
00020                 Q931InitIEXXX   Initialize IE (see Q931api.c).
00021 
00022   Dialect Note: This file will only contain standard DSS1 IE. Other IE as
00023                 used in QSIG, NI2, Q.932 etc are located in separate files.
00024 
00025                 See     q931.h for description.
00026 
00027   License/Copyright:
00028 
00029   Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved.
00030   email:janvb@caselaboratories.com
00031 
00032   Redistribution and use in source and binary forms, with or without
00033   modification, are permitted provided that the following conditions are
00034   met:
00035 
00036         * Redistributions of source code must retain the above copyright notice,
00037           this list of conditions and the following disclaimer.
00038         * Redistributions in binary form must reproduce the above copyright notice,
00039           this list of conditions and the following disclaimer in the documentation
00040           and/or other materials provided with the distribution.
00041         * Neither the name of the Case Labs, Ltd nor the names of its contributors
00042           may be used to endorse or promote products derived from this software
00043           without specific prior written permission.
00044 
00045   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00046   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00047   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00048   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00049   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00050   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00051   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00052   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00053   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00054   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00055   POSSIBILITY OF SUCH DAMAGE.
00056 *****************************************************************************/
00057 #include <stdio.h>
00058 #include <string.h>
00059 
00060 #if defined(__WIN32__) || defined(__WIN64__)
00061 #else
00062 #include <netinet/in.h> /* X.213 NPAS, IANA IPC - RFC4548 */
00063 #include <arpa/inet.h>  /* X.213 NPAS, IANA IPC - RFC4548 */
00064 #endif
00065 
00066 #include "Q931.h"
00067 #include "Q931priv.h"
00068 
00069 #include "Q850.h"
00070 #include "X213.h"
00071 
00072 #include "utils/common.h"
00073 #include "utils/strstream.h"
00074 
00075 /****************************************************************************
00076  * Helper functions for tracing output
00077  ****************************************************************************/
00078 
00079 static const char *q931_network_id_type(const unsigned char type)
00080 {
00081         switch (type) {
00082         case 0x00:
00083                 return "User specified";
00084         case 0x02:
00085                 return "National network identification";
00086         case 0x03:
00087                 return "International network identification";
00088         default:
00089                 return "reserved";
00090         }
00091 }
00092 
00093 static const char *q931_network_id_plan(const unsigned char plan)
00094 {
00095         switch (plan) {
00096         case 0x00:
00097                 return "Unknown";
00098         case 0x01:
00099                 return "Carrier Identification Code (CIC)";
00100         case 0x03:
00101                 return "Data network identification code (X.121)";
00102         default:
00103                 return "reserved";
00104         }
00105 }
00106 
00107 static const char *q931_signal_desc(unsigned char value)
00108 {
00109         switch (value) {
00110         case 0x00:
00111                 return "Dial tone on";
00112         case 0x01:
00113                 return "Ring back tone on";
00114         case 0x02:
00115                 return "Intercept tone on";
00116         case 0x03:
00117                 return "Network congestion tone on";
00118         case 0x04:
00119                 return "Busy tone on";
00120         case 0x05:
00121                 return "Confirm tone on";
00122         case 0x06:
00123                 return "Answer tone on";
00124         case 0x07:
00125                 return "Call waiting tone on";
00126         case 0x08:
00127                 return "Off-hook warning tone on";
00128         case 0x09:
00129                 return "Pre-emption tone on";
00130         case 0x3f:
00131                 return "Tones off";
00132 
00133         case 0x40:
00134                 return "Alerting on, pattern 0";
00135         case 0x41:
00136                 return "Alerting on, pattern 1";
00137         case 0x42:
00138                 return "Alerting on, pattern 2";
00139         case 0x43:
00140                 return "Alerting on, pattern 3";
00141         case 0x44:
00142                 return "Alerting on, pattern 4";
00143         case 0x45:
00144                 return "Alerting on, pattern 5";
00145         case 0x46:
00146                 return "Alerting on, pattern 6";
00147         case 0x47:
00148                 return "Alerting on, pattern 7";
00149         case 0x4f:
00150                 return "Alerting off";
00151 
00152         default:
00153                 return "reserved";
00154         }
00155 }
00156 
00157 static const char *q931_progdesc_type(unsigned char type)
00158 {
00159         switch (type) {
00160         case 0x01:
00161                 return "Call is not end-to-end ISDN, progress in-band";
00162         case 0x02:
00163                 return "Destination address is non-ISDN";
00164         case 0x03:
00165                 return "Origination address is non-ISDN";
00166         case 0x04:
00167                 return "Call has returned to the ISDN";
00168         case 0x05:
00169                 return "Interworking has occured";
00170         case 0x08:
00171                 return "In-band information or an appropriate pattern is now available";
00172         default:
00173                 return "reserved";
00174         }
00175 }
00176 
00177 static const char *q931_subaddr_type(unsigned char type)
00178 {
00179         switch (type) {
00180         case 0x00:
00181                 return "NSAP";
00182         case 0x02:
00183                 return "user specified";
00184         default:
00185                 return "reserved";
00186         }
00187 }
00188 
00189 static const char *q931_coding_type(unsigned char type)
00190 {
00191         switch (type) {
00192         case 0x00:
00193                 return "ITU-T";
00194         case 0x01:
00195                 return "ISO/IEC";
00196         case 0x02:
00197                 return "national standard";
00198         case 0x03:
00199                 return "specific to location";
00200         default:
00201                 return "unknown/invalid";
00202         }
00203 }
00204 
00205 static const char *q931_location_type(unsigned char type)
00206 {
00207         switch (type) {
00208         case 0x00:
00209                 return "user";
00210         case 0x01:
00211                 return "private network serving the local user";
00212         case 0x02:
00213                 return "public network serving the local user";
00214         case 0x03:
00215                 return "transit network";
00216         case 0x04:
00217                 return "public network serving the remote user";
00218         case 0x05:
00219                 return "private network serving the remote user";
00220         case 0x07:
00221                 return "international network";
00222         case 0x0a:
00223                 return "network beyond interworking point";
00224         case 0x0c:
00225         case 0x0d:
00226         case 0x0e:
00227         case 0x0f:
00228                 return "reserved";
00229         default:
00230                 return "invalid/unknown";
00231         }
00232 }
00233 
00234 static const char *q931_ton_type(const unsigned char ton)
00235 {
00236         switch (ton) {
00237         case 0x00:
00238                 return "Unknown";
00239         case 0x01:
00240                 return "International number";
00241         case 0x02:
00242                 return "National number";
00243         case 0x03:
00244                 return "Network specific number";
00245         case 0x04:
00246                 return "Subscriber number";
00247         case 0x06:
00248                 return "Abbreviated number";
00249         case 0x07:
00250                 return "Reserved for extension";
00251         default:
00252                 return "reserved";
00253         }
00254 }
00255 
00256 static const char *q931_numbering_plan_type(const unsigned char plan)
00257 {
00258         switch (plan) {
00259         case 0x00:
00260                 return "Unknown";
00261         case 0x01:
00262                 return "ISDN/telephony numbering plan (E.164)";
00263         case 0x03:
00264                 return "Data numbering plan (X.121)";
00265         case 0x04:
00266                 return "Telext numbering plan (F.69)";
00267         case 0x08:
00268                 return "National standard numbering plan";
00269         case 0x09:
00270                 return "Private numbering plan";
00271         case 0x0f:
00272                 return "Reserved for extension";
00273         default:
00274                 return "reserved";
00275         }
00276 }
00277 
00278 static const char *q931_presentation_type(const unsigned char type)
00279 {
00280         switch (type) {
00281         case 0x00:
00282                 return "Presentation allowed";
00283         case 0x01:
00284                 return "Presentation restricted";
00285         case 0x02:
00286                 return "Number not available due to interworking";
00287         case 0x03:
00288                 return "Reserved";
00289         default:
00290                 return "unknown/invalid";
00291         }
00292 }
00293 
00294 static const char *q931_screening_type(const unsigned char type)
00295 {
00296         switch (type) {
00297         case 0x00:
00298                 return "User-provided, not screened";
00299         case 0x01:
00300                 return "User-provided, verified and passed";
00301         case 0x02:
00302                 return "User-provided, verified and failed";
00303         case 0x03:
00304                 return "Network provided";
00305         default:
00306                 return "unknown/invalid";
00307         }
00308 }
00309 
00310 /********************************************************************************************************************************
00311  * CRV Decoding
00312  ********************************************************************************************************************************/
00313 
00314 L3USHORT Q931Uie_CRV(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *IOff, L3INT *OOff)
00315 {
00316         L3USHORT CRV = 0;
00317         L3INT Octet = *IOff;
00318         L3INT l = IBuf[Octet++];
00319 
00320         if (l == 1) {   /* One octet CRV */
00321                 CRV = IBuf[Octet++] & 0x7F;
00322         }
00323         else if (l == 2) {      /* two octet CRV */
00324                 CRV  = (IBuf[Octet++] & 0x7f) << 8;
00325                 CRV |=  IBuf[Octet++];
00326         }
00327         else {
00328                 /* Long CRV is not used, so we skip this */
00329                 /* TODO: is it right to set to 0 here? */
00330                 CRV = 0;
00331                 Octet += l;
00332         }
00333 
00334         *IOff = Octet;
00335         return CRV;
00336 }
00337 
00338 
00339 /*****************************************************************************
00340 
00341   Macro:                Q931MoreIE
00342 
00343   Description:  Local helper macro detecting if there is more IE space left
00344                 based on the 3 standard parameters Octet, Off and IESpace.
00345                 This can be used to test if the IE is completed to avoid
00346                 that the header of the next IE is interpreted as a part of
00347                 the current IE.
00348 
00349 *****************************************************************************/
00350 #define Q931MoreIE() (Octet + Off - 2 < IESize)
00351 
00352 #define Q931IESizeTest(x) {\
00353         if (Octet + Off - 2 != IESize) {\
00354                 Q931SetError(trunk, x, Octet, Off);\
00355                 return x;\
00356         }\
00357 }
00358 
00359 /*****************************************************************************
00360 
00361   Function:      Q931ReadExt
00362 
00363   Description:  Many of the octets in the standard have an MSB 'ext.1'. This
00364                                 means that the octet usually is the latest octet, but that a
00365                                 futhure standard may extend the octet. A stack must be able
00366                                 to handle such extensions by skipping the extension octets.
00367 
00368                                 This function will increase the offset counter with 1 for
00369                                 each octet with an MSB of zero. This will allow the stack to
00370                                 skip extensions wihout knowing anything about them.
00371 
00372   Parameters:   IBuf    ptr to octet array.
00373                                 Off      Starting offset counter
00374 
00375   Return Value: New offset value.
00376 
00377 *****************************************************************************/
00378 
00379 L3INT Q931ReadExt(L3UCHAR * IBuf, L3INT Off)
00380 {
00381         L3INT c = 0;
00382         while ((IBuf[c] & 0x80) == 0) {
00383                 c++;
00384         }
00385         return Off + c;
00386 }
00387 
00388 
00389 /********************************************************************************************************************************
00390  * Bearer Capability IE
00391  ********************************************************************************************************************************/
00392 
00393 L3INT Q931Uie_BearerCap(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
00394 {
00395         Q931ie_BearerCap *pie = (Q931ie_BearerCap*)OBuf;
00396         ie *pIE = &pMsg->BearerCap;
00397         L3INT Off = 0;
00398         L3INT Octet = 0;
00399         L3INT IESize;
00400         *pIE = 0;
00401 
00402         /* Octet 1 */
00403         pie->IEId = IBuf[Octet++];
00404 
00405         /* Octet 2 */
00406         IESize = IBuf[Octet++];
00407 
00408         /* Octet 3 */
00409         pie->CodStand = ieGetOctet((IBuf[Octet] & 0x60) >> 5);
00410         pie->ITC      = ieGetOctet(IBuf[Octet] & 0x1f);
00411         Off           = Q931ReadExt(&IBuf[Octet], Off);
00412         Octet++;
00413 
00414         /* Octet 4 */
00415         pie->TransMode = ieGetOctet((IBuf[Octet + Off] & 0x60) >> 5);
00416         pie->ITR       = ieGetOctet(IBuf[Octet + Off] & 0x1f);
00417         Off            = Q931ReadExt(&IBuf[Octet + Off], Off);
00418         Octet++;
00419 
00420         /* Octet 4.1. Rate multiplier is only present if ITR = Multirate                */
00421         if (pie->ITR == 0x18) {
00422                 pie->RateMul = ieGetOctet(IBuf[Octet + Off] & 0x7f);
00423                 Off = Q931ReadExt(&IBuf[Octet + Off], Off);
00424                 Off ++;
00425         }
00426 
00427         /* Octet 5 */
00428         if ((IBuf[Octet + Off] & 0x60) == 0x20 && Q931MoreIE()) {
00429                 pie->Layer1Ident = ieGetOctet((IBuf[Octet + Off] & 0x60) >> 5);
00430                 pie->UIL1Prot    = ieGetOctet(IBuf[Octet + Off] & 0x1f);
00431                 Octet++;
00432 
00433                 /* Octet 5a. The octet may be present if ITC is unrestrictd digital info
00434                  * and UIL1Prot is either V.110, I.460 and X.30 or V.120. It may also
00435                  * be present if ITC = 3.1 kHz audio and UIL1Prot is G.711.
00436                  * Bit 8 of Octet 5 = 0 indicates that 5a is present.
00437                  */
00438 
00439                 if (IsQ931Ext(IBuf[Octet + Off - 1])) {
00440                         if (((pie->ITC == 0x08) && (pie->UIL1Prot == 0x01 || pie->UIL1Prot == 0x08))
00441                         || ((pie->ITC == 0x10) && (pie->UIL1Prot == 0x02 || pie->UIL1Prot == 0x03))) {
00442                                 pie->SyncAsync = ieGetOctet((IBuf[Octet + Off] & 0x40) >> 6);
00443                                 pie->Negot     = ieGetOctet((IBuf[Octet + Off] & 0x20) >> 5);
00444                                 pie->UserRate  = ieGetOctet(IBuf[Octet + Off] & 0x1f);
00445                                 Off ++;
00446                         }
00447                         else {
00448                                 /* We have detected bit 8 = 0, but no setting that require the  */
00449                                 /* additional octets ??? */
00450                                 Q931SetError(trunk, Q931E_BEARERCAP, 5,Off);
00451                                 return Q931E_BEARERCAP;
00452                         }
00453 
00454                         /* Octet 5b. Two different structures used. */
00455                         if (IsQ931Ext(IBuf[Octet + Off - 1])) {
00456                                 if (pie->UIL1Prot == 0x01) { /* ITU V.110, I.460 and X.30 */
00457                                         pie->InterRate = ieGetOctet((IBuf[Octet + Off] & 0x60) >> 5);
00458                                         pie->NIConTx   = ieGetOctet((IBuf[Octet + Off] & 0x10) >> 4);
00459                                         pie->NIConRx   = ieGetOctet((IBuf[Octet + Off] & 0x08) >> 3);
00460                                         pie->FlowCtlTx = ieGetOctet((IBuf[Octet + Off] & 0x04) >> 2);
00461                                         pie->FlowCtlRx = ieGetOctet((IBuf[Octet + Off] & 0x20) >> 1);
00462                                         Off++;
00463                                 }
00464                                 else if (pie->UIL1Prot == 0x08) { /* ITU V.120 */
00465                                         pie->HDR        = ieGetOctet((IBuf[Octet + Off] & 0x40) >> 6);
00466                                         pie->MultiFrame = ieGetOctet((IBuf[Octet + Off] & 0x20) >> 5);
00467                                         pie->Mode       = ieGetOctet((IBuf[Octet + Off] & 0x10) >> 4);
00468                                         pie->LLInegot   = ieGetOctet((IBuf[Octet + Off] & 0x08) >> 3);
00469                                         pie->Assignor   = ieGetOctet((IBuf[Octet + Off] & 0x04) >> 2);
00470                                         pie->InBandNeg  = ieGetOctet((IBuf[Octet + Off] & 0x02) >> 1);
00471                                         Off++;
00472                                 }
00473                                 else {
00474                                         Q931SetError(trunk,Q931E_BEARERCAP, 5,Off);
00475                                         return Q931E_BEARERCAP;
00476                                 }
00477 
00478                                 /* Octet 5c */
00479                                 if (IsQ931Ext(IBuf[Octet + Off - 1])) {
00480                                         pie->NumStopBits = ieGetOctet((IBuf[Octet + Off] & 0x60) >> 5);
00481                                         pie->NumDataBits = ieGetOctet((IBuf[Octet + Off] & 0x18) >> 3);
00482                                         pie->Parity      = ieGetOctet(IBuf[Octet + Off] & 0x07);
00483                                         Off++;
00484 
00485                                         /* Octet 5d */
00486                                         if (IsQ931Ext(IBuf[Octet + Off - 1])) {
00487                                                 pie->DuplexMode = ieGetOctet((IBuf[Octet + Off] & 0x40) >> 6);
00488                                                 pie->ModemType  = ieGetOctet(IBuf[Octet + Off] & 0x3f);
00489                                                 Off ++;
00490                                         }
00491                                 }
00492                         }
00493                 }
00494         }
00495 
00496         /* Octet 6 */
00497         if ((IBuf[Octet + Off] & 0x60) == 0x40 && Q931MoreIE()) {
00498                 pie->Layer2Ident = ieGetOctet((IBuf[Octet + Off] & 0x60) >> 5);
00499                 pie->UIL2Prot    = ieGetOctet(IBuf[Octet + Off] & 0x1f);
00500 
00501                 Off = Q931ReadExt(&IBuf[Octet + Off], Off);
00502                 Octet ++;
00503         }
00504 
00505         /* Octet 7 */
00506         if ((IBuf[Octet + Off] & 0x60) == 0x60 && Q931MoreIE()) {
00507                 pie->Layer3Ident = ieGetOctet((IBuf[Octet + Off] & 0x60) >> 5);
00508                 pie->UIL3Prot    = ieGetOctet(IBuf[Octet + Off] & 0x1f);
00509                 Octet++;
00510 
00511                 /* Octet 7a */
00512                 if (IsQ931Ext(IBuf[Octet + Off - 1])) {
00513                         if (pie->UIL3Prot == 0x0c) {
00514                                 pie->AL3Info1 = ieGetOctet(IBuf[Octet + Off] & 0x0f);
00515                                 Off++;
00516 
00517                                 /* Octet 7b */
00518                                 if (IsQ931Ext(IBuf[Octet + Off])) {
00519                                         pie->AL3Info2 = ieGetOctet(IBuf[Octet + Off] & 0x0f);
00520                                         Off++;
00521                                 }
00522                         }
00523                         else {
00524                                 Q931SetError(trunk,Q931E_BEARERCAP, 7, Off);
00525                                 return Q931E_BEARERCAP;
00526 
00527                         }
00528                 }
00529         }
00530 
00531         Q931IESizeTest(Q931E_BEARERCAP);
00532         Q931SetIE(*pIE, *OOff);
00533 
00534         *IOff = (*IOff) + Octet + Off;
00535         *OOff = (*OOff) + sizeof(Q931ie_BearerCap);
00536         pie->Size = sizeof(Q931ie_BearerCap);
00537 
00538         return Q931E_NO_ERROR;
00539 }
00540 
00541 
00542 L3INT Q931Pie_BearerCap(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
00543 {
00544         Q931ie_BearerCap *pIE = (Q931ie_BearerCap*)IBuf;
00545         L3INT rc = 0;
00546         L3INT Beg = *Octet; /* remember current offset */
00547         L3INT li;
00548 
00549         Q931Log(trunk, Q931_LOG_DEBUG, "Encoding Bearer Capability IE\n");
00550 
00551         OBuf[(*Octet)++] = Q931ie_BEARER_CAPABILITY ;
00552         li = (*Octet)++; /* remember length position */
00553 
00554         /* Octet 3 - Coding standard / Information transfer capability */
00555         OBuf[(*Octet)++] = 0x80 | ((pIE->CodStand << 5) & 0x60) | (pIE->ITC & 0x1f);
00556 
00557         /* Octet 4 - Transfer mode / Information transfer rate */
00558         OBuf[(*Octet)++] = 0x80 | ((pIE->TransMode << 5) & 0x60) | (pIE->ITR & 0x1f);
00559 
00560         if (pIE->ITR == 0x18) {
00561                 /* Octet 4.1 - Rate Multiplier */
00562                 OBuf[(*Octet)++] = 0x80 | (pIE->RateMul & 0x7f);
00563         }
00564 
00565         /* Octet 5 - Layer 1 Ident / User information layer 1 protocol */
00566         if (pIE->Layer1Ident == 0x01) {
00567                 if (((pIE->ITC == 0x08) && (pIE->UIL1Prot == 0x01 || pIE->UIL1Prot == 0x08)) ||
00568                    ((pIE->ITC == 0x10) && (pIE->UIL1Prot == 0x02 || pIE->UIL1Prot == 0x03))) {
00569                         OBuf[(*Octet)++] = 0x00 | ((pIE->Layer1Ident << 5) & 0x60) | (pIE->UIL1Prot & 0x15);
00570 
00571                         /* Octet 5a - SyncAsync/Negot/UserRate */
00572                         OBuf[(*Octet)++] = 0x00 | ((pIE->SyncAsync << 6) & 0x40) | ((pIE->Negot << 5) & 0x20) | (pIE->UserRate & 0x1f);
00573 
00574                         /* Octet 5b - one of two types */
00575                         if (pIE->UIL1Prot == 0x01) { /* ITU V.110, I.460 and X.30       */
00576                                 /* Octet 5b - Intermed rate/ Nic on Tx/Nix on Rx/FlowCtlTx/FlowCtlRx */
00577                                 OBuf[(*Octet)++] = 0x00
00578                                                 | ((pIE->InterRate << 6) & 0x60)
00579                                                 | ((pIE->NIConTx   << 4) & 0x10)
00580                                                 | ((pIE->NIConRx   << 3) & 0x08)
00581                                                 | ((pIE->FlowCtlTx << 2) & 0x04)
00582                                                 | ((pIE->FlowCtlRx << 1) & 0x02);
00583                         }
00584                         else if (pIE->UIL1Prot == 0x08) { /* ITU V.120 */
00585                                 /* Octet 5b - HDR/Multiframe/Mode/LLINegot/Assignor/Inbandneg*/
00586                                 OBuf[(*Octet)++] = 0x00
00587                                                 | ((pIE->InterRate  << 6) & 0x60)
00588                                                 | ((pIE->MultiFrame << 5) & 0x20)
00589                                                 | ((pIE->Mode       << 4) & 0x10)
00590                                                 | ((pIE->LLInegot   << 3) & 0x08)
00591                                                 | ((pIE->Assignor   << 2) & 0x04)
00592                                                 | ((pIE->InBandNeg  << 1) & 0x02);
00593                         }
00594 
00595                         /* Octet 5c - NumStopBits/NumStartBits/Parity                                   */
00596                         OBuf[(*Octet)++] = 0x00
00597                                         | ((pIE->NumStopBits << 5) & 0x60)
00598                                         | ((pIE->NumDataBits << 3) & 0x18)
00599                                         | (pIE->Parity & 0x07);
00600 
00601                         /* Octet 5d - Duplex Mode/Modem Type */
00602                         OBuf[(*Octet)++] = 0x80 | ((pIE->DuplexMode << 6) & 0x40) | (pIE->ModemType & 0x3f);
00603                 }
00604                 else {
00605                         OBuf[(*Octet)++] = 0x80 | ((pIE->Layer1Ident << 5) & 0x60) | (pIE->UIL1Prot & 0x1f);
00606                 }
00607         }
00608 
00609         /* Octet 6 - Layer2Ident/User information layer 2 prtocol */
00610         if (pIE->Layer2Ident == 0x02) {
00611                 OBuf[(*Octet)++] = 0x80 | ((pIE->Layer2Ident << 5) & 0x60) | (pIE->UIL2Prot & 0x1f);
00612         }
00613 
00614         /* Octet 7 - Layer 3 Ident/ User information layer 3 protocol */
00615         if (pIE->Layer3Ident == 0x03) {
00616                 if (pIE->UIL3Prot == 0x0c) {
00617                         OBuf[(*Octet)++] = 0x00 | ((pIE->Layer3Ident << 5) & 0x60) | (pIE->UIL3Prot & 0x1f);
00618 
00619                         /* Octet 7a - Additional information layer 3 msb */
00620                         OBuf[(*Octet)++] = 0x00 | (pIE->AL3Info1 & 0x0f);
00621 
00622                         /* Octet 7b - Additional information layer 3 lsb */
00623                         OBuf[(*Octet)++] = 0x80 | (pIE->AL3Info2 & 0x0f);
00624                 }
00625                 else {
00626                         OBuf[(*Octet)++] = 0x80 | ((pIE->Layer3Ident << 5) & 0x60) | (pIE->UIL3Prot & 0x1f);
00627                 }
00628         }
00629 
00630         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
00631         return rc;
00632 }
00633 
00634 
00635 static const char *q931_information_transfer_capability_type(const unsigned char type)
00636 {
00637         switch (type) {
00638         case 0x00:
00639                 return "Speech";
00640         case 0x08:
00641                 return "Unrestricted digital information";
00642         case 0x09:
00643                 return "Restricted digital information";
00644         case 0x10:
00645                 return "3.1KHz Audio";
00646         case 0x11:
00647                 return "Unrestricted digital information with tones/announcements";
00648         case 0x18:
00649                 return "Video";
00650         default:
00651                 return "reserved";
00652         }
00653 }
00654 
00655 static const char *q931_transfer_mode_type(const unsigned char type)
00656 {
00657         switch (type) {
00658         case 0x00:
00659                 return "Circuit mode";
00660         case 0x02:
00661                 return "Packet mode";
00662         default:
00663                 return "reserved";
00664         }
00665 }
00666 
00667 static const char *q931_information_transfer_rate_type(const unsigned char type)
00668 {
00669         switch (type) {
00670         case 0x00:
00671                 return "- Packet mode -";
00672         case 0x10:
00673                 return "64 kbit/s";
00674         case 0x11:
00675                 return "2 x 64 kbit/s";
00676         case 0x13:
00677                 return "384 kbit/s";
00678         case 0x15:
00679                 return "1536 kbit/s";
00680         case 0x17:
00681                 return "1920 kbit/s";
00682         case 0x18:
00683                 return "Multirate (64 kbit/s base rate)";
00684         default:
00685                 return "reserved";
00686         }
00687 }
00688 
00689 static const char *q931_user_information_layer1_type(const unsigned char type)
00690 {
00691         switch (type) {
00692         case 0x01:
00693                 return "ITU-T V.110 / I.460 / X.30";
00694         case 0x02:
00695                 return "G.711 u-law";
00696         case 0x03:
00697                 return "G.711 a-law";
00698         case 0x04:
00699                 return "G.721 32 kbit/s ADPCM (I.460)";
00700         case 0x05:
00701                 return "H.221 and H.242";
00702         case 0x06:
00703                 return "H.223 and H.245";
00704         case 0x07:
00705                 return "Non-ITU-T";
00706         case 0x08:
00707                 return "ITU-T V.120";
00708         case 0x09:
00709                 return "ITU-T X.31 HDLC flag stuffing";
00710         default:
00711                 return "reserved";
00712         }
00713 }
00714 
00715 static const char *q931_user_information_layer2_type(const unsigned char type)
00716 {
00717         switch (type) {
00718         case 0x02:
00719                 return "Q.921 / I.441";
00720         case 0x06:
00721                 return "X.25 link-layer";
00722         case 0x0c:
00723                 return "LAN logical link control (ISO/IEC 8802-2)";
00724         default:
00725                 return "reserved";
00726         }
00727 }
00728 
00729 static const char *q931_user_information_layer3_type(const unsigned char type)
00730 {
00731         switch (type) {
00732         case 0x02:
00733                 return "Q.931";
00734         case 0x06:
00735                 return "X.25 packet layer";
00736         case 0x0b:
00737                 return "ISO/IEC TR 9577";
00738         default:
00739                 return "reserved";
00740         }
00741 }
00742 
00743 static const char *q931_tr9577_layer3_type(const unsigned char n1, const unsigned char n2)
00744 {
00745         unsigned char value = (n1 << 4) | n2;
00746 
00747         switch (value) {
00748         case 0xcc:
00749                 return "Internet Protocol (RFC 791, ISO/IEC TR 9577)";
00750         case 0xcf:
00751                 return "Point-to-point Protocol (RFC 1548)";
00752         default:
00753                 return "unknown/invalid";
00754         }
00755 }
00756 
00757 L3INT Q931Die_BearerCap(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
00758 {
00759         Q931ie_BearerCap *pie = (Q931ie_BearerCap *)ie;
00760         strstream_printf(ostream,
00761                         "\tBearer Capability IE [%#02x]:\n"
00762                         "\t\tCoding:                              %s\n"
00763                         "\t\tInformation transfer cap.:           %s\n"
00764                         "\t\tTransfer mode:                       %s\n"
00765                         "\t\tInformation transfer rate:           %s\n",
00766                         pie->IEId,
00767                         q931_coding_type(pie->CodStand),
00768                         q931_information_transfer_capability_type(pie->ITC),
00769                         q931_transfer_mode_type(pie->TransMode),
00770                         q931_information_transfer_rate_type(pie->ITR));
00771 
00772         switch (pie->ITR) {
00773         case 0x18:
00774                 strstream_printf(ostream,
00775                          "\t\tRate-multiplier:                    %d (%d kbit/s)\n", pie->RateMul, pie->RateMul << 7);
00776         default:
00777                 break;
00778         }
00779 
00780         strstream_printf(ostream,
00781                         "\t\tUser information layer 1 protocol:   %s\n"
00782                         "\t\tUser information layer 2 protocol:   %s\n"
00783                         "\t\tUser information layer 3 protocol:   %s\n",
00784                         q931_user_information_layer1_type(pie->UIL1Prot),
00785                         q931_user_information_layer2_type(pie->UIL2Prot),
00786                         q931_user_information_layer3_type(pie->UIL3Prot));
00787 
00788         if (pie->UIL3Prot == 0x0b) {
00789                 strstream_printf(ostream,
00790                         "\t\tLayer 3 protocol:                    %s\n",
00791                         q931_tr9577_layer3_type(pie->AL3Info1, pie->AL3Info2));
00792         }
00793         return Q931E_NO_ERROR;
00794 }
00795 
00796 
00797 /********************************************************************************************************************************
00798  * Call ID IE
00799  ********************************************************************************************************************************/
00800 
00801 L3INT Q931Uie_CallID(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
00802 {
00803         Q931ie_CallID *pie = (Q931ie_CallID*)OBuf;
00804         ie *pIE = &pMsg->CallID;
00805         L3INT Off = 0;
00806         L3INT Octet = 0;
00807         L3INT x = 0;
00808         L3INT IESize;
00809 
00810         *pIE = 0;
00811 
00812         /* Octet 1 */
00813         pie->IEId = IBuf[Octet++];
00814 
00815         /* Octet 2 */
00816         IESize = IBuf[Octet++];
00817 
00818         /* Octet 3 */
00819         do {
00820                 pie->CallId[x] = IBuf[Octet + Off] & 0x7f;
00821                 Off++;
00822                 x++;
00823         } while (Q931MoreIE());
00824 
00825         Q931IESizeTest(Q931E_CALLID);
00826         Q931SetIE(*pIE, *OOff);
00827 
00828         *IOff = (*IOff) + Octet + Off;
00829         *OOff = (*OOff) + sizeof(Q931ie_CallID) + x - 1;
00830         pie->Size = (L3UCHAR)(sizeof(Q931ie_CallID) + x - 1);
00831 
00832         return Q931E_NO_ERROR;
00833 }
00834 
00835 L3INT Q931Pie_CallID(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
00836 {
00837         Q931ie_CallID *pIE = (Q931ie_CallID*)IBuf;
00838         L3INT rc = 0;
00839         L3INT Beg = *Octet;/* remember current offset */
00840         L3INT li;
00841         L3INT sCI = pIE->Size - sizeof(Q931ie_CallID) + 1;
00842         L3INT x;
00843 
00844         OBuf[(*Octet)++] = Q931ie_CALL_IDENTITY ;
00845         li = (*Octet)++; /* remember length position */
00846 
00847         for (x = 0; x < sCI; x++) {
00848                 OBuf[(*Octet)++] = pIE->CallId[x];
00849         }
00850 
00851         OBuf[(*Octet) - 1] |= 0x80; /* set complete flag at last octet*/
00852 
00853         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
00854         return rc;
00855 }
00856 
00857 L3INT Q931Die_CallID(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
00858 {
00859         Q931ie_CallID *pie = (Q931ie_CallID *)ie;
00860         strstream_printf(ostream,
00861                         "\tCall ID IE [%#02x]:\n"
00862                         "\t\tID:    [ ",
00863                         pie->IEId);
00864         strstream_printhex(ostream, (char *)pie->CallId, pie->Size - sizeof(*pie));
00865         strstream_puts(ostream, " ]\n");
00866         return Q931E_NO_ERROR;
00867 }
00868 
00869 
00870 /********************************************************************************************************************************
00871  * Call State IE
00872  ********************************************************************************************************************************/
00873 
00874 L3INT Q931Uie_CallState(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
00875 {
00876         Q931ie_CallState *pie = (Q931ie_CallState*)OBuf;
00877         ie *pIE = &pMsg->CallState;
00878         L3INT Off = 0;
00879         L3INT Octet = 0;
00880         L3INT IESize;
00881 
00882         *pIE = 0;
00883 
00884         /* Octet 1 */
00885         pie->IEId = IBuf[Octet++];
00886 
00887         /* Octet 2 */
00888         IESize = IBuf[Octet++];
00889 
00890         /* Octet 3 */
00891         pie->CodStand  = (IBuf[Octet + Off] >> 6) & 0x03;
00892         pie->CallState =  IBuf[Octet + Off] & 0x3f;
00893         Octet++;
00894 
00895         Q931IESizeTest(Q931E_CALLSTATE);
00896         Q931SetIE(*pIE, *OOff);
00897 
00898         *IOff = (*IOff) + Octet + Off;
00899         *OOff = (*OOff) + sizeof(Q931ie_CallState);
00900         pie->Size = sizeof(Q931ie_CallState);
00901 
00902         return Q931E_NO_ERROR;
00903 }
00904 
00905 L3INT Q931Pie_CallState(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
00906 {
00907         Q931ie_CallState *pIE = (Q931ie_CallState*)IBuf;
00908         L3INT rc = 0;
00909         L3INT Beg = *Octet; /* remember current offset */
00910         L3INT li;
00911 
00912         OBuf[(*Octet)++] = Q931ie_CALL_STATE;
00913         li = (*Octet)++; /* remember length position */
00914 
00915         OBuf[(*Octet)++] = ((pIE->CodStand & 0x03) << 6) | (pIE->CallState & 0x3f);
00916 
00917         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
00918         return rc;
00919 }
00920 
00921 static const struct {
00922         const unsigned char id;
00923         const char *name;
00924 } q931_callstate_names[] = {
00925         /* common */
00926         { 0x00, "Idle"                  },
00927 
00928         /* local */
00929         { 0x01, "Call initiated"        },
00930         { 0x02, "Overlap sending"       },
00931         { 0x03, "Outgoing call proceeding" },
00932         { 0x04, "Call delivered"        },
00933         { 0x06, "Call present"          },
00934         { 0x07, "Call received"         },
00935         { 0x08, "Connect request"       },
00936         { 0x09, "Incoming call proceeding" },
00937         { 0x0a, "Active"                },
00938         { 0x0b, "Disconnect request"    },
00939         { 0x0c, "Disconnect indication" },
00940         { 0x0f, "Suspend request"       },
00941         { 0x11, "Resume request"        },
00942         { 0x13, "Release request"       },
00943         { 0x16, "Call abort"            },
00944         { 0x19, "Overlap receiving"     },
00945 
00946         /* global */
00947         { 0x3d, "Restart request"       },
00948         { 0x3e, "Restart"               },
00949 };
00950 
00951 static const char *q931_callstate_name(const unsigned char state)
00952 {
00953         for (int i = 0; i < ARRAY_SIZE(q931_callstate_names); i++) {
00954                 if (q931_callstate_names[i].id == state)
00955                         return q931_callstate_names[i].name;
00956         }
00957         return "invalid";
00958 }
00959 
00960 L3INT Q931Die_CallState(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
00961 {
00962         Q931ie_CallState *pie = (Q931ie_CallState *)ie;
00963         strstream_printf(ostream,
00964                         "\tCall State IE [%#02x]:\n"
00965                         "\t\tCoding:     %s\n"
00966                         "\t\tState:      %s\n",
00967                         pie->IEId,
00968                         q931_coding_type(pie->CodStand),
00969                         q931_callstate_name(pie->CallState));
00970         return Q931E_NO_ERROR;
00971 }
00972 
00973 
00974 /********************************************************************************************************************************
00975  * Called SubAddress IE
00976  ********************************************************************************************************************************/
00977 
00978 L3INT Q931Uie_CalledSub(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
00979 {
00980         Q931ie_CalledSub *pie = (Q931ie_CalledSub*)OBuf;
00981         ie *pIE = &pMsg->CalledSub;
00982         L3INT Off = 0;
00983         L3INT Octet = 0;
00984         L3INT x;
00985         L3INT IESize;
00986 
00987         *pIE = 0;
00988 
00989         /* Octet 1 */
00990         pie->IEId = IBuf[Octet++];
00991 
00992         /* Octet 2 */
00993         IESize = IBuf[Octet++];
00994 
00995         /* Octet 3 */
00996         pie->TypNum     = (IBuf[Octet + Off] >> 4) & 0x07;
00997         pie->OddEvenInd = (IBuf[Octet + Off] >> 3) & 0x01;
00998         Octet++;
00999 
01000         /* Octet 4 */
01001         x = 0;
01002         do {
01003                 pie->Digit[x] = IBuf[Octet + Off] & 0x7f;
01004                 Off++;
01005                 x++;
01006         } while (Q931MoreIE() && x < 20);
01007 
01008         Q931IESizeTest(Q931E_CALLEDSUB);
01009         Q931SetIE(*pIE, *OOff);
01010 
01011         *IOff = (*IOff) + Octet + Off;
01012         *OOff = (*OOff) + sizeof(Q931ie_CalledSub) + x - 1;
01013         pie->Size = (L3UCHAR)(sizeof(Q931ie_CalledSub) + x - 1);
01014 
01015         return Q931E_NO_ERROR;
01016 }
01017 
01018 L3INT Q931Pie_CalledSub(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
01019 {
01020         Q931ie_CalledSub *pIE = (Q931ie_CalledSub*)IBuf;
01021         L3INT rc = 0;
01022         L3INT Beg = *Octet;
01023         L3INT li;
01024         L3INT sN = pIE->Size - sizeof(Q931ie_CalledSub) + 1;
01025         L3INT x;
01026 
01027         /* Octet 1 */
01028         OBuf[(*Octet)++] = Q931ie_CALLED_PARTY_SUBADDRESS;
01029         li = (*Octet)++;
01030 
01031         /* Octet 3 */
01032         OBuf[(*Octet)++] = 0x80 | (pIE->TypNum << 4) | (pIE->OddEvenInd << 3);
01033 
01034         /* Octet 4 */
01035         for (x = 0; x<sN; x++) {
01036                 OBuf[(*Octet)++] = pIE->Digit[x];
01037         }
01038 
01039         OBuf[(*Octet) - 1] |= 0x80; /* Terminate bit */
01040 
01041         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
01042         return rc;
01043 }
01044 
01045 L3INT Q931Die_CalledSub(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
01046 {
01047         Q931ie_CalledSub *pie = (Q931ie_CalledSub *)ie;
01048         char tmp[50] = { 0 };
01049         int ret = 0;
01050 
01051         if (nsap_afi_valid(pie->Digit[0])) {
01052                 struct nsap_addr nsap = { 0 };
01053                 int offset = 0;
01054 
01055                 /* Decode NSAP Address */
01056                 ret = nsap_decode(&nsap, (char *)&pie->Digit[0], pie->Size - sizeof(*pie));
01057                 if (ret != NSAPE_NO_ERROR) {
01058                         Q931Log(trunk, Q931_LOG_ERROR, "Failed to decode NSAP address\n");
01059                         return Q931E_INTERNAL;
01060                 }
01061                 nsap_print(&nsap, &tmp[offset], sizeof(tmp) - offset);
01062         }
01063         strstream_printf(ostream,
01064                         "\tCalled Party Subaddress IE [%#02x]:\n"
01065                         "\t\tType:        %s\n"
01066                         "\t\tOdd/Even:    %s\n"
01067                         "\t\tAddress:     %s\n",
01068                         pie->IEId, q931_subaddr_type(pie->TypNum), pie->OddEvenInd ? "Odd" : "Even", tmp);
01069         return Q931E_NO_ERROR;
01070 }
01071 
01072 
01073 /********************************************************************************************************************************
01074  * Called Number IE
01075  ********************************************************************************************************************************/
01076 
01077 L3INT Q931Uie_CalledNum(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
01078 {
01079         Q931ie_CalledNum *pie = (Q931ie_CalledNum*)OBuf;
01080         ie *pIE = &pMsg->CalledNum;
01081         L3INT Off = 0;
01082         L3INT Octet = 0;
01083         L3INT x;
01084         L3INT IESize; /* # digits in this case */
01085 
01086         *pIE = 0;
01087 
01088         /* Octet 1 */
01089         pie->IEId = IBuf[Octet++];
01090 
01091         /* Octet 2 */
01092         IESize = IBuf[Octet++];
01093 
01094         /* Octet 3 */
01095         pie->TypNum    = (IBuf[Octet + Off] >> 4) & 0x07;
01096         pie->NumPlanID =  IBuf[Octet + Off] & 0x0f;
01097         Octet++;
01098 
01099         /* Octet 4*/
01100         x = 0;
01101         do {
01102                 pie->Digit[x] = IBuf[Octet + Off] & 0x7f;
01103                 Off++;
01104                 x++;
01105         } while ((IBuf[Octet + Off]&0x80) == 0 && Q931MoreIE());
01106 
01107         pie->Digit[x] = '\0';
01108 
01109         Q931SetIE(*pIE, *OOff);
01110 
01111         *IOff = (*IOff) + Octet + Off;
01112         *OOff = (*OOff) + sizeof(Q931ie_CalledNum) + x;
01113         pie->Size = (L3UCHAR)(sizeof(Q931ie_CalledNum) + x);
01114 
01115         return Q931E_NO_ERROR;
01116 }
01117 
01118 L3INT Q931Pie_CalledNum(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
01119 {
01120         Q931ie_CalledNum *pIE = (Q931ie_CalledNum*)IBuf;
01121         L3INT rc = 0;
01122         L3INT Beg = *Octet;
01123         L3INT li;
01124         L3INT sN = pIE->Size - sizeof(Q931ie_CalledNum);
01125         L3INT x;
01126 
01127         /* Octet 1 */
01128         OBuf[(*Octet)++] = Q931ie_CALLED_PARTY_NUMBER;
01129 
01130         /* Octet 2 */
01131         li = (*Octet)++;
01132 
01133         /* Octet 3 */
01134         OBuf[(*Octet)++] = 0x80 | (pIE->TypNum << 4) | (pIE->NumPlanID);
01135 
01136         /* Octet 4 */
01137         for (x = 0; x<sN; x++) {
01138                 OBuf[(*Octet)++] = pIE->Digit[x];
01139         }
01140 
01141         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
01142         return rc;
01143 }
01144 
01145 L3INT Q931Die_CalledNum(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
01146 {
01147         Q931ie_CalledNum *pie = (Q931ie_CalledNum *)ie;
01148         strstream_printf(ostream,
01149                         "\tCalled Party Number IE [%#02x]:\n"
01150                         "\t\tType of number:    %s\n"
01151                         "\t\tNumbering plan:    %s\n"
01152                         "\t\tNumber:            %.*s\n",
01153                         pie->IEId, q931_ton_type(pie->TypNum),
01154                         q931_numbering_plan_type(pie->NumPlanID),
01155                         pie->Size - sizeof(*pie), pie->Digit);
01156         return Q931E_NO_ERROR;
01157 }
01158 
01159 
01160 /********************************************************************************************************************************
01161  * Calling Number IE
01162  ********************************************************************************************************************************/
01163 
01164 L3INT Q931Uie_CallingNum(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
01165 {
01166         Q931ie_CallingNum *pie = (Q931ie_CallingNum*)OBuf;
01167         ie *pIE = &pMsg->CallingNum;
01168         L3INT Off = 0;
01169         L3INT Octet = 0;
01170         L3INT x;
01171         L3INT IESize;
01172 
01173         *pIE = 0;
01174 
01175         /* Octet 1 */
01176         pie->IEId = IBuf[Octet++];
01177 
01178         /* Octet 2 */
01179         IESize = IBuf[Octet++];
01180 
01181         /* Octet 3 */
01182         pie->TypNum    = (IBuf[Octet + Off] >> 4) & 0x07;
01183         pie->NumPlanID =  IBuf[Octet + Off] & 0x0f;
01184 
01185         /* Octet 3a */
01186         if ((IBuf[Octet + Off] & 0x80) == 0) {
01187                 Off++;
01188                 pie->PresInd   = (IBuf[Octet + Off] >> 5) & 0x03;
01189                 pie->ScreenInd =  IBuf[Octet + Off] & 0x03;
01190         }
01191         Octet++;
01192 
01193         /* Octet 4 */
01194         x = 0;
01195         while (Q931MoreIE()) {
01196                 pie->Digit[x++] = IBuf[Octet + Off] & 0x7f;
01197 
01198                 if ((IBuf[Octet + Off] & 0x80) != 0) {
01199                         break;
01200                 }
01201                 Off++;
01202         }
01203         pie->Digit[x] = '\0';
01204 
01205         Q931IESizeTest(Q931E_CALLINGNUM);
01206         Q931SetIE(*pIE, *OOff);
01207 
01208         *IOff = (*IOff) + Octet + Off;
01209         *OOff = (*OOff) + sizeof(Q931ie_CallingNum) + x;
01210         pie->Size = (L3UCHAR)(sizeof(Q931ie_CallingNum) + x);
01211 
01212         return Q931E_NO_ERROR;
01213 }
01214 
01215 L3INT Q931Pie_CallingNum(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
01216 {
01217         Q931ie_CallingNum *pIE = (Q931ie_CallingNum*)IBuf;
01218         L3INT rc = 0;
01219         L3INT Beg = *Octet;
01220         L3INT li;
01221         L3INT sN = pIE->Size - sizeof(Q931ie_CallingNum);
01222         L3INT x;
01223 
01224         /* Octet 1 */
01225         OBuf[(*Octet)++] = Q931ie_CALLING_PARTY_NUMBER;
01226 
01227         /* Octet 2 */
01228         li = (*Octet)++;
01229 
01230         /* Octet 3 */
01231         OBuf[(*Octet)++] = 0x00 | (pIE->TypNum << 4) | (pIE->NumPlanID);
01232 
01233         /* Octet 4 */
01234         OBuf[(*Octet)++] = 0x80;
01235 
01236         /* Octet 5 */
01237         for (x = 0; x<sN; x++) {
01238                 OBuf[(*Octet)++] = pIE->Digit[x];
01239         }
01240 
01241         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
01242         return rc;
01243 }
01244 
01245 L3INT Q931Die_CallingNum(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
01246 {
01247         Q931ie_CallingNum *pie = (Q931ie_CallingNum *)ie;
01248         strstream_printf(ostream,
01249                         "\tCalling Party Number IE [%#02x]:\n"
01250                         "\t\tType of number:    %s\n"
01251                         "\t\tNumbering plan:    %s\n"
01252                         "\t\tPresentation:      %s\n"
01253                         "\t\tScreening:         %s\n"
01254                         "\t\tNumber:            %.*s\n",
01255                         pie->IEId, q931_ton_type(pie->TypNum),
01256                         q931_numbering_plan_type(pie->NumPlanID),
01257                         q931_presentation_type(pie->PresInd),
01258                         q931_screening_type(pie->ScreenInd),
01259                         pie->Size - sizeof(*pie), pie->Digit);
01260         return Q931E_NO_ERROR;
01261 }
01262 
01263 
01264 /********************************************************************************************************************************
01265  * Calling SubAddress IE
01266  ********************************************************************************************************************************/
01267 
01268 L3INT Q931Uie_CallingSub(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
01269 {
01270         Q931ie_CallingSub *pie = (Q931ie_CallingSub*)OBuf;
01271         ie *pIE = &pMsg->CallingSub;
01272         L3INT Off = 0;
01273         L3INT Octet = 0;
01274         L3INT x;
01275         L3INT IESize;
01276 
01277         *pIE = 0;
01278 
01279         /* Octet 1 */
01280         pie->IEId = IBuf[Octet++];
01281 
01282         /* Octet 2 */
01283         IESize = IBuf[Octet++];
01284 
01285         /* Octet 3 */
01286         pie->TypNum     = (IBuf[Octet + Off] >> 4) & 0x07;
01287         pie->OddEvenInd = (IBuf[Octet + Off] >> 3) & 0x01;
01288         Octet++;
01289 
01290         /* Octet 4*/
01291         x = 0;
01292         do {
01293                 pie->Digit[x] = IBuf[Octet + Off] & 0x7f;
01294                 Off++;
01295                 x++;
01296         } while (Q931MoreIE() && x < 20);
01297 
01298         Q931IESizeTest(Q931E_CALLINGSUB);
01299         Q931SetIE(*pIE, *OOff);
01300 
01301         *IOff = (*IOff) + Octet + Off;
01302         *OOff = (*OOff) + sizeof(Q931ie_CallingSub) + x -1;
01303         pie->Size = (L3UCHAR)(sizeof(Q931ie_CallingSub) + x -1);
01304 
01305         return Q931E_NO_ERROR;
01306 }
01307 
01308 L3INT Q931Pie_CallingSub(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
01309 {
01310         Q931ie_CallingSub *pIE = (Q931ie_CallingSub*)IBuf;
01311         L3INT rc = 0;
01312         L3INT Beg = *Octet;
01313         L3INT li;
01314         L3INT sN = pIE->Size - sizeof(Q931ie_CallingSub) + 1;
01315         L3INT x;
01316 
01317         /* Octet 1 */
01318         OBuf[(*Octet)++] = Q931ie_CALLING_PARTY_SUBADDRESS;
01319         li = (*Octet)++;
01320 
01321         /* Octet 3 */
01322         OBuf[(*Octet)++] = 0x80 | (pIE->TypNum << 4) | (pIE->OddEvenInd << 3);
01323 
01324         /* Octet 4 */
01325         for (x = 0; x<sN; x++) {
01326                 OBuf[(*Octet)++] = pIE->Digit[x];
01327         }
01328 
01329         OBuf[(*Octet) - 1] |= 0x80; /* Terminate bit */
01330 
01331         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
01332         return rc;
01333 }
01334 
01335 L3INT Q931Die_CallingSub(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
01336 {
01337         Q931ie_CallingSub *pie = (Q931ie_CallingSub *)ie;
01338         char tmp[50] = { 0 };
01339 
01340         strstream_printf(ostream,
01341                         "\tCalling Party Subaddress IE [%#02x]:\n",
01342                         "\t\tType:      %s\n"
01343                         "\t\tOdd/Even:  %s\n"
01344                         "\t\tAddress:   %s\n",
01345                         pie->IEId, q931_subaddr_type(pie->TypNum), pie->OddEvenInd ? "Odd" : "Even", tmp);
01346         return Q931E_NO_ERROR;
01347 }
01348 
01349 
01350 /********************************************************************************************************************************
01351  * Cause IE
01352  ********************************************************************************************************************************/
01353 
01354 L3INT Q931Uie_Cause(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
01355 {
01356         Q931ie_Cause *pie = (Q931ie_Cause*)OBuf;
01357         ie *pIE = &pMsg->Cause;
01358         L3INT Off = 0;
01359         L3INT Octet = 0;
01360         L3INT IESize;
01361 
01362         *pIE = 0;
01363 
01364         pie->IEId = IBuf[Octet++];
01365 
01366         /* Octet 2*/
01367         IESize = IBuf[Octet++];
01368 
01369         /* Octet 3*/
01370         pie->CodStand = (IBuf[Octet + Off]>>5) & 0x03;
01371         pie->Location =  IBuf[Octet + Off] & 0x0f;
01372 
01373         /* Octet 3a */
01374         if ((IBuf[Octet + Off] & 0x80) == 0) {
01375                 Off++;
01376                 pie->Recom = IBuf[Octet + Off] & 0x7f;
01377         }
01378         Octet++;
01379 
01380         /* Octet 4 */
01381         pie->Value = IBuf[Octet + Off] & 0x7f;
01382         Octet++;
01383 
01384         /* Consume optional Diagnostic bytes */
01385         while (Q931MoreIE()) {
01386                 Off++;
01387         };
01388 
01389         Q931IESizeTest(Q931E_CAUSE);
01390         Q931SetIE(*pIE, *OOff);
01391 
01392         *IOff = (*IOff) + Octet + Off;
01393         *OOff = (*OOff) + sizeof(Q931ie_Cause);
01394         pie->Size = sizeof(Q931ie_Cause);
01395 
01396         return Q931E_NO_ERROR;
01397 }
01398 
01399 L3INT Q931Pie_Cause(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
01400 {
01401         Q931ie_Cause *pIE = (Q931ie_Cause*)IBuf;
01402         L3INT rc = 0;
01403         L3INT Beg = *Octet;
01404         L3INT li;
01405 
01406         OBuf[(*Octet)++] = Q931ie_CAUSE;
01407         li = (*Octet)++;
01408 
01409         /* Octet 3 */
01410         OBuf[(*Octet)++] = 0x80 | (pIE->CodStand<<5) | pIE->Location;
01411 
01412         /* Octet 3a - currently not supported in send */
01413 
01414         /* Octet 4 */
01415         OBuf[(*Octet)++] = 0x80 | pIE->Value;
01416 
01417         /* Octet 5 - diagnostics not supported in send */
01418 
01419         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
01420         return rc;
01421 }
01422 
01423 L3INT Q931Die_Cause(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
01424 {
01425         Q931ie_Cause *pie = (Q931ie_Cause *)ie;
01426         strstream_printf(ostream,
01427                         "\tCause IE [%#02x]:\n"
01428                         "\t\tCoding:   %s\n"
01429                         "\t\tLocation: %s\n"
01430                         "\t\tCode:     %d (%s)\n",
01431                         pie->IEId, q931_coding_type(pie->CodStand), q931_location_type(pie->Location),
01432                         pie->Value, Q850CauseGetName(pie->Value));
01433         return Q931E_NO_ERROR;
01434 }
01435 
01436 
01437 /********************************************************************************************************************************
01438  * Congestion Level IE
01439  ********************************************************************************************************************************/
01440 
01441 L3INT Q931Uie_CongLevel(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
01442 {
01443         Q931ie_CongLevel *pie = (Q931ie_CongLevel*)OBuf;
01444         ie *pIE = &pMsg->CongestionLevel;
01445         L3INT Off = 0;
01446         L3INT Octet = 0;
01447 
01448         *pIE = 0;
01449 
01450         pie->IEId      = IBuf[Octet] & 0xf0;
01451         pie->CongLevel = IBuf[Octet] & 0x0f;
01452         Octet ++;
01453 
01454         Q931SetIE(*pIE, *OOff);
01455 
01456         *IOff = (*IOff) + Octet + Off;
01457         *OOff = (*OOff) + sizeof(Q931ie_CongLevel);
01458         pie->Size = sizeof(Q931ie_CongLevel);
01459 
01460         return Q931E_NO_ERROR;
01461 }
01462 
01463 L3INT Q931Pie_CongLevel(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
01464 {
01465         Q931ie_CongLevel *pIE = (Q931ie_CongLevel*)IBuf;
01466         L3INT rc = 0;
01467         /* L3INT Beg = *Octet; */
01468 
01469         OBuf[(*Octet)++] = Q931ie_CONGESTION_LEVEL | pIE->CongLevel;
01470 
01471         return rc;
01472 }
01473 
01474 
01475 static const char *q931_congestion_level_type(const unsigned char type)
01476 {
01477         switch (type) {
01478         case 0x00:
01479                 return "Receiver ready";
01480         case 0x0f:
01481                 return "Receiver not ready";
01482         default:
01483                 return "reserved";
01484         }
01485 }
01486 
01487 L3INT Q931Die_CongLevel(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
01488 {
01489         Q931ie_CongLevel *pie = (Q931ie_CongLevel *)ie;
01490         strstream_printf(ostream,
01491                         "\tCongestion Level IE [%#02x]:\n"
01492                         "\t\tLevel:   %s\n",
01493                         pie->IEId, q931_congestion_level_type(pie->CongLevel));
01494         return Q931E_NO_ERROR;
01495 }
01496 
01497 
01498 /********************************************************************************************************************************
01499  * Channel ID IE
01500  ********************************************************************************************************************************/
01501 
01502 L3INT Q931Uie_ChanID(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR *OBuf, L3INT *IOff, L3INT *OOff)
01503 {
01504         Q931ie_ChanID *pie = (Q931ie_ChanID*)OBuf;
01505         ie *pIE = &pMsg->ChanID;
01506         L3INT Off = 0;
01507         L3INT Octet = 0;
01508         L3INT IESize;
01509 //18 04 e1 80 83 01
01510         *pIE = 0;
01511 
01512         Q931Log(trunk, Q931_LOG_DEBUG, "Decoding ChanID IE\n");
01513 
01514         /* Octet 1 */
01515         pie->IEId = IBuf[Octet++];
01516 
01517         /* Octet 2 */
01518         IESize    = IBuf[Octet++];
01519 
01520         /* Octet 3 */
01521         pie->IntIDPresent = (IBuf[Octet] >> 6) & 0x01;
01522         pie->IntType      = (IBuf[Octet] >> 5) & 0x01;
01523         pie->PrefExcl     = (IBuf[Octet] >> 3) & 0x01;
01524         pie->DChanInd     = (IBuf[Octet] >> 2) & 0x01;
01525         pie->InfoChanSel  =  IBuf[Octet] & 0x03;
01526 
01527         Off = Q931ReadExt(&IBuf[Octet++], Off);
01528 
01529         /* Octet 3.1 */
01530         if (pie->IntIDPresent) {
01531                 pie->InterfaceID = IBuf[Octet + Off] & 0x7f;
01532 
01533                 /* Temp fix. Interface id can be extended using the extension bit */
01534                 /* this will read the octets, but do nothing with them. this is done */
01535                 /* because the usage of this field is a little unclear */
01536                 /* 30.jan.2001/JVB */
01537                 Off = Q931ReadExt(&IBuf[Octet + Off], Off);
01538                 Off++;
01539         }
01540 
01541         if ((Octet + Off - 2) != IESize) {
01542                 /* Octet 3.2 */
01543                 if (pie->IntType == 1) {        /* PRI etc */
01544                         pie->CodStand    = (IBuf[Octet + Off] >> 5) & 0x03;
01545                         pie->NumMap      = (IBuf[Octet + Off] >> 4) & 0x01;
01546                         pie->ChanMapType =  IBuf[Octet + Off] & 0x0f;
01547                         Off++;
01548 
01549                         /* Octet 3.3 */
01550                         /* Temp fix. Assume B channel. H channels not supported */
01551                         pie->ChanSlot = IBuf[Octet + Off] & 0x7f;
01552 
01553                         /* Some dialects don't follow the extension coding properly for this, but this should be safe for all */
01554                         if ((Octet + Off - 1) != IESize) {
01555                                 Off = Q931ReadExt(&IBuf[Octet + Off], Off);
01556                         }
01557                         Off++;
01558                 }
01559         }
01560 
01561         Q931IESizeTest(Q931E_CHANID);
01562         Q931SetIE(*pIE, *OOff);
01563 
01564         *IOff = (*IOff) + Octet + Off;
01565         *OOff = (*OOff) + sizeof(Q931ie_ChanID);
01566         pie->Size = sizeof(Q931ie_ChanID);
01567 
01568         if (trunk->loglevel == Q931_LOG_DEBUG) {
01569                 const char *iface;
01570                 char tmp[100] = "";
01571 
01572                 if (!pie->IntType) {
01573                         switch (pie->InfoChanSel) {
01574                         case 0x0:
01575                                 iface = "None";
01576                                 break;
01577                         case 0x1:
01578                                 iface = "B1";
01579                                 break;
01580                         case 0x2:
01581                                 iface = "B2";
01582                                 break;
01583                         default:
01584                                 iface = "Any Channel";
01585                         }
01586 
01587                         snprintf(tmp, sizeof(tmp)-1, "InfoChanSel: %d (%s)", pie->InfoChanSel, iface);
01588                 }
01589 
01590                 Q931Log(trunk, Q931_LOG_DEBUG,
01591                         "\n-------------------------- Q.931 Channel ID ------------------------\n"
01592                         "    Pref/Excl: %s, Interface Type: %s\n"
01593                         "    %s\n"
01594                         "--------------------------------------------------------------------\n\n",
01595                         ((pie->PrefExcl) ? "Preferred" : "Exclusive"),
01596                         ((pie->IntType) ? "PRI/Other" : "BRI"),
01597                         tmp);
01598         }
01599         return Q931E_NO_ERROR;
01600 }
01601 
01602 L3INT Q931Pie_ChanID(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
01603 {
01604         Q931ie_ChanID *pIE = (Q931ie_ChanID*)IBuf;
01605         L3INT rc = Q931E_NO_ERROR;
01606         L3INT Beg = *Octet;     /* remember current offset */
01607         L3INT li;
01608 
01609         OBuf[(*Octet)++] = Q931ie_CHANNEL_IDENTIFICATION;
01610         li = (*Octet)++; /* remember length position */
01611 
01612         /* Octet 3 flags & BRI chan # */
01613         OBuf[(*Octet)++] = 0x80
01614                         | ((pIE->IntIDPresent << 6) & 0x40)
01615                         | ((pIE->IntType << 5) & 0x20)
01616                         | ((pIE->PrefExcl << 3) & 0x08)
01617                         |  (pIE->InfoChanSel & 0x03);
01618 
01619         /* Octet 3.1 - Interface Identifier */
01620         if (pIE->IntIDPresent) {
01621                 OBuf[(*Octet)++] = 0x80 | (pIE->InterfaceID & 0x7f);
01622         }
01623 
01624         /* Octet 3.2 & 3.3 - PRI */
01625         if (pIE->IntType) {
01626                 OBuf[(*Octet)++]  = 0x80
01627                         | ((pIE->CodStand << 5) & 0x60)
01628                         | ((pIE->NumMap << 4) & 0x10)
01629                         |  (pIE->ChanMapType & 0x0f);           /* TODO: support all possible channel map types */
01630 
01631                 /* Octet 3.3 Channel number */
01632                 switch (pIE->ChanMapType) {
01633                 case 0x6:       /* Slot map: H0 Channel Units */        /* unsupported, Octets 3.3.1 - 3.3.3 */
01634                         return Q931E_CHANID;
01635 
01636                 case 0x8:       /* Slot map: H11 Channel Units */
01637                 case 0x9:       /* Slot map: H12 Channel Units */
01638                 default:        /* Channel number */
01639                         OBuf[(*Octet)++] = 0x80 | (pIE->ChanSlot & 0x7f);
01640                         break;
01641                 }
01642         }
01643 
01644         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
01645         return rc;
01646 }
01647 
01648 L3INT Q931Die_ChanID(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
01649 {
01650         Q931ie_ChanID *pie = (Q931ie_ChanID *)ie;
01651         char tmp[1024] = { 0 };
01652         int offset = 0;
01653 
01654         if (!pie->IntType) {    /* BRI */
01655                 const char *iface;
01656 
01657                 switch (pie->InfoChanSel) {
01658                 case 0x0:
01659                         iface = "None";
01660                         break;
01661                 case 0x1:
01662                         iface = "B1";
01663                         break;
01664                 case 0x2:
01665                         iface = "B2";
01666                         break;
01667                 default:
01668                         iface = "Any Channel";
01669                 }
01670 
01671                 offset += snprintf(tmp, sizeof(tmp) - 1, "\t\tInfoChanSel:          %d (%s)", pie->InfoChanSel, iface);
01672         } else {        /* PRI */
01673                 const char *iface;
01674 
01675                 switch (pie->InfoChanSel) {
01676                 case 0x0:
01677                         iface = "None";
01678                         break;
01679                 case 0x1:
01680                         iface = "As indicated";
01681                         break;
01682                 case 0x2:
01683                         iface = "Reserved";
01684                         break;
01685                 default:
01686                         iface = "Any Channel";
01687                 }
01688 
01689                 offset += snprintf(tmp, sizeof(tmp) - 1, "\t\tInfoChanSel:          %d (%s)\n", pie->InfoChanSel, iface);
01690         }
01691 
01692         if (pie->ChanSlot) {
01693                 offset += snprintf(tmp + offset, sizeof(tmp) - offset - 1, "\t\tChannel:              %d\n", pie->ChanSlot);
01694         } else if (pie->InterfaceID) {
01695                 offset += snprintf(tmp + offset, sizeof(tmp) - offset - 1, "\t\tInterface:            %d\n", pie->InterfaceID);
01696         }
01697 
01698         strstream_printf(ostream,
01699                 "\tChannel ID IE [%#02x]:\n"
01700                 "\t\tPreferred/Exclusive:  %s\n"
01701                 "\t\tInterface Type:       %s\n"
01702                 "%s",
01703                 pie->IEId,
01704                 ((pie->PrefExcl) ? "Preferred" : "Exclusive"),
01705                 ((pie->IntType) ? "PRI/Other" : "BRI"),
01706                 tmp);
01707         return Q931E_NO_ERROR;
01708 }
01709 
01710 
01711 /********************************************************************************************************************************
01712  * DateTime IE
01713  ********************************************************************************************************************************/
01714 
01715 L3INT Q931Uie_DateTime(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *IOff, L3INT *OOff)
01716 {
01717         Q931ie_DateTime * pie = (Q931ie_DateTime*)OBuf;
01718         ie *pIE = &pMsg->DateTime;
01719         L3INT Off = 0;
01720         L3INT Octet = 0;
01721         L3INT IESize = 0;
01722 
01723         *pIE = 0;
01724 
01725         pie->IEId = IBuf[Octet++];
01726 
01727         /* Octet 2 */
01728         IESize = IBuf[Octet++];
01729 
01730         /* Octet 3 - Year */
01731         pie->Year = IBuf[Octet++];
01732 
01733         /* Octet 4 - Month */
01734         pie->Month = IBuf[Octet++];
01735 
01736         /* Octet 5 - Day */
01737         pie->Day = IBuf[Octet++];
01738 
01739         /*******************************************************************
01740                 The remaining part of the IE are optioinal, but only the length
01741                 can now tell us wherever these fields are present or not
01742                 (always remember: IESize does not include ID and Size octet)
01743         ********************************************************************/
01744         pie->Format = 0;
01745 
01746         /* Octet 6 - Hour (optional)*/
01747         if (IESize >= 4) {
01748                 pie->Format = 1;
01749                 pie->Hour = IBuf[Octet++];
01750 
01751                 /* Octet 7 - Minute (optional)*/
01752                 if (IESize >= 5) {
01753                         pie->Format = 2;
01754                         pie->Minute = IBuf[Octet++];
01755 
01756                         /* Octet 8 - Second (optional)*/
01757                         if (IESize >= 6) {
01758                                 pie->Format = 3;
01759                                 pie->Second = IBuf[Octet++];
01760                         }
01761                 }
01762         }
01763 
01764         Q931IESizeTest(Q931E_DATETIME);
01765         Q931SetIE(*pIE, *OOff);
01766 
01767         *IOff = (*IOff) + Octet + Off;
01768         *OOff = (*OOff) + sizeof(Q931ie_DateTime);
01769         pie->Size = sizeof(Q931ie_DateTime);
01770 
01771         return Q931E_NO_ERROR;
01772 }
01773 
01774 L3INT Q931Pie_DateTime(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
01775 {
01776         Q931ie_DateTime *pIE = (Q931ie_DateTime*)IBuf;
01777         L3INT rc = 0;
01778         L3INT Beg = *Octet;
01779         L3INT li;
01780 
01781         OBuf[(*Octet)++] = Q931ie_DATETIME;
01782         li = (*Octet)++;
01783 
01784         OBuf[(*Octet)++] = pIE->Year;
01785         OBuf[(*Octet)++] = pIE->Month;
01786         OBuf[(*Octet)++] = pIE->Day;
01787         if (pIE->Format >= 1) {
01788                 OBuf[(*Octet)++] = pIE->Hour;
01789 
01790                 if (pIE->Format >= 2) {
01791                         OBuf[(*Octet)++] = pIE->Minute;
01792 
01793                         if (pIE->Format >= 3) {
01794                                 OBuf[(*Octet)++] = pIE->Second;
01795                         }
01796                 }
01797         }
01798 
01799         OBuf[li] = (L3UCHAR)((*Octet)-Beg) - 2;
01800         return rc;
01801 }
01802 
01803 L3INT Q931Die_DateTime(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
01804 {
01805         Q931ie_DateTime *pie = (Q931ie_DateTime *)ie;
01806         char tmp[50] = { 0 };
01807 
01808         switch (pie->Format) {
01809         case 3:
01810                 sprintf(tmp, "%02u:%02u:%02u [hh:mm:ss]", pie->Hour, pie->Minute, pie->Second);
01811                 break;
01812         case 2:
01813                 sprintf(tmp, "%02u:%02u [hh:mm]", pie->Hour, pie->Minute);
01814                 break;
01815         case 1:
01816                 sprintf(tmp, "%02u [hh]", pie->Hour);
01817                 break;
01818         default:
01819                 strcat(tmp, "N/A");
01820                 break;
01821         }
01822 
01823         strstream_printf(ostream,
01824                         "\tDateTime IE [%#02x]:\n"
01825                         "\t\tDate:   %02u/%02u/%02u [mm/dd/yy]\n"
01826                         "\t\tTime:   %s\n",
01827                         pie->IEId, pie->Month, pie->Day, pie->Year, tmp);
01828         return Q931E_NO_ERROR;
01829 }
01830 
01831 
01832 /********************************************************************************************************************************
01833  * Display IE
01834  ********************************************************************************************************************************/
01835 
01836 L3INT Q931Uie_Display(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
01837 {
01838         Q931ie_Display *pie = (Q931ie_Display*)OBuf;
01839         ie *pIE = &pMsg->Display;
01840         L3INT Off = 0;
01841         L3INT Octet = 0;
01842         L3INT IESize;
01843         L3INT x;
01844 
01845         *pIE = 0;
01846 
01847         pie->IEId = IBuf[Octet++];
01848         IESize    = IBuf[Octet++];
01849 
01850         for (x = 0; x<IESize; x++) {
01851                 pie->Display[x] = IBuf[Octet + Off] & 0x7f;
01852                 Off++;
01853         }
01854 
01855         Q931IESizeTest(Q931E_DISPLAY);
01856         Q931SetIE(*pIE, *OOff);
01857 
01858         *IOff = (*IOff) + Octet + Off;
01859         *OOff = (*OOff) + sizeof(Q931ie_Display) + x - 1;
01860         pie->Size = (L3UCHAR)(sizeof(Q931ie_Display) + x - 1);
01861 
01862         return Q931E_NO_ERROR;
01863 }
01864 
01865 L3INT Q931Pie_Display(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
01866 {
01867         Q931ie_Display *pIE = (Q931ie_Display*)IBuf;
01868         L3INT rc = 0;
01869         L3INT Beg = *Octet;
01870         L3INT li;
01871         L3INT DSize;
01872         L3INT x;
01873 
01874         OBuf[(*Octet)++] = Q931ie_DISPLAY;
01875         li = (*Octet)++;
01876 
01877         DSize = pIE->Size - sizeof(Q931ie_Display);
01878 
01879         for (x = 0; x< DSize; x++) {
01880 
01881                 OBuf[(*Octet)++] = pIE->Display[x];
01882         }
01883 
01884         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
01885         return rc;
01886 }
01887 
01888 L3INT Q931Die_Display(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
01889 {
01890         Q931ie_Display *pie = (Q931ie_Display *)ie;
01891         strstream_printf(ostream,
01892                         "\tDisplay IE [%#02x]:\n"
01893                         "\t\tValue:   %.*s\n",
01894                         pie->IEId, pie->Size - sizeof(*pie), pie->Display);
01895         return Q931E_NO_ERROR;
01896 }
01897 
01898 
01899 /********************************************************************************************************************************
01900  * High-Layer Compat IE
01901  ********************************************************************************************************************************/
01902 
01903 L3INT Q931Uie_HLComp(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
01904 {
01905         Q931ie_HLComp * pie = (Q931ie_HLComp*)OBuf;
01906         ie *pIE = &pMsg->HLComp;
01907         L3INT Off = 0;
01908         L3INT Octet = 0;
01909         L3INT IESize;
01910 
01911         *pIE = 0;
01912 
01913         pie->IEId = IBuf[Octet++];
01914 
01915         /* Octet */
01916         IESize = IBuf[Octet++];
01917 
01918         /* Octet 3*/
01919         pie->CodStand  = (IBuf[Octet + Off] >>5) & 0x03;
01920         pie->Interpret = (IBuf[Octet + Off] >>2) & 0x07;
01921         pie->PresMeth  =  IBuf[Octet + Off] & 0x03;
01922         Octet++;
01923 
01924         /* Octet 4 */
01925         pie->HLCharID = IBuf[Octet + Off] & 0x7f;
01926         Octet++;
01927 
01928         /* Octet 4a*/
01929         if ((IBuf[Octet + Off - 1] & 0x80) == 0 && Q931MoreIE()) {
01930                 if (pie->HLCharID == 0x5e || pie->HLCharID == 0x5f) {
01931                         pie->EHLCharID = IBuf[Octet + Off] & 0x7f;
01932                         Off++;
01933                 }
01934                 else if ( pie->HLCharID >= 0xc3 && pie->HLCharID <= 0xcf) {
01935                         pie->EVideoTlfCharID = IBuf[Octet + Off] & 0x7f;
01936                         Off++;
01937                 }
01938                 else {
01939                         /* error Octet 4a indicated, but invalid value in Octet 4. */
01940                         Q931SetError(trunk,Q931E_HLCOMP, 4, Off);
01941                         return Q931E_HLCOMP;
01942                 }
01943                 Off = Q931ReadExt(&IBuf[Octet + Off], Off);
01944         }
01945 
01946         Q931IESizeTest(Q931E_HLCOMP);
01947         Q931SetIE(*pIE, *OOff);
01948 
01949         *IOff = (*IOff) + Octet + Off;
01950         *OOff = (*OOff) + sizeof(Q931ie_HLComp);
01951         pie->Size = sizeof(Q931ie_HLComp);
01952 
01953         return Q931E_NO_ERROR;
01954 }
01955 
01956 L3INT Q931Pie_HLComp(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
01957 {
01958         Q931ie_HLComp *pIE = (Q931ie_HLComp*)IBuf;
01959         L3INT rc = 0;
01960         L3INT Beg = *Octet;
01961         L3INT li;
01962 
01963         OBuf[(*Octet)++] = Q931ie_HIGH_LAYER_COMPATIBILITY;
01964         li = (*Octet)++;
01965 
01966         /* Octet 3 */
01967         OBuf[(*Octet)++] = 0x80 | ((pIE->CodStand << 5) & 0x60) | ((pIE->Interpret << 2) & 0x1c) | (pIE->PresMeth & 0x03);
01968 
01969         /* Octet 4 */
01970         OBuf[(*Octet)++] = pIE->HLCharID;
01971 
01972         /* Octet 4a */
01973         if (pIE->HLCharID == 0x5e || pIE->HLCharID == 0x5f) {
01974                 OBuf[(*Octet)++] = 0x80 | (pIE->EHLCharID & 0x7f);
01975         }
01976         else if ( pIE->HLCharID >= 0xc3 && pIE->HLCharID <= 0xcf) {
01977                 OBuf[(*Octet)++] = 0x80 | (pIE->EVideoTlfCharID & 0x7f);
01978         }
01979         else {
01980                 OBuf[(*Octet) - 1] |= 0x80;
01981         }
01982 
01983         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
01984         return rc;
01985 }
01986 
01987 static const char *q931_hl_characteristics_type(const unsigned char type)
01988 {
01989         switch (type) {
01990         case 0x01:
01991                 return "Telephony";
01992         case 0x04:
01993                 return "Facsimile Group 2/3 (F.182)";
01994         case 0x21:
01995                 return "Facsimile Group 4 Class I (F.184)";
01996         case 0x24:
01997                 return "Facsimile Group 4 Classes II and III (F.184)";
01998         case 0x28:
01999                 return "-";
02000         case 0x31:
02001                 return "-";
02002         case 0x32:
02003                 return "Syntax based Videotex (F.300 and T.102)";
02004         case 0x33:
02005                 return "Internationel Videotex interworking via gateways or interworking units (F.300 and T.101)";
02006         case 0x35:
02007                 return "Telex service (F.60)";
02008         case 0x38:
02009                 return "Message Handling System (MHS, X.400-series)";
02010         case 0x41:
02011                 return "OSI application (X.200-series)";
02012         case 0x42:
02013                 return "FTAM application (ISO 8571)";
02014         case 0x5e:
02015                 return "Reserved for maintenance";
02016         case 0x5f:
02017                 return "Reserved for maintenance";
02018         case 0x60:
02019                 return "Videotelephony (F.720, F.721 and F.731 profile 1a)";
02020         case 0x61:
02021                 return "Videoconferenceing (F.702 and F.731 profile 1b)";
02022         case 0x62:
02023                 return "Audiographic conferencing (F.702 and F.731 profile 2a2 etc.)";
02024         case 0x63:
02025         case 0x64:
02026         case 0x65:
02027         case 0x66:
02028         case 0x67:
02029                 return "Reserved for audiovisual service (F.700-series)";
02030         case 0x68:
02031                 return "Multimedia services (F.700-series)";
02032         case 0x6b:
02033         case 0x6c:
02034         case 0x6d:
02035         case 0x6e:
02036         case 0x6f:
02037                 return "Reserved for audiovisual service (F.700-series)";
02038         default:
02039                 return "reserved";
02040         }
02041 }
02042 
02043 L3INT Q931Die_HLComp(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
02044 {
02045         Q931ie_HLComp *pie = (Q931ie_HLComp *)ie;
02046         strstream_printf(ostream,
02047                         "\tHigh-Layer Compat IE [%#02x]:\n"
02048                         "\t\tCoding:                %s\n"
02049                         "\t\tInterpretation:        %s\n"
02050                         "\t\tPresentation:          %s\n"
02051                         "\t\tHL Characteristics:    %s\n",
02052                         pie->IEId, q931_coding_type(pie->CodStand),
02053                         ((pie->Interpret == 0x04) ? "First/only HL characteristic" : "reserved"),
02054                         ((pie->PresMeth  == 0x01) ? "HL protocol profile" : "reserved"),
02055                         q931_hl_characteristics_type(pie->HLCharID));
02056         return Q931E_NO_ERROR;
02057 }
02058 
02059 
02060 /********************************************************************************************************************************
02061  * Keypad Facility IE
02062  ********************************************************************************************************************************/
02063 
02064 L3INT Q931Uie_KeypadFac(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
02065 {
02066         Q931ie_KeypadFac *pie = (Q931ie_KeypadFac*)OBuf;
02067         ie *pIE = &pMsg->KeypadFac;
02068         L3INT Off = 0;
02069         L3INT Octet = 0;
02070         L3INT IESize;
02071         L3INT x;
02072 
02073         *pIE = 0;
02074 
02075         pie->IEId = IBuf[Octet++];
02076         IESize = IBuf[Octet++];
02077 
02078         for (x = 0; x<IESize; x++) {
02079                 pie->KeypadFac[x] = IBuf[Octet + Off] & 0x7f;
02080                 Off++;
02081         }
02082 
02083         Q931IESizeTest(Q931E_KEYPADFAC);
02084         Q931SetIE(*pIE, *OOff);
02085 
02086         *IOff = (*IOff) + Octet + Off;
02087         *OOff = (*OOff) + sizeof(Q931ie_KeypadFac) + x - 1;
02088         pie->Size = (L3UCHAR)(sizeof(Q931ie_KeypadFac) + x - 1);
02089 
02090         return Q931E_NO_ERROR;
02091 }
02092 
02093 L3INT Q931Pie_KeypadFac(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
02094 {
02095         Q931ie_KeypadFac *pIE = (Q931ie_KeypadFac*)IBuf;
02096         L3INT rc = 0;
02097         L3INT Beg = *Octet;
02098         L3INT li;
02099         L3INT DSize;
02100         L3INT x;
02101 
02102         OBuf[(*Octet)++] = Q931ie_KEYPAD_FACILITY;
02103         li = (*Octet)++;
02104 
02105         DSize = pIE->Size - sizeof(Q931ie_KeypadFac) + 1;
02106 
02107         for (x = 0; x< DSize; x++) {
02108                 OBuf[(*Octet)++] = pIE->KeypadFac[x];
02109         }
02110 
02111         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
02112         return rc;
02113 }
02114 
02115 L3INT Q931Die_KeypadFac(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
02116 {
02117         Q931ie_KeypadFac *pie = (Q931ie_KeypadFac *)ie;
02118         strstream_printf(ostream,
02119                         "\tKeypad Facility IE [%#02x]:\n"
02120                         "\t\tValue:     %.*s\n",
02121                         pie->IEId, pie->Size - sizeof(*pie), pie->KeypadFac);
02122         return Q931E_NO_ERROR;
02123 }
02124 
02125 
02126 /********************************************************************************************************************************
02127  * Low-Layer Compat IE
02128  ********************************************************************************************************************************/
02129 
02130 L3INT Q931Uie_LLComp(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
02131 {
02132         Q931ie_LLComp *pie = (Q931ie_LLComp*)OBuf;
02133         ie *pIE = &pMsg->LLComp;
02134         L3INT Off = 0;
02135         L3INT Octet = 0;
02136         L3INT IESize;
02137 
02138         *pIE = 0;
02139 
02140         pie->IEId = IBuf[Octet++];
02141 
02142         /* Octet 2 */
02143         IESize = IBuf[Octet++];
02144 
02145         /* Octet 3 */
02146         pie->CodStand  = (IBuf[Octet + Off] >> 5) & 0x03;
02147         pie->ITransCap =  IBuf[Octet + Off] & 0x1f;
02148         Octet++;
02149 
02150         /* Octet 3a*/
02151         if (IsQ931Ext(IBuf[Octet + Off - 1])) {
02152                 pie->NegotInd = (IBuf[Octet + Off] >> 6) & 0x01;
02153                 Off++;
02154         }
02155 
02156         /* Octet 4 */
02157         pie->TransMode = (IBuf[Octet + Off] >> 5) & 0x03;
02158         pie->InfoRate  =  IBuf[Octet + Off] & 0x1f;
02159 
02160         Octet++;
02161 
02162         /* Octet 4.1 */
02163         if (pie->InfoRate == 0x14) { /* Mutirate */
02164                 pie->RateMul = IBuf[Octet + Off] & 0x7f;
02165                 Off++;
02166         }
02167 
02168         /* Octet 5 - Layer 1 Ident */
02169         if ((IBuf[Octet + Off] & 0x60) == 0x20) { /* Layer 1 Ident ? */
02170                 pie->Layer1Ident = (IBuf[Octet + Off] >> 5) & 0x03;
02171                 pie->UIL1Prot    =  IBuf[Octet + Off] & 0x1f;
02172                 Octet++;
02173 
02174                 /* Octet 5a */
02175                 if (IsQ931Ext(IBuf[Octet + Off - 1])) {
02176                         pie->SyncAsync = (IBuf[Octet + Off] >> 6) & 0x01;
02177                         pie->Negot     = (IBuf[Octet + Off] >> 5) & 0x01;
02178                         pie->UserRate  =  IBuf[Octet + Off] & 0x1f;
02179                         Off++;
02180 
02181                         /* Octet 5b - 2 options */
02182                         if (IsQ931Ext(IBuf[Octet + Off - 1])) {
02183                                 if (pie->UIL1Prot == 0x01) { /* V.110, I.460 and X.30*/
02184                                         pie->InterRate = (IBuf[Octet + Off] >> 5) & 0x03;
02185                                         pie->NIConTx   = (IBuf[Octet + Off] >> 4) & 0x01;
02186                                         pie->NIConRx   = (IBuf[Octet + Off] >> 3) & 0x01;
02187                                         pie->FlowCtlTx = (IBuf[Octet + Off] >> 2) & 0x01;
02188                                         pie->FlowCtlRx = (IBuf[Octet + Off] >> 1) & 0x01;
02189                                         Off++;
02190                                 }
02191                                 else if (pie->UIL1Prot == 0x80) { /* V.120 */
02192                                         pie->HDR        = (IBuf[Octet + Off] >> 6) & 0x01;
02193                                         pie->MultiFrame = (IBuf[Octet + Off] >> 5) & 0x01;
02194                                         pie->ModeL1     = (IBuf[Octet + Off] >> 4) & 0x01;
02195                                         pie->NegotLLI   = (IBuf[Octet + Off] >> 3) & 0x01;
02196                                         pie->Assignor   = (IBuf[Octet + Off] >> 2) & 0x01;
02197                                         pie->InBandNeg  = (IBuf[Octet + Off] >> 1) & 0x01;
02198                                         Off++;
02199                                 }
02200                                 else if (pie->UIL1Prot == 0x07) { /* non standard */
02201                                         Off = Q931ReadExt(&IBuf[Octet + Off], Off);
02202                                         Off++;
02203                                 }
02204                                 else {
02205                                         Q931SetError(trunk,Q931E_LLCOMP, 5,2);
02206                                         return Q931E_LLCOMP;
02207                                 }
02208 
02209                                 /* Octet 5c */
02210                                 if (IsQ931Ext(IBuf[Octet + Off - 1])) {
02211                                         pie->NumStopBits = (IBuf[Octet + Off] >> 5) & 0x03;
02212                                         pie->NumDataBits = (IBuf[Octet + Off] >> 3) & 0x03;
02213                                         pie->Parity      =  IBuf[Octet + Off] & 0x07;
02214                                         Off++;
02215 
02216                                         /* Octet 5d */
02217                                         if (IsQ931Ext(IBuf[Octet + Off - 1])) {
02218                                                 pie->DuplexMode = (IBuf[Octet + Off] >> 6) & 0x01;
02219                                                 pie->ModemType  =  IBuf[Octet + Off] & 0x3f;
02220                                                 Off = Q931ReadExt(&IBuf[Octet + Off], Off);
02221                                                 Off++;
02222                                         }
02223                                 }
02224                         }
02225                 }
02226         }
02227 
02228         /* Octet 6 - Layer 2 Ident */
02229         if ((IBuf[Octet + Off] & 0x60) == 0x40) { /* Layer 1 Ident ? */
02230                 pie->Layer2Ident = (IBuf[Octet + Off] >>5) & 0x03;
02231                 pie->UIL2Prot    =  IBuf[Octet + Off] & 0x1f;
02232                 Octet++;
02233 
02234                 /* Octet 6a */
02235                 if (IsQ931Ext(IBuf[Octet + Off - 1])) {
02236                         if (pie->UIL2Prot == 0x10) { /* 2nd 6a */
02237                                 pie->UsrSpcL2Prot = IBuf[Octet + Off] & 0x7f;
02238                                 Off++;
02239                         }
02240                         else { /* assume 1st 6a */
02241                                 pie->ModeL2  = (IBuf[Octet + Off] >> 5) & 0x03;
02242                                 pie->Q933use =  IBuf[Octet + Off] & 0x03;
02243                                 Off++;
02244                         }
02245                         /* Octet 6b */
02246                         if (IsQ931Ext(IBuf[Octet + Off - 1])) {
02247                                 pie->WindowSize = IBuf[Octet + Off] & 0x7f;
02248                                 Off++;
02249                         }
02250                 }
02251         }
02252 
02253         /* Octet 7 - layer 3 Ident */
02254         if ((IBuf[Octet + Off] & 0x60) == 0x60) { /* Layer 3 Ident ? */
02255                 pie->Layer3Ident = (IBuf[Octet + Off] >> 5) & 0x03;
02256                 pie->UIL3Prot    =  IBuf[Octet + Off] & 0x1f;
02257                 Octet++;
02258 
02259                 /* Octet 7a */
02260                 if (IsQ931Ext(IBuf[Octet + Off - 1])) {
02261                         if (pie->UIL3Prot == 0x0b) {
02262                                 /* Octet 7a + 7b AddL3Info */
02263                                 pie->AddL3Info = ((IBuf[Octet + Off] << 4) & 0xf0)
02264                                                                 | (IBuf[Octet + Off + 1] & 0x0f);
02265                                 Off += 2;
02266                         }
02267                         else {
02268                                 if (pie->UIL3Prot == 0x1f) {
02269                                         pie->ModeL3 = (IBuf[Octet + Off] >> 5) & 0x03;
02270                                         Off++;
02271                                 }
02272                                 else {
02273                                         pie->OptL3Info = IBuf[Octet + Off] & 0x7f;
02274                                         Off++;
02275                                 }
02276 
02277                                 /* Octet 7b*/
02278                                 if (IsQ931Ext(IBuf[Octet + Off - 1])) {
02279                                         pie->DefPackSize = IBuf[Octet + Off] & 0x0f;
02280                                         Off++;
02281 
02282                                         /* Octet 7c */
02283                                         if (IsQ931Ext(IBuf[Octet + Off - 1])) {
02284                                                 pie->PackWinSize= IBuf[Octet + Off] & 0x7f;
02285                                         }
02286                                 }
02287                         }
02288                 }
02289         }
02290 
02291         Q931IESizeTest(Q931E_LLCOMP);
02292         Q931SetIE(*pIE, *OOff);
02293 
02294         *IOff = (*IOff) + Octet + Off;
02295         *OOff = (*OOff) + sizeof(Q931ie_LLComp);
02296         pie->Size = sizeof(Q931ie_LLComp);
02297 
02298         return Q931E_NO_ERROR;
02299 }
02300 
02301 L3INT Q931Pie_LLComp(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
02302 {
02303         Q931ie_LLComp *pIE = (Q931ie_LLComp*)IBuf;
02304         L3INT rc = 0;
02305         L3INT Beg = *Octet;
02306         L3INT li;
02307 
02308         OBuf[(*Octet)++] = Q931ie_LOW_LAYER_COMPATIBILITY;
02309         li = (*Octet)++;
02310 
02311         /* Octet 3 */
02312         OBuf[(*Octet)++] = (pIE->CodStand << 6) | pIE->ITransCap;
02313 
02314         /* Octet 3a */
02315         OBuf[(*Octet)++] = 0x80 | (pIE->NegotInd << 6);
02316 
02317         /* Octet 4 */
02318         OBuf[(*Octet)++] = 0x80 | (pIE->TransMode << 5) | pIE->InfoRate;
02319 
02320         /* Octet 4.1 */
02321         if (pIE->InfoRate == 0x18) {
02322                 OBuf[(*Octet)++] = 0x80 | pIE->RateMul;
02323         }
02324 
02325         /* Octet 5 */
02326         if (pIE->Layer1Ident == 0x01) {
02327                 OBuf[(*Octet)++] = (pIE->Layer1Ident << 5) | pIE->UIL1Prot;
02328 
02329                 /* Octet 5a */
02330                 if ((pIE->ITransCap == 0x08 && (pIE->UIL1Prot == 0x01 || pIE->UIL1Prot == 0x08))
02331                         || (pIE->ITransCap == 0x10 && (pIE->UIL1Prot == 0x02 || pIE->UIL1Prot == 0x03))) {
02332                         OBuf[(*Octet)++] = (pIE->SyncAsync<<6) | (pIE->Negot<<5) | pIE->UserRate;
02333 
02334                         /* Octet 5b*/
02335                         if (pIE->UIL1Prot == 0x01) {
02336                                 OBuf[(*Octet)++] =  (pIE->InterRate << 5)
02337                                                         | (pIE->NIConTx << 4)
02338                                                         | (pIE->NIConTx << 3)
02339                                                         | (pIE->FlowCtlTx << 2)
02340                                                         | (pIE->FlowCtlRx << 1);
02341                         }
02342                         else if (pIE->UIL1Prot == 0x08) {
02343                                 OBuf[(*Octet)++] =  (pIE->HDR << 6)
02344                                                         | (pIE->MultiFrame << 5)
02345                                                         | (pIE->ModeL1 << 4)
02346                                                         | (pIE->NegotLLI << 3)
02347                                                         | (pIE->Assignor << 2)
02348                                                         | (pIE->InBandNeg << 1);
02349                         }
02350                         else {
02351                                 OBuf[(*Octet) - 1] |= 0x80;
02352                         }
02353 
02354                         /* How to detect wherever 5c and 5d is to present is not clear
02355                          * but they have been inculded as 'standard'
02356                          * Octet 5c
02357                          */
02358                         if (pIE->UIL1Prot == 0x01 || pIE->UIL1Prot == 0x08) {
02359                                 OBuf[(*Octet)++] = (pIE->NumStopBits << 5) | (pIE->NumDataBits << 3) | pIE->Parity ;
02360 
02361                                 /* Octet 5d */
02362                                 OBuf[(*Octet)++] = 0x80 | (pIE->DuplexMode << 6) | pIE->ModemType;
02363                         }
02364                 }
02365                 else {
02366                         OBuf[(*Octet) - 1] |= 0x80;
02367                 }
02368         }
02369 
02370         /* Octet 6 */
02371         if (pIE->Layer2Ident == 0x02) {
02372                 OBuf[(*Octet)++] = (pIE->Layer2Ident << 5) | pIE->UIL2Prot;
02373 
02374                 /* Octet 6a*/
02375                 if (pIE->UIL2Prot == 0x02 /* Q.921/I.441 */
02376                 || pIE->UIL2Prot == 0x06 /* X.25 link layer */
02377                 || pIE->UIL2Prot == 0x07 /* X.25 multilink */
02378                 || pIE->UIL2Prot == 0x09 /* HDLC ARM */
02379                 || pIE->UIL2Prot == 0x0a /* HDLC NRM */
02380                 || pIE->UIL2Prot == 0x0b /* HDLC ABM */
02381                 || pIE->UIL2Prot == 0x0d /* X.75 SLP */
02382                 || pIE->UIL2Prot == 0x0e /* Q.922 */
02383                 || pIE->UIL2Prot == 0x11) { /* ISO/ECE 7776 DTE-DCE */
02384                         OBuf[(*Octet)++] = (pIE->ModeL2 << 5) | pIE->Q933use;
02385 
02386                         /* Octet 6b */
02387                         OBuf[(*Octet)++] = 0x80 | pIE->WindowSize;
02388                 }
02389                 else if (pIE->UIL2Prot == 0x10) { /* User Specific */
02390                         OBuf[(*Octet)++] = 0x80 | pIE->UsrSpcL2Prot;
02391                 }
02392                 else {
02393                         OBuf[(*Octet) - 1] |= 0x80;
02394                 }
02395         }
02396 
02397         /* Octet 7 */
02398         if (pIE->Layer3Ident == 0x03) {
02399                 OBuf[(*Octet)++] = (pIE->Layer3Ident << 5) | pIE->UIL3Prot;
02400 
02401                 /* Octet 7a - 3 different ones */
02402                 if (pIE->UIL3Prot == 0x10) {
02403                         OBuf[(*Octet++)] = 0x80 | pIE->OptL3Info;
02404                 }
02405                 else if (pIE->UIL3Prot == 0x06
02406                         ||  pIE->UIL3Prot == 0x07
02407                         ||  pIE->UIL3Prot == 0x08) {
02408                         OBuf[(*Octet)++] = pIE->ModeL3 << 5;
02409 
02410                         /* Octet 7b note 7 */
02411                         OBuf[(*Octet)++] = pIE->DefPackSize;
02412 
02413                         /* Octet 7c note 7 */
02414                         OBuf[(*Octet)++] = 0x80 | pIE->PackWinSize;
02415                 }
02416                 else if (pIE->UIL3Prot == 0x0b) {
02417                         OBuf[(*Octet)++] = (pIE->AddL3Info >> 4) & 0x0f;
02418                         OBuf[(*Octet)++] = 0x80 | (pIE->AddL3Info & 0x0f);
02419                 }
02420                 else {
02421                         OBuf[(*Octet) - 1] |= 0x80;
02422                 }
02423         }
02424         else {
02425                 Q931SetError(trunk,Q931E_LLCOMP, 7,0);
02426                 rc = Q931E_LLCOMP;
02427         }
02428 
02429         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
02430         return rc;
02431 }
02432 
02436 L3INT Q931Die_LLComp(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
02437 {
02438         Q931ie_LLComp *pie = (Q931ie_LLComp *)ie;
02439         strstream_printf(ostream,
02440                         "\tLow-Layer Compat IE [%#02x]:\n"
02441                         "\t\tCoding:        %s\n",
02442                         pie->IEId, q931_coding_type(pie->CodStand));
02443         return Q931E_NO_ERROR;
02444 }
02445 
02446 
02447 /********************************************************************************************************************************
02448  * Network Facility IE
02449  ********************************************************************************************************************************/
02450 
02451 L3INT Q931Uie_NetFac(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
02452 {
02453         Q931ie_NetFac *pie = (Q931ie_NetFac*)OBuf;
02454         ie *pIE = &pMsg->NetFac;
02455         L3INT Off = 0;
02456         L3INT Octet = 0;
02457         L3INT x = 0;
02458         L3INT IESize;
02459 
02460         *pIE = 0;
02461 
02462         pie->IEId = IBuf[Octet++];
02463 
02464         /* Octet 2 */
02465         IESize = IBuf[Octet++];
02466 
02467         pie->LenNetID = IBuf[Octet + Off]; /* full octet is used */
02468         Octet++;
02469 
02470         if (pie->LenNetID > 0) {
02471                 /* Octet 3.1 */
02472                 pie->TypeNetID = (IBuf[Octet + Off] >> 4) & 0x0f;
02473                 pie->NetIDPlan =  IBuf[Octet + Off] & 0x0f;
02474                 Off = Q931ReadExt(&IBuf[Octet], Off);
02475                 Off++;
02476 
02477                 /* Octet 3.2*/
02478                 for (x = 0; x < pie->LenNetID; x++) {
02479                         pie->NetID[x] = IBuf[Octet + Off] & 0x7f;
02480                         Off++;
02481                 }
02482         }
02483 
02484         /* Octet 4*/
02485         pie->NetFac = IBuf[Octet + Off]; /* Full Octet is used */
02486         Octet++;
02487 
02488         Q931IESizeTest(Q931E_NETFAC);
02489         Q931SetIE(*pIE, *OOff);
02490 
02491         *IOff = (*IOff) + Octet + Off;
02492         *OOff = (*OOff) + sizeof(Q931ie_NetFac) + x - 1;
02493         pie->Size = (L3UCHAR)(sizeof(Q931ie_NetFac) + x - 1);
02494 
02495         return Q931E_NO_ERROR;
02496 }
02497 
02498 L3INT Q931Pie_NetFac(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
02499 {
02500         Q931ie_NetFac *pIE = (Q931ie_NetFac*)IBuf;
02501         L3INT rc = Q931E_NO_ERROR;
02502         L3INT Beg = *Octet;
02503         L3INT li;
02504         L3INT x;
02505 
02506         OBuf[(*Octet)++] = Q931ie_NETWORK_SPECIFIC_FACILITIES;
02507         li = (*Octet)++;
02508 
02509         /* Octet 3 */
02510         OBuf[(*Octet)++] = pIE->LenNetID;
02511 
02512         if (pIE->LenNetID > 0) {
02513                 /* Octet 3.1 */
02514                 OBuf[(*Octet)++] = 0x80 | (pIE->TypeNetID << 4) | pIE->NetIDPlan;
02515 
02516                 /* Octet 3.2 */
02517                 for (x = 0; x <pIE->LenNetID; x++) {
02518                         OBuf[(*Octet)++] = pIE->NetID[x];
02519                 }
02520         }
02521 
02522         /* Octet 4 */
02523         OBuf[(*Octet)++] = pIE->NetFac;
02524 
02525         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
02526         return rc;
02527 }
02528 
02529 L3INT Q931Die_NetFac(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
02530 {
02531         Q931ie_NetFac *pie = (Q931ie_NetFac *)ie;
02532         strstream_printf(ostream,
02533                         "\tNetwork-specific Facilities IE [%#02x]:\n"
02534                         "\t\tType of Network ID:    %s\n"
02535                         "\t\tNetwork ID plan:       %s\n"
02536                         "\t\tNetwork ID:            %.*s\n"
02537                         "\t\tFacilities:            [ ",
02538                         pie->IEId, q931_network_id_type(pie->TypeNetID), q931_network_id_plan(pie->NetIDPlan),
02539                         pie->LenNetID, pie->NetID);
02540         strstream_printhex(ostream, (char *)&pie->NetFac, pie->Size - (sizeof(*pie) + pie->LenNetID));
02541         strstream_puts(ostream, " ]\n");
02542         return Q931E_NO_ERROR;
02543 }
02544 
02545 
02546 /********************************************************************************************************************************
02547  * Notify Indication IE
02548  ********************************************************************************************************************************/
02549 
02550 L3INT Q931Uie_NotifInd(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
02551 {
02552         Q931ie_NotifInd *pie = (Q931ie_NotifInd*)OBuf;
02553         ie *pIE = &pMsg->NotifInd;
02554         L3INT Off = 0;
02555         L3INT Octet = 0;
02556         L3INT IESize;
02557 
02558         *pIE = 0;
02559 
02560         pie->IEId = IBuf[Octet++];
02561 
02562         /* Octet 2*/
02563         IESize = IBuf[Octet++];
02564 
02565         /* Octet 3 */
02566         pie->Notification = IBuf[Octet + Off] & 0x7f;
02567 
02568         Off = Q931ReadExt(&IBuf[Octet], Off);
02569         Octet++;
02570 
02571         Q931IESizeTest(Q931E_NOTIFIND);
02572         Q931SetIE(*pIE, *OOff);
02573 
02574         *IOff = (*IOff) + Octet + Off;
02575         *OOff = (*OOff) + sizeof(Q931ie_NotifInd);
02576         pie->Size = sizeof(Q931ie_NotifInd);
02577 
02578         return Q931E_NO_ERROR;
02579 }
02580 
02581 L3INT Q931Pie_NotifInd(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
02582 {
02583         Q931ie_NotifInd *pIE = (Q931ie_NotifInd*)IBuf;
02584         L3INT rc = Q931E_NO_ERROR;
02585         L3INT Beg = *Octet;
02586         L3INT li;
02587 
02588         OBuf[(*Octet)++] = Q931ie_NOTIFICATION_INDICATOR;
02589         li = (*Octet)++;
02590 
02591         /* Octet 3 */
02592         OBuf[(*Octet)++] = pIE->Notification;
02593 
02594         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
02595         return rc;
02596 }
02597 
02598 
02599 static const char *q931_notification_type(const unsigned char type)
02600 {
02601         switch (type) {
02602         case 0x00:
02603                 return "User suspended";
02604         case 0x01:
02605                 return "User resumed";
02606         case 0x02:
02607                 return "Bearer service change";
02608         default:
02609                 return "reserved";
02610         }
02611 }
02612 
02613 L3INT Q931Die_NotifInd(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
02614 {
02615         Q931ie_NotifInd *pie = (Q931ie_NotifInd *)ie;
02616         strstream_printf(ostream,
02617                         "\tNotification Indicator IE [%#02x]:\n"
02618                         "\t\tDescription:  %s\n",
02619                         pie->IEId, q931_notification_type(pie->Notification));
02620         return Q931E_NO_ERROR;
02621 }
02622 
02623 
02624 /********************************************************************************************************************************
02625  * Progress Indication IE
02626  ********************************************************************************************************************************/
02627 
02628 L3INT Q931Uie_ProgInd(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
02629 {
02630         Q931ie_ProgInd *pie = (Q931ie_ProgInd*)OBuf;
02631         ie *pIE = &pMsg->ProgInd;
02632         L3INT Off = 0;
02633         L3INT Octet = 0;
02634         L3INT IESize;
02635 
02636         *pIE = 0;
02637 
02638         pie->IEId = IBuf[Octet++];
02639 
02640         /* Octet 2 */
02641         IESize = IBuf[Octet++];
02642 
02643         /* Octet 3 */
02644         pie->CodStand = (IBuf[Octet + Off] >> 5) & 0x03;
02645         pie->Location =  IBuf[Octet + Off] & 0x0f;
02646 
02647         Off = Q931ReadExt(&IBuf[Octet], Off);
02648         Octet++;
02649 
02650         /* Octet 4 */
02651         pie->ProgDesc = IBuf[Octet + Off] & 0x7f;
02652         Off = Q931ReadExt(&IBuf[Octet], Off);
02653         Octet++;
02654 
02655         Q931IESizeTest(Q931E_PROGIND);
02656         Q931SetIE(*pIE, *OOff);
02657 
02658         *IOff = (*IOff) + Octet + Off;
02659         *OOff = (*OOff) + sizeof(Q931ie_ProgInd);
02660         pie->Size = sizeof(Q931ie_ProgInd);
02661 
02662         return Q931E_NO_ERROR;
02663 }
02664 
02665 L3INT Q931Pie_ProgInd(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
02666 {
02667         Q931ie_ProgInd *pIE = (Q931ie_ProgInd*)IBuf;
02668         L3INT rc = Q931E_NO_ERROR;
02669         L3INT Beg = *Octet;
02670         L3INT li;
02671 
02672         OBuf[(*Octet)++] = Q931ie_PROGRESS_INDICATOR;
02673         li = (*Octet)++;
02674 
02675         /* Octet 3 */
02676         OBuf[(*Octet)++] = 0x80 | (pIE->CodStand << 5) | pIE->Location;
02677 
02678         /* Octet 4 */
02679         OBuf[(*Octet)++] = 0x80 | pIE->ProgDesc;
02680 
02681         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
02682         return rc;
02683 }
02684 
02685 L3INT Q931Die_ProgInd(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
02686 {
02687         Q931ie_ProgInd *pie = (Q931ie_ProgInd *)ie;
02688         strstream_printf(ostream,
02689                         "\tProgress Indicator IE [%#02x]:\n"
02690                         "\t\tCoding:          %s\n"
02691                         "\t\tLocation:        %s\n"
02692                         "\t\tProgress Desc.:  %s\n",
02693                         pie->IEId, q931_coding_type(pie->CodStand), q931_location_type(pie->Location),
02694                         q931_progdesc_type(pie->ProgDesc));
02695         return Q931E_NO_ERROR;
02696 }
02697 
02698 
02699 /********************************************************************************************************************************
02700  * Repeat Indication IE
02701  ********************************************************************************************************************************/
02702 
02703 L3INT Q931Uie_RepeatInd(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
02704 {
02705         Q931ie_RepeatInd *pie = (Q931ie_RepeatInd*)OBuf;
02706         ie *pIE = &pMsg->RepeatInd;
02707         L3INT Off = 0;
02708         L3INT Octet = 0;
02709 
02710         *pIE = 0;
02711 
02712         pie->IEId      = IBuf[Octet] & 0xf0;
02713         pie->RepeatInd = IBuf[Octet] & 0x0f;
02714         Octet ++;
02715 
02716         Q931SetIE(*pIE, *OOff);
02717 
02718         *IOff = (*IOff) + Octet + Off;
02719         *OOff = (*OOff) + sizeof(Q931ie_RepeatInd);
02720         pie->Size = sizeof(Q931ie_RepeatInd);
02721 
02722         return Q931E_NO_ERROR;
02723 }
02724 
02725 L3INT Q931Pie_RepeatInd(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
02726 {
02727         Q931ie_RepeatInd *pIE = (Q931ie_RepeatInd*)IBuf;
02728         L3INT rc = 0;
02729         /* L3INT Beg = *Octet; */
02730 
02731         OBuf[(*Octet)++] = Q931ie_REPEAT_INDICATOR | pIE->RepeatInd;
02732 
02733         return rc;
02734 }
02735 
02736 L3INT Q931Die_RepeatInd(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
02737 {
02738         Q931ie_RepeatInd *pie = (Q931ie_RepeatInd *)ie;
02739         strstream_printf(ostream,
02740                         "\tRepeat Indicator IE [%#02x]:\n",
02741                         pie->IEId);
02742         return Q931E_NO_ERROR;
02743 }
02744 
02745 
02746 /********************************************************************************************************************************
02747  * Rev-Charge Indication IE
02748  ********************************************************************************************************************************/
02749 
02750 L3INT Q931Uie_RevChargeInd(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
02751 {
02752         ie iE;
02753         /* ie *pIE = &pMsg->RevChargeInd; */
02754         Q931SetIE(iE, *OOff);
02755 
02756         return iE;
02757 }
02758 
02759 L3INT Q931Pie_RevChargeInd(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
02760 {
02761         L3BOOL RetCode = L3FALSE;
02762 
02763         NoWarning(OBuf);
02764         NoWarning(IBuf);
02765 
02766         return RetCode;
02767 }
02768 
02769 L3INT Q931Die_RevChargeInd(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
02770 {
02771         strstream_printf(ostream,
02772                         "\tRevCharge Indicator IE [%#02x]:\n",
02773                         ie->IEId);
02774         return Q931E_NO_ERROR;
02775 }
02776 
02777 
02778 /********************************************************************************************************************************
02779  * Restart Indication IE
02780  ********************************************************************************************************************************/
02781 
02782 L3INT Q931Uie_RestartInd(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
02783 {
02784         Q931ie_RestartInd *pie = (Q931ie_RestartInd*)OBuf;
02785         ie *pIE = &pMsg->RestartInd;
02786         L3INT Off = 0;
02787         L3INT Octet = 0;
02788         L3INT IESize;
02789 
02790         *pIE = 0;
02791 
02792         pie->IEId = IBuf[Octet++];
02793 
02794         /* Octet 2 */
02795         IESize = IBuf[Octet++];
02796 
02797         /* Octet 3 */
02798         pie->Class = IBuf[Octet + Off] & 0x07;
02799         pie->Spare = IBuf[Octet + Off] & 0x70;
02800 
02801         Off = Q931ReadExt(&IBuf[Octet], Off);
02802         Octet++;
02803 
02804         Q931IESizeTest(Q931E_RESTARTIND);
02805         Q931SetIE(*pIE, *OOff);
02806 
02807         *IOff = (*IOff) + Octet + Off;
02808         *OOff = (*OOff) + sizeof(Q931ie_RestartInd);
02809         pie->Size = sizeof(Q931ie_RestartInd);
02810 
02811 
02812         return Q931E_NO_ERROR;
02813 }
02814 
02815 L3INT Q931Pie_RestartInd(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
02816 {
02817         Q931ie_RestartInd *pIE = (Q931ie_RestartInd*)IBuf;
02818         L3INT rc = Q931E_NO_ERROR;
02819         L3INT Beg = *Octet;
02820         L3INT li;
02821 
02822         OBuf[(*Octet)++] = Q931ie_RESTART_INDICATOR;
02823         li = (*Octet)++;
02824 
02825         /* Octet 3*/
02826         OBuf[(*Octet)++] = 0x80 | pIE->Class;
02827 
02828         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
02829         return rc;
02830 }
02831 
02832 L3INT Q931Die_RestartInd(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
02833 {
02834         Q931ie_RestartInd *pie = (Q931ie_RestartInd *)ie;
02835         const char *rclass = NULL;
02836 
02837         switch (pie->Class) {
02838         case 0x00:
02839                 rclass = "Channel";
02840                 break;
02841         case 0x06:
02842                 rclass = "Interface";
02843                 break;
02844         case 0x07:
02845                 rclass = "All interfaces";
02846                 break;
02847         default:
02848                 rclass = "Invalid/unknown";
02849         }
02850 
02851         strstream_printf(ostream,
02852                         "\tRestart Indicator IE [%#02x]:\n"
02853                         "\t\tClass: %s\n",
02854                         pie->IEId, rclass);
02855         return Q931E_NO_ERROR;
02856 }
02857 
02858 
02859 /********************************************************************************************************************************
02860  * Segment IE
02861  ********************************************************************************************************************************/
02862 
02863 L3INT Q931Uie_Segment(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
02864 {
02865         Q931ie_Segment *pie = (Q931ie_Segment*)OBuf;
02866         ie *pIE = &pMsg->Segment;
02867         L3INT Off = 0;
02868         L3INT Octet = 0;
02869         L3INT IESize;
02870 
02871         *pIE = 0;
02872 
02873         pie->IEId = IBuf[Octet++];
02874         Octet++;
02875 
02876         /* Octet 2*/
02877         IESize = IBuf[Octet++];
02878 
02879         /* Octet 3 */
02880         pie->FSI       = (IBuf[Octet + Off] & 0x80) >> 7;
02881         pie->NumSegRem =  IBuf[Octet + Off] & 0x7f;
02882         Octet++;
02883 
02884         /* Octet 4 */
02885         pie->SegType = IBuf[Octet + Off] & 0x7f;
02886         Octet++;
02887 
02888         Q931IESizeTest(Q931E_SEGMENT);
02889         Q931SetIE(*pIE, *OOff);
02890 
02891         *IOff = (*IOff) + Octet + Off;
02892         *OOff = (*OOff) + sizeof(Q931ie_Segment);
02893         pie->Size = sizeof(Q931ie_Segment);
02894 
02895         return Q931E_NO_ERROR;
02896 }
02897 
02898 L3INT Q931Pie_Segment(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
02899 {
02900         Q931ie_Segment *pIE = (Q931ie_Segment*)IBuf;
02901         L3INT rc = Q931E_NO_ERROR;
02902         L3INT Beg = *Octet;
02903         L3INT li;
02904 
02905         OBuf[(*Octet)++] = Q931ie_SEGMENTED_MESSAGE;
02906         li = (*Octet)++;
02907 
02908         /* Octet 3 */
02909         OBuf[(*Octet)++] = (pIE->FSI << 7) | pIE->NumSegRem;
02910 
02911         /* Octet 4 */
02912         OBuf[(*Octet)++] = pIE->SegType;
02913 
02914         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
02915         return rc;
02916 }
02917 
02918 L3INT Q931Die_Segment(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
02919 {
02920         Q931ie_Segment *pie = (Q931ie_Segment *)ie;
02921         strstream_printf(ostream,
02922                         "\tSegment IE [%#02x]:\n"
02923                         "\t\tFirst segment:  %s\n"
02924                         "\t\tRemaining:      %d\n"
02925                         "\t\tType:           %#02x (%s)\n",
02926                         pie->IEId, pie->FSI ? "Yes" : "No", pie->NumSegRem,
02927                         pie->SegType, "-N/A-");
02928         return Q931E_NO_ERROR;
02929 }
02930 
02931 
02932 /********************************************************************************************************************************
02933  * Sending Complete IE
02934  ********************************************************************************************************************************/
02935 
02947 L3INT Q931Uie_SendComplete(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
02948 {
02949         Q931ie_SendComplete *pie = (Q931ie_SendComplete*)OBuf;
02950         ie *pIE = &pMsg->SendComplete;
02951         L3INT Off = 0;
02952         L3INT Octet = 0;
02953 
02954         *pIE = 0;
02955         Octet++;
02956 
02957         Q931SetIE(*pIE, *OOff);
02958 
02959         *IOff = (*IOff) + Octet + Off;
02960         *OOff = (*OOff) + sizeof(Q931ie_SendComplete);
02961         pie->Size = sizeof(Q931ie_SendComplete);
02962 
02963         return Q931E_NO_ERROR;
02964 }
02965 
02975 L3INT Q931Pie_SendComplete(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
02976 {
02977         /* Q931ie_SendComplete * pIE = (Q931ie_SendComplete*)IBuf; */
02978         /* L3INT Beg = *Octet; */
02979 
02980         OBuf[(*Octet)++] = 0x80 | (L3UCHAR)Q931ie_SENDING_COMPLETE;
02981 
02982         return Q931E_NO_ERROR;
02983 }
02984 
02992 L3INT Q931Die_SendComplete(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
02993 {
02994         strstream_printf(ostream,
02995                 "\tSending Complete IE [%#02x]\n",
02996                 ie->IEId);
02997         return Q931E_NO_ERROR;
02998 }
02999 
03000 
03001 /********************************************************************************************************************************
03002  * Signal IE
03003  ********************************************************************************************************************************/
03004 
03005 L3INT Q931Uie_Signal(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
03006 {
03007         Q931ie_Signal *pie = (Q931ie_Signal*)OBuf;
03008         ie *pIE = &pMsg->Signal;
03009         L3INT Off = 0;
03010         L3INT Octet = 0;
03011         L3INT IESize;
03012 
03013         *pIE = 0;
03014 
03015         pie->IEId = IBuf[Octet++];
03016 
03017         /* Octet 2 */
03018         IESize = IBuf[Octet++];
03019 
03020         /* Octet 3 */
03021         pie->Signal = IBuf[Octet + Off];
03022         Octet++;
03023 
03024         Q931IESizeTest(Q931E_SIGNAL);
03025         Q931SetIE(*pIE, *OOff);
03026 
03027         *IOff = (*IOff) + Octet + Off;
03028         *OOff = (*OOff) + sizeof(Q931ie_Signal);
03029         pie->Size = sizeof(Q931ie_Signal);
03030 
03031         return Q931E_NO_ERROR;
03032 }
03033 
03034 L3INT Q931Pie_Signal(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
03035 {
03036         Q931ie_Signal *pIE = (Q931ie_Signal*)IBuf;
03037         L3INT rc = Q931E_NO_ERROR;
03038         L3INT Beg = *Octet;
03039         L3INT li;
03040 
03041         OBuf[(*Octet)++] = Q931ie_SIGNAL;
03042         li = (*Octet)++;
03043 
03044         /* Octet 3 */
03045         OBuf[(*Octet)++] = pIE->Signal;
03046 
03047         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
03048         return rc;
03049 }
03050 
03051 L3INT Q931Die_Signal(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
03052 {
03053         Q931ie_Signal *pie = (Q931ie_Signal *)ie;
03054         strstream_printf(ostream,
03055                         "\tSignal IE [%#02x]:\n"
03056                         "\t\tSignal:    %#02x (%s)\n",
03057                         pie->IEId, pie->Signal, q931_signal_desc(pie->Signal));
03058         return Q931E_NO_ERROR;
03059 }
03060 
03061 
03062 /********************************************************************************************************************************
03063  * Trans-Net Selector IE
03064  ********************************************************************************************************************************/
03065 
03066 L3INT Q931Uie_TransNetSel(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
03067 {
03068         Q931ie_TransNetSel *pie = (Q931ie_TransNetSel*)OBuf;
03069         ie *pIE = &pMsg->TransNetSel;
03070         L3INT Off = 0;
03071         L3INT Octet = 0;
03072         L3INT x = 0;
03073         L3INT l;
03074 
03075         *pIE = 0;
03076 
03077         pie->IEId = IBuf[Octet++];
03078 
03079         /* Octet 2 */
03080         l = IBuf[Octet++] - 3;
03081 
03082         /* Octet 3 */
03083         pie->Type = (IBuf[Octet + Off] >> 4) & 0x07;
03084 
03085         Off = Q931ReadExt(&IBuf[Octet], Off);
03086         Octet++;
03087 
03088         for (x = 0; x < l; x++) {
03089                 pie->NetID[x] = IBuf[Octet + Off] & 0x7f;
03090                 Off++;
03091         }
03092 
03093         Q931SetIE(*pIE, *OOff);
03094 
03095         *IOff = (*IOff) + Octet + Off;
03096         *OOff = (*OOff) + sizeof(Q931ie_TransNetSel) + x - 1;
03097         pie->Size = (L3UCHAR)(sizeof(Q931ie_TransNetSel) + x - 1);
03098 
03099         return Q931E_NO_ERROR;
03100 }
03101 
03102 L3INT Q931Pie_TransNetSel(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
03103 {
03104         Q931ie_TransNetSel *pIE = (Q931ie_TransNetSel*)IBuf;
03105         L3INT rc = Q931E_NO_ERROR;
03106         L3INT Beg = *Octet;
03107         L3INT li;
03108         L3INT x;
03109         L3INT l;
03110 
03111         OBuf[(*Octet)++] = Q931ie_TRANSIT_NETWORK_SELECTION;
03112         li = (*Octet)++;
03113 
03114         /* Octet 3 */
03115         OBuf[(*Octet)++] = 0x80 | (pIE->Type << 4) | pIE->NetIDPlan;
03116 
03117         /* Octet 4 */
03118         l = pIE->Size - sizeof(Q931ie_TransNetSel) + 1;
03119         for (x = 0; x < l; x++) {
03120                 OBuf[(*Octet)++] = pIE->NetID[x];
03121         }
03122 
03123         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
03124         return rc;
03125 }
03126 
03127 L3INT Q931Die_TransNetSel(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
03128 {
03129         Q931ie_TransNetSel *pie = (Q931ie_TransNetSel *)ie;
03130         strstream_printf(ostream,
03131                         "\tTransit Network Selection IE [%#02x]:\n"
03132                         "\t\tType of Network ID:    %s\n"
03133                         "\t\tNetwork ID plan:       %s\n"
03134                         "\t\tNetwork ID:            %.*s\n",
03135                         pie->IEId, q931_network_id_type(pie->Type), q931_network_id_plan(pie->NetIDPlan),
03136                         pie->Size - sizeof(*pie), pie->NetID);
03137         return Q931E_NO_ERROR;
03138 }
03139 
03140 
03141 /********************************************************************************************************************************
03142  * User-User IE
03143  ********************************************************************************************************************************/
03144 
03145 L3INT Q931Uie_UserUser(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
03146 {
03147         Q931ie_UserUser *pie = (Q931ie_UserUser*)OBuf;
03148         ie *pIE = &pMsg->UserUser;
03149         L3INT Octet = 0;
03150         L3INT Off = 0;
03151         L3INT l;
03152 
03153         *pIE = 0;
03154 
03155         pie->IEId = IBuf[Octet++];
03156 
03157         /* Octet 2 */
03158         l = IBuf[Octet++] - 1;
03159 
03160         /* Octet 3 */
03161         pie->ProtDisc = IBuf[Octet++];
03162 
03163         for (Off = 0; Off < l; Off++) {
03164                 pie->User[Off] = IBuf[Octet + Off];
03165         }
03166 
03167         Q931SetIE(*pIE, *OOff);
03168 
03169         *IOff = (*IOff) + Octet + Off;
03170         *OOff = (*OOff) + sizeof(Q931ie_UserUser) + Off - 1;
03171         pie->Size = (L3UCHAR)(sizeof(Q931ie_UserUser) + Off - 1);
03172 
03173         return Q931E_NO_ERROR;
03174 }
03175 
03176 L3INT Q931Pie_UserUser(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
03177 {
03178         Q931ie_UserUser *pIE = (Q931ie_UserUser*)IBuf;
03179         L3INT rc = Q931E_NO_ERROR;
03180         L3INT Beg = *Octet;
03181         L3INT li;
03182         L3INT x;
03183         L3INT l;
03184 
03185         OBuf[(*Octet)++] = Q931ie_USER_USER;
03186         li = (*Octet)++;
03187 
03188         /* Octet 3 */
03189         OBuf[(*Octet)++] = pIE->ProtDisc;
03190 
03191         /* Octet 4 */
03192         l = pIE->Size - sizeof(Q931ie_UserUser) + 1;
03193         for (x = 0; x < l; x++) {
03194                 OBuf[(*Octet)++] = pIE->User[x];
03195         }
03196 
03197         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
03198         return rc;
03199 }
03200 
03201 L3INT Q931Die_UserUser(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
03202 {
03203         Q931ie_UserUser *pie = (Q931ie_UserUser *)ie;
03204         strstream_printf(ostream,
03205                         "\tUser-User IE [%#02x]:\n",
03206                         pie->IEId);
03207 
03208         strstream_puts(ostream, "\t\tValue:    [ ");
03209         strstream_printhex(ostream, (char *)pie->User, pie->Size - sizeof(*pie));
03210         strstream_puts(ostream, " ]\n");
03211         return Q931E_NO_ERROR;
03212 }
03213 
03214 
03215 /********************************************************************************************************************************
03216  * Generic Digits IE
03217  ********************************************************************************************************************************/
03218 
03219 L3INT Q931Uie_GenericDigits(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
03220 {
03221         Q931ie_GenericDigits *pie = (Q931ie_GenericDigits*)OBuf;
03222         ie *pIE = &pMsg->GenericDigits;
03223         L3INT Off = 0;
03224         L3INT Octet = 0;
03225         L3INT x;
03226         L3INT IESize;
03227 
03228         *pIE = 0;
03229 
03230         /* Octet 1 */
03231         pie->IEId = IBuf[Octet++];
03232 
03233         /* Octet 2 */
03234         IESize = IBuf[Octet++];
03235 
03236         /* Octet 3 */
03237         pie->Type     = (IBuf[Octet]) & 0x1F;
03238         pie->Encoding = (IBuf[Octet] >> 5) & 0x07;
03239         Octet++;
03240 
03241         /* Octet 4*/
03242         if (pie->Encoding == 0) { /* BCD Even */
03243                 x = 0;
03244                 do {
03245                         pie->Digit[x++] =  IBuf[Octet + Off] & 0x0f;
03246                         pie->Digit[x++] = (IBuf[Octet + Off] >> 4) & 0x0f;
03247                         Off++;
03248                 } while (Q931MoreIE());
03249         } else if (pie->Encoding == 1) { /* BCD Odd */
03250                 x = 0;
03251                 do {
03252                         pie->Digit[x++] = IBuf[Octet + Off] & 0x0f;
03253                         if (Q931MoreIE()) {
03254                                 pie->Digit[x] = (IBuf[Octet + Off] >> 4) & 0x0f;
03255                         }
03256                         x++;
03257                         Off++;
03258                 } while (Q931MoreIE());
03259         } else if (pie->Encoding == 2) { /* IA5 */
03260                 x = 0;
03261                 do {
03262                         pie->Digit[x++] = IBuf[Octet + Off] & 0x7f;
03263                         Off++;
03264                 } while (Q931MoreIE());
03265         } else {
03266                 /* Binary encoding type unkown */
03267                 Q931SetError(trunk, Q931E_GENERIC_DIGITS, Octet, Off);
03268                 return Q931E_GENERIC_DIGITS;
03269         }
03270 
03271         Q931IESizeTest(Q931E_GENERIC_DIGITS);
03272         Q931SetIE(*pIE, *OOff);
03273 
03274         *IOff = (*IOff) + Octet + Off;
03275         *OOff = (*OOff) + sizeof(Q931ie_CallingSub) + x - 1;
03276         pie->Size = (L3UCHAR)(sizeof(Q931ie_CallingSub) + x - 1);
03277 
03278         return Q931E_NO_ERROR;
03279 }
03280 
03281 L3INT Q931Pie_GenericDigits(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
03282 {
03283         OBuf[(*Octet)++] = (Q931ie_GENERIC_DIGITS & 0xFF);
03284         OBuf[(*Octet)++] = 0;
03285 
03286         return Q931E_NO_ERROR;
03287 }
03288 
03289 L3INT Q931Die_GenericDigits(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
03290 {
03291         Q931ie_GenericDigits *pie = (Q931ie_GenericDigits *)ie;
03292         strstream_printf(ostream,
03293                         "\tGeneric Digits IE [%#02x]:\n",
03294                         pie->IEId);
03295         return Q931E_NO_ERROR;
03296 }
03297 
03298 
03299 /********************************************************************************************************************************
03300  * Change Status IE
03301  ********************************************************************************************************************************/
03302 
03303 L3INT Q931Uie_ChangeStatus(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
03304 {
03305         Q931ie_ChangeStatus *pie = (Q931ie_ChangeStatus*)OBuf;
03306         ie *pIE = &pMsg->ChangeStatus;
03307         L3INT Off = 0;
03308         L3INT Octet = 0;
03309         L3INT IESize;
03310 
03311         *pIE = 0;
03312 
03313         pie->IEId = IBuf[Octet++];
03314 
03315         /* Octet 2 */
03316         IESize = IBuf[Octet++];
03317 
03318         /* Octet 3 */
03319         pie->Preference = (IBuf[Octet + Off] >> 6) & 0x01;
03320         pie->Spare      =  IBuf[Octet + Off] & 0x38;
03321         pie->NewStatus  =  IBuf[Octet + Off] & 0x07;
03322         Octet++;
03323 
03324         Q931SetIE(*pIE, *OOff);
03325 
03326         *IOff = (*IOff) + Octet + Off;
03327         *OOff = (*OOff) + sizeof(Q931ie_ChangeStatus);
03328         pie->Size = sizeof(Q931ie_ChangeStatus);
03329 
03330         return Q931E_NO_ERROR;
03331 }
03332 
03333 L3INT Q931Pie_ChangeStatus(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
03334 {
03335         Q931ie_ChangeStatus *pIE = (Q931ie_ChangeStatus*)IBuf;
03336         L3INT rc = Q931E_NO_ERROR;
03337         L3INT Beg = *Octet;
03338         L3INT li;
03339 
03340         OBuf[(*Octet)++] = Q931ie_CHANGE_STATUS;
03341         li = (*Octet)++;
03342 
03343         /* Octet 3 */
03344         OBuf[(*Octet)++] = 0x80 | pIE->NewStatus | ((pIE->Preference & 0x01) << 6);
03345 
03346         OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2;
03347         return rc;
03348 }
03349 
03350 L3INT Q931Die_ChangeStatus(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
03351 {
03352         Q931ie_ChangeStatus *pie = (Q931ie_ChangeStatus *)ie;
03353         strstream_printf(ostream,
03354                         "\tChange Status IE [%#02x]:\n"
03355                         "\t\tNew Status: %#02x\n"
03356                         "\t\tPreference: %s\n",
03357                         pie->IEId, pie->NewStatus, pie->Preference ? "yes" : "no");
03358         return Q931E_NO_ERROR;
03359 }
03360 
03361 
03362 /********************************************************************************************************************************
03363  * Generic IE handling
03364  ********************************************************************************************************************************/
03365 
03366 L3INT Q931Uie_Generic(Q931_TrunkInfo_t *trunk, Q931mes_Generic *pMsg, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *IOff, L3INT *OOff)
03367 {
03368         L3INT Octet = 0;
03369         L3UCHAR id = 0;
03370 
03371         /* id */
03372         id = IBuf[Octet++];
03373 
03374         /* Length */
03375         if (!(id & 0x80)) {
03376                 Octet += IBuf[Octet];
03377                 Octet++;
03378 
03379                 Q931Log(trunk, Q931_LOG_DEBUG, "Discarding IE %#02x with length %d\n", id, Octet - 2);
03380         } else {
03381                 Q931Log(trunk, Q931_LOG_DEBUG, "Discarding single Octet IE %#02x\n", id);
03382         }
03383 
03384         *IOff += Octet;
03385         return Q931E_NO_ERROR;
03386 }
03387 
03388 L3INT Q931Pie_Generic(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
03389 {
03390         /* do nothing */
03391         return Q931E_NO_ERROR;
03392 }
03393 
03394 L3INT Q931Die_Generic(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
03395 {
03396         strstream_printf(ostream, "\tUnhandled IE [%#02x]\n", ie->IEId);
03397         return Q931E_NO_ERROR;
03398 }