1 /*****************************************************************************
2 
3   FileName:	DMSmes.c
4 
5   Contents:	Pack/Unpack functions. These functions will unpack a DMS-100 ISDN
6 		message from the bit packed original format into structs
7 		that contains variables sized by the user. It will also pack
8 		the struct back into a Q.931 message as required.
9 
10 		See national.h for description.
11 
12   License/Copyright:
13 
14   Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved.
15   email:janvb@caselaboratories.com
16 
17   Copyright (c) 2007, Michael Jerris. All rights reserved.
18   email:mike@jerris.com
19 
20   Redistribution and use in source and binary forms, with or without
21   modification, are permitted provided that the following conditions are
22   met:
23 
24 	* Redistributions of source code must retain the above copyright notice,
25 	  this list of conditions and the following disclaimer.
26 	* Redistributions in binary form must reproduce the above copyright notice,
27 	  this list of conditions and the following disclaimer in the documentation
28 	  and/or other materials provided with the distribution.
29 	* Neither the name of the Case Labs, Ltd nor the names of its contributors
30 	  may be used to endorse or promote products derived from this software
31 	  without specific prior written permission.
32 
33   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
34   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
37   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
38   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
39   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
40   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
41   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43   POSSIBILITY OF SUCH DAMAGE.
44 
45 *****************************************************************************/
46 
47 #include "DMS.h"
48 
49 /*****************************************************************************
50 
51   Function:	 DMSUmes_Setup
52 
53 *****************************************************************************/
DMSUmes_Setup(Q931_TrunkInfo_t * pTrunk,L3UCHAR * IBuf,Q931mes_Generic * mes,L3INT IOff,L3INT Size)54 L3INT DMSUmes_Setup(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size)
55 {
56 	L3INT ir = 0;
57 	L3INT OOff = 0;
58 	L3INT rc = Q931E_NO_ERROR;
59 	L3UCHAR last_codeset = 0, codeset = 0;
60 	L3UCHAR shift_lock = 1;
61 
62 	while (IOff < Size) {
63 		if (!shift_lock) {
64 			codeset = last_codeset;
65 		}
66 
67 		if ((IBuf[IOff] & 0xF0) == Q931ie_SHIFT ) {
68 			shift_lock = (IBuf[IOff] & 0x08);
69 			if (shift_lock) {
70 				last_codeset = codeset;
71 			}
72 			codeset = ((IBuf[IOff] & 0x07));
73 			IOff++;
74 		}
75 
76 		if (codeset == 0) {
77 			switch (IBuf[IOff]) {
78 			case Q931ie_SENDING_COMPLETE:
79 			case Q931ie_BEARER_CAPABILITY:
80 			case Q931ie_CHANNEL_IDENTIFICATION:
81 			case Q931ie_PROGRESS_INDICATOR:
82 			case Q931ie_NETWORK_SPECIFIC_FACILITIES:
83 			case Q931ie_DISPLAY:
84 			case Q931ie_DATETIME:
85 			case Q931ie_KEYPAD_FACILITY:
86 			case Q931ie_SIGNAL:
87 			case Q931ie_CALLING_PARTY_NUMBER:
88 			case Q931ie_CALLING_PARTY_SUBADDRESS:
89 			case Q931ie_CALLED_PARTY_NUMBER:
90 			case Q931ie_CALLED_PARTY_SUBADDRESS:
91 			case Q931ie_TRANSIT_NETWORK_SELECTION:
92 			case Q931ie_LOW_LAYER_COMPATIBILITY:
93 			case Q931ie_HIGH_LAYER_COMPATIBILITY:
94 				rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
95 				if (rc != Q931E_NO_ERROR)
96 					return rc;
97 				break;
98 			case Q931ie_REPEAT_INDICATOR:
99 				if (ir < 2) {
100 					rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
101 					ir++;
102 				} else {
103 					return Q931E_ILLEGAL_IE;
104 				}
105 				break;
106 			default:
107 				return Q931E_ILLEGAL_IE;
108 				break;
109 			}
110 		} else if (codeset == 6) {
111 			switch (IBuf[IOff]) {
112 			case Q931ie_GENERIC_DIGITS:
113 				rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
114 				if (rc != Q931E_NO_ERROR)
115 					return rc;
116 				break;
117 			default:
118 				return Q931E_ILLEGAL_IE;
119 				break;
120 			}
121 
122 		} else {
123 			return Q931E_ILLEGAL_IE;
124 		}
125 	}
126 	mes->Size = sizeof(Q931mes_Generic) - 1 + OOff;
127 	return Q931E_NO_ERROR;
128 }
129 
130 /*****************************************************************************
131 
132   Function:	 DMSPmes_Setup
133 
134   Decription:	Pack a Q931mes_Generic into a real Q.931 message. The user will
135 				set up a SETUP message and issue this to the stack where it
136 				is processed by Q931ProcSetup that processes and validates
137 				it before it actually sends it out. This function is called
138 				to compute the real Q.931 message.
139 
140   Parameters:	IBuf[IN]	Ptr to un-packed struct
141 				ISize[IN]	Size of input buffer (unpacked message).
142 				OBuf[OUT]	Ptr to packed 'octet' wise message.
143 				OSize[OUT]	Size of packed message.
144 
145   Called By:	Q931ProcSetup
146 
147 *****************************************************************************/
DMSPmes_Setup(Q931_TrunkInfo_t * pTrunk,Q931mes_Generic * IBuf,L3INT ISize,L3UCHAR * OBuf,L3INT * OSize)148 L3INT DMSPmes_Setup(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize)
149 {
150 	L3INT rc = Q931E_NO_ERROR;
151 	Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf;
152 	L3INT Octet = 0;
153 
154 	/* Q931 Message Header */
155 	Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet);
156 
157 	/* Sending Complete */
158 	if (Q931IsIEPresent(pMes->SendComplete)) {
159 		OBuf[Octet++]	= (L3UCHAR)(pMes->SendComplete & 0x00ff);
160 	}
161 
162 	/* Repeat Indicator */
163 	if (Q931IsIEPresent(pMes->RepeatInd)) {
164 		OBuf[Octet++]	= (L3UCHAR)(pMes->RepeatInd & 0x00ff);
165 	}
166 
167 	/* Bearer capability */
168 	if (Q931IsIEPresent(pMes->BearerCap)) {
169 		if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_BEARER_CAPABILITY](pTrunk, Q931GetIEPtr(pMes->BearerCap,pMes->buf), OBuf, &Octet)) != 0)
170 			return rc;
171 	} else {
172 		rc = Q931E_BEARERCAP;
173 	}
174 
175 	/* Channel Identification */
176 	if (Q931IsIEPresent(pMes->ChanID)) {
177 		if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CHANNEL_IDENTIFICATION](pTrunk, Q931GetIEPtr(pMes->ChanID,pMes->buf), OBuf, &Octet)) != 0)
178 			return rc;
179 	}
180 
181 	/* Progress indicator */
182 	if (Q931IsIEPresent(pMes->ProgInd)) {
183 		if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_PROGRESS_INDICATOR](pTrunk, Q931GetIEPtr(pMes->ProgInd,pMes->buf), OBuf, &Octet)) != 0)
184 			return rc;
185 	}
186 
187 	/* Network spesific facilities */
188 	if (Q931IsIEPresent(pMes->NetFac)) {
189 		if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_NETWORK_SPECIFIC_FACILITIES](pTrunk, Q931GetIEPtr(pMes->NetFac,pMes->buf), OBuf, &Octet)) != 0)
190 			return rc;
191 	}
192 
193 	/* Display */
194 	if (Q931IsIEPresent(pMes->Display)) {
195 		if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0)
196 			return rc;
197 	}
198 
199 	/* Date/Time */
200 	if (Q931IsIEPresent(pMes->DateTime)) {
201 		if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DATETIME](pTrunk, Q931GetIEPtr(pMes->DateTime,pMes->buf), OBuf, &Octet)) != 0)
202 			return rc;
203 	}
204 
205 	/* Keypad Facility */
206 	if (Q931IsIEPresent(pMes->KeypadFac)) {
207 		if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_KEYPAD_FACILITY](pTrunk, Q931GetIEPtr(pMes->KeypadFac,pMes->buf), OBuf, &Octet)) != 0)
208 			return rc;
209 	}
210 
211 	/* Signal */
212 	if (Q931IsIEPresent(pMes->Signal)) {
213 		if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_SIGNAL](pTrunk, Q931GetIEPtr(pMes->Signal,pMes->buf), OBuf, &Octet)) != 0)
214 			return rc;
215 	}
216 
217 	/* Calling Party Number */
218 	if (Q931IsIEPresent(pMes->CallingNum)) {
219 		if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLING_PARTY_NUMBER](pTrunk, Q931GetIEPtr(pMes->CallingNum,pMes->buf), OBuf, &Octet)) != 0)
220 			return rc;
221 	}
222 
223 	/* Calling Party Subaddress */
224 	if (Q931IsIEPresent(pMes->CallingSub)) {
225 		if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLING_PARTY_SUBADDRESS](pTrunk, Q931GetIEPtr(pMes->CallingSub,pMes->buf), OBuf, &Octet)) != 0)
226 			return rc;
227 	}
228 
229 	/* Called Party number */
230 	if (Q931IsIEPresent(pMes->CalledNum)) {
231 		if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLED_PARTY_NUMBER](pTrunk, Q931GetIEPtr(pMes->CalledNum,pMes->buf), OBuf, &Octet)) != 0)
232 			return rc;
233 	}
234 
235 
236 	/* Called party subaddress */
237 	if (Q931IsIEPresent(pMes->CalledSub)) {
238 		if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLED_PARTY_SUBADDRESS](pTrunk, Q931GetIEPtr(pMes->CalledSub,pMes->buf), OBuf, &Octet)) != 0)
239 			return rc;
240 	}
241 
242 	/* Transit network selection */
243 	if (Q931IsIEPresent(pMes->TransNetSel)) {
244 		if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_TRANSIT_NETWORK_SELECTION](pTrunk, Q931GetIEPtr(pMes->TransNetSel,pMes->buf), OBuf, &Octet)) != 0)
245 			return rc;
246 	}
247 
248 	/* Repeat Indicator */
249 	if (Q931IsIEPresent(pMes->LLRepeatInd)) {
250 		rc = Q931E_UNKNOWN_IE;/* TODO */
251 	}
252 
253 	/* Low Layer Compatibility */
254 	if (Q931IsIEPresent(pMes->LLComp)) {
255 		if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_LOW_LAYER_COMPATIBILITY](pTrunk, Q931GetIEPtr(pMes->LLComp,pMes->buf), OBuf, &Octet)) != 0)
256 			return rc;
257 	}
258 
259 	/* High Layer Compatibility */
260 	if (Q931IsIEPresent(pMes->HLComp)) {
261 		if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_HIGH_LAYER_COMPATIBILITY](pTrunk, Q931GetIEPtr(pMes->HLComp,pMes->buf), OBuf, &Octet)) != 0)
262 			return rc;
263 	}
264 
265 	*OSize = Octet;
266 	return rc;
267 }
268 
269 
270 /*****************************************************************************
271 
272   Function:	 DMSUmes_0x0f
273 
274 *****************************************************************************/
DMSUmes_0x0f(Q931_TrunkInfo_t * pTrunk,L3UCHAR * IBuf,Q931mes_Generic * mes,L3INT IOff,L3INT Size)275 L3INT DMSUmes_0x0f(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size)
276 {
277 	if (mes->ProtDisc == 8) {
278 		return Q931Umes_ConnectAck(pTrunk, IBuf, mes, IOff, Size);
279 	}
280 
281 	if (mes->ProtDisc == 3) {
282 		return Q931Umes_Service(pTrunk, IBuf, mes, IOff, Size);
283 	}
284 
285 	return Q931E_UNKNOWN_MESSAGE;
286 }
287 
288 /*****************************************************************************
289 
290   Function:	 DMSPmes_0x0f
291 
292 *****************************************************************************/
DMSPmes_0x0f(Q931_TrunkInfo_t * pTrunk,Q931mes_Generic * IBuf,L3INT ISize,L3UCHAR * OBuf,L3INT * OSize)293 L3INT DMSPmes_0x0f(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize)
294 {
295 	Q931mes_Generic *mes = (Q931mes_Generic *)IBuf;
296 
297 	if (mes->ProtDisc == 8) {
298 		return Q931Pmes_ConnectAck(pTrunk, IBuf, ISize, OBuf, OSize);
299 	}
300 
301 	if (mes->ProtDisc == 3) {
302 		return Q931Pmes_Service(pTrunk, IBuf, ISize, OBuf, OSize);
303 	}
304 
305 	return Q931E_UNKNOWN_MESSAGE;
306 }
307 
308 /*****************************************************************************
309 
310   Function:	 DMSUmes_0x07
311 
312 *****************************************************************************/
DMSUmes_0x07(Q931_TrunkInfo_t * pTrunk,L3UCHAR * IBuf,Q931mes_Generic * mes,L3INT IOff,L3INT Size)313 L3INT DMSUmes_0x07(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size)
314 {
315 	if (mes->ProtDisc == 8) {
316 		return Q931Umes_Connect(pTrunk, IBuf, mes, IOff, Size);
317 	}
318 
319 	if (mes->ProtDisc == 3) {
320 		return Q931Umes_ServiceAck(pTrunk, IBuf, mes, IOff, Size);
321 	}
322 
323 	return Q931E_UNKNOWN_MESSAGE;
324 }
325 
326 /*****************************************************************************
327 
328   Function:	 DMSPmes_0x07
329 
330 *****************************************************************************/
DMSPmes_0x07(Q931_TrunkInfo_t * pTrunk,Q931mes_Generic * IBuf,L3INT ISize,L3UCHAR * OBuf,L3INT * OSize)331 L3INT DMSPmes_0x07(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize)
332 {
333 	Q931mes_Generic *mes = (Q931mes_Generic *)IBuf;
334 
335 	if (mes->ProtDisc == 8) {
336 		return Q931Pmes_Connect(pTrunk, IBuf, ISize, OBuf, OSize);
337 	}
338 
339 	if (mes->ProtDisc == 3) {
340 		return Q931Pmes_ServiceAck(pTrunk, IBuf, ISize, OBuf, OSize);
341 	}
342 
343 	return Q931E_UNKNOWN_MESSAGE;
344 }
345