libisdn
|
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 }