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