1 /*
2  * libpri: An implementation of Primary Rate ISDN
3  *
4  * Copyright (C) 2009 Digium, Inc.
5  *
6  * Richard Mudgett <rmudgett@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2 as published by the
16  * Free Software Foundation. See the LICENSE file included with
17  * this program for more details.
18  *
19  * In addition, when this program is distributed with Asterisk in
20  * any form that would qualify as a 'combined work' or as a
21  * 'derivative work' (but not mere aggregation), you can redistribute
22  * and/or modify the combination under the terms of the license
23  * provided with that copy of Asterisk, instead of the license
24  * terms granted here.
25  */
26 
27 /*!
28  * \file
29  * \brief Remote Operations Service Element (ROSE) main controlling functions
30  *
31  * \author Richard Mudgett <rmudgett@digium.com>
32  */
33 
34 
35 #include <stdio.h>
36 
37 #include "compat.h"
38 #include "libpri.h"
39 #include "pri_internal.h"
40 #include "rose.h"
41 #include "rose_internal.h"
42 #include "asn1.h"
43 #include "pri_facility.h"
44 
45 
46 #define ROSE_TAG_COMPONENT_INVOKE	(ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1)
47 #define ROSE_TAG_COMPONENT_RESULT	(ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2)
48 #define ROSE_TAG_COMPONENT_ERROR	(ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3)
49 #define ROSE_TAG_COMPONENT_REJECT	(ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 4)
50 
51 /*! \brief Structure to convert a code value to a string */
52 struct rose_code_strings {
53 	/*! \brief Code value to convert to a string */
54 	int code;
55 	/*! \brief String equivalent of the associated code value */
56 	const char *name;
57 };
58 
59 /*! \brief ROSE invoke/result message conversion table entry. */
60 struct rose_convert_msg {
61 	/*! \brief library encoded operation-value */
62 	enum rose_operation operation;
63 	/*!
64 	 * \brief OID prefix values to use when encoding/decoding the operation-value OID
65 	 * \note NULL if operation-value is a localValue.
66 	 */
67 	const struct asn1_oid *oid_prefix;
68 	/*! \brief Last OID value or localValue for the encoded operation-value */
69 	u_int16_t value;
70 
71 	/*!
72 	 * \brief Encode the ROSE invoke operation-value arguments.
73 	 *
74 	 * \param ctrl D channel controller for diagnostic messages or global options.
75 	 * \param pos Starting position to encode ASN.1 component.
76 	 * \param end End of ASN.1 encoding data buffer.
77 	 * \param args Arguments to encode in the buffer.
78 	 *
79 	 * \retval Start of the next ASN.1 component to encode on success.
80 	 * \retval NULL on error.
81 	 *
82 	 * \note The function pointer is NULL if there are no arguments to encode.
83 	 */
84 	unsigned char *(*encode_invoke_args)(struct pri *ctrl, unsigned char *pos,
85 		unsigned char *end, const union rose_msg_invoke_args *args);
86 	/*!
87 	 * \brief Encode the ROSE result operation-value arguments.
88 	 *
89 	 * \param ctrl D channel controller for diagnostic messages or global options.
90 	 * \param pos Starting position to encode ASN.1 component.
91 	 * \param end End of ASN.1 encoding data buffer.
92 	 * \param args Arguments to encode in the buffer.
93 	 *
94 	 * \retval Start of the next ASN.1 component to encode on success.
95 	 * \retval NULL on error.
96 	 *
97 	 * \note The function pointer is NULL if there are no arguments to encode.
98 	 */
99 	unsigned char *(*encode_result_args)(struct pri *ctrl, unsigned char *pos,
100 		unsigned char *end, const union rose_msg_result_args *args);
101 
102 	/*!
103 	 * \brief Decode the ROSE invoke operation-value arguments.
104 	 *
105 	 * \param ctrl D channel controller for diagnostic messages or global options.
106 	 * \param tag Component tag that identified this structure.
107 	 * \param pos Starting position of the ASN.1 component length.
108 	 * \param end End of ASN.1 decoding data buffer.
109 	 * \param args Arguments to fill in from the decoded buffer.
110 	 *
111 	 * \retval Start of the next ASN.1 component on success.
112 	 * \retval NULL on error.
113 	 *
114 	 * \note The function pointer is NULL if there are no arguments to decode.
115 	 */
116 	const unsigned char *(*decode_invoke_args)(struct pri *ctrl, unsigned tag,
117 		const unsigned char *pos, const unsigned char *end,
118 		union rose_msg_invoke_args *args);
119 	/*!
120 	 * \brief Decode the ROSE result operation-value arguments.
121 	 *
122 	 * \param ctrl D channel controller for diagnostic messages or global options.
123 	 * \param tag Component tag that identified this structure.
124 	 * \param pos Starting position of the ASN.1 component length.
125 	 * \param end End of ASN.1 decoding data buffer.
126 	 * \param args Arguments to fill in from the decoded buffer.
127 	 *
128 	 * \retval Start of the next ASN.1 component on success.
129 	 * \retval NULL on error.
130 	 *
131 	 * \note The function pointer is NULL if there are no arguments to decode.
132 	 */
133 	const unsigned char *(*decode_result_args)(struct pri *ctrl, unsigned tag,
134 		const unsigned char *pos, const unsigned char *end,
135 		union rose_msg_result_args *args);
136 };
137 
138 /*! \brief ROSE error code conversion table entry. */
139 struct rose_convert_error {
140 	/*! \brief library encoded error-value */
141 	enum rose_error_code code;
142 	/*!
143 	 * \brief OID prefix values to use when encoding/decoding the error-value OID
144 	 * \note NULL if error-value is a localValue.
145 	 */
146 	const struct asn1_oid *oid_prefix;
147 	/*! \brief Last OID value or localValue for the encoded error-value */
148 	u_int16_t value;
149 
150 	/*!
151 	 * \brief Encode the ROSE error parameters.
152 	 *
153 	 * \param ctrl D channel controller for diagnostic messages or global options.
154 	 * \param pos Starting position to encode ASN.1 component.
155 	 * \param end End of ASN.1 encoding data buffer.
156 	 * \param args Arguments to encode in the buffer.
157 	 *
158 	 * \retval Start of the next ASN.1 component to encode on success.
159 	 * \retval NULL on error.
160 	 *
161 	 * \note The function pointer is NULL if there are no arguments to encode.
162 	 */
163 	unsigned char *(*encode_error_args)(struct pri *ctrl, unsigned char *pos,
164 		unsigned char *end, const union rose_msg_error_args *args);
165 
166 	/*!
167 	 * \brief Decode the ROSE error parameters.
168 	 *
169 	 * \param ctrl D channel controller for diagnostic messages or global options.
170 	 * \param tag Component tag that identified this structure.
171 	 * \param pos Starting position of the ASN.1 component length.
172 	 * \param end End of ASN.1 decoding data buffer.
173 	 * \param args Arguments to fill in from the decoded buffer.
174 	 *
175 	 * \retval Start of the next ASN.1 component on success.
176 	 * \retval NULL on error.
177 	 *
178 	 * \note The function pointer is NULL if there are no arguments to decode.
179 	 */
180 	const unsigned char *(*decode_error_args)(struct pri *ctrl, unsigned tag,
181 		const unsigned char *pos, const unsigned char *end,
182 		union rose_msg_error_args *args);
183 };
184 
185 
186 /* ------------------------------------------------------------------- */
187 
188 
189 /*
190  * Note the first value in oid.values[] is really the first two
191  * OID subidentifiers.  They are compressed using this formula:
192  * First_Value = (First_Subidentifier * 40) + Second_Subidentifier
193  */
194 
195 /*! \brief ETSI Explicit Call Transfer OID prefix. */
196 static const struct asn1_oid rose_etsi_ect = {
197 /* *INDENT-OFF* */
198 	/* {ccitt(0) identified-organization(4) etsi(0) 369 operations-and-errors(1)} */
199 	4, { 4, 0, 369, 1 }
200 /* *INDENT-ON* */
201 };
202 
203 /*! \brief ETSI Status Request OID prefix. */
204 static const struct asn1_oid rose_etsi_status_request = {
205 /* *INDENT-OFF* */
206 	/* {itu-t(0) identified-organization(4) etsi(0) 196 status-request-procedure(9)} */
207 	4, { 4, 0, 196, 9 }
208 /* *INDENT-ON* */
209 };
210 
211 /*! \brief ETSI Call Completion Busy Status OID prefix. */
212 static const struct asn1_oid rose_etsi_ccbs = {
213 /* *INDENT-OFF* */
214 	/* {ccitt(0) identified-organization(4) etsi(0) 359 operations-and-errors(1)} */
215 	4, { 4, 0, 359, 1 }
216 /* *INDENT-ON* */
217 };
218 
219 /*! \brief ETSI Call Completion Busy Status public-private interworking OID prefix. */
220 static const struct asn1_oid rose_etsi_ccbs_t = {
221 /* *INDENT-OFF* */
222 	/* {ccitt(0) identified-organization(4) etsi(0) 359 private-networks-operations-and-errors(2)} */
223 	4, { 4, 0, 359, 2 }
224 /* *INDENT-ON* */
225 };
226 
227 /*! \brief ETSI Call Completion No Reply OID prefix. */
228 static const struct asn1_oid rose_etsi_ccnr = {
229 /* *INDENT-OFF* */
230 	/* {ccitt(0) identified-organization(4) etsi(0) 1065 operations-and-errors(1)} */
231 	4, { 4, 0, 1065, 1 }
232 /* *INDENT-ON* */
233 };
234 
235 /*! \brief ETSI Call Completion No Reply public-private interworking OID prefix. */
236 static const struct asn1_oid rose_etsi_ccnr_t = {
237 /* *INDENT-OFF* */
238 	/* {ccitt(0) identified-organization(4) etsi(0) 1065 private-networks-operations-and-errors(2)} */
239 	4, { 4, 0, 1065, 2 }
240 /* *INDENT-ON* */
241 };
242 
243 /*! \brief ETSI Message Waiting Indication OID prefix. */
244 static const struct asn1_oid rose_etsi_mwi = {
245 /* *INDENT-OFF* */
246 	/* {ccitt(0) identified-organization(4) etsi(0) 745 operations-and-errors(1)} */
247 	4, { 4, 0, 745, 1 }
248 /* *INDENT-ON* */
249 };
250 
251 /*! \brief ETSI specific invoke/result encode/decode message table */
252 static const struct rose_convert_msg rose_etsi_msgs[] = {
253 /* *INDENT-OFF* */
254 /*
255  *		operation,                                  oid_prefix, value,
256  *			encode_invoke_args,                     encode_result_args,
257  *			decode_invoke_args,                     decode_result_args
258  */
259 	/*
260 	 * localValue's from Diversion-Operations
261 	 * {ccitt identified-organization etsi(0) 207 operations-and-errors(1)}
262 	 */
263 	{
264 		ROSE_ETSI_ActivationDiversion,				NULL, 7,
265 			rose_enc_etsi_ActivationDiversion_ARG,	NULL,
266 			rose_dec_etsi_ActivationDiversion_ARG,	NULL
267 	},
268 	{
269 		ROSE_ETSI_DeactivationDiversion,			NULL, 8,
270 			rose_enc_etsi_DeactivationDiversion_ARG,NULL,
271 			rose_dec_etsi_DeactivationDiversion_ARG,NULL
272 	},
273 	{
274 		ROSE_ETSI_ActivationStatusNotificationDiv,	NULL, 9,
275 			rose_enc_etsi_ActivationStatusNotificationDiv_ARG,NULL,
276 			rose_dec_etsi_ActivationStatusNotificationDiv_ARG,NULL
277 	},
278 	{
279 		ROSE_ETSI_DeactivationStatusNotificationDiv,NULL, 10,
280 			rose_enc_etsi_DeactivationStatusNotificationDiv_ARG,NULL,
281 			rose_dec_etsi_DeactivationStatusNotificationDiv_ARG,NULL
282 	},
283 	{
284 		ROSE_ETSI_InterrogationDiversion,			NULL, 11,
285 			rose_enc_etsi_InterrogationDiversion_ARG,rose_enc_etsi_InterrogationDiversion_RES,
286 			rose_dec_etsi_InterrogationDiversion_ARG,rose_dec_etsi_InterrogationDiversion_RES
287 	},
288 	{
289 		ROSE_ETSI_DiversionInformation,				NULL, 12,
290 			rose_enc_etsi_DiversionInformation_ARG,	NULL,
291 			rose_dec_etsi_DiversionInformation_ARG,	NULL
292 	},
293 	{
294 		ROSE_ETSI_CallDeflection,					NULL, 13,
295 			rose_enc_etsi_CallDeflection_ARG,		NULL,
296 			rose_dec_etsi_CallDeflection_ARG,		NULL
297 	},
298 	{
299 		ROSE_ETSI_CallRerouting,					NULL, 14,
300 			rose_enc_etsi_CallRerouting_ARG,		NULL,
301 			rose_dec_etsi_CallRerouting_ARG,		NULL
302 	},
303 	{
304 		ROSE_ETSI_DivertingLegInformation2,			NULL, 15,
305 			rose_enc_etsi_DivertingLegInformation2_ARG,NULL,
306 			rose_dec_etsi_DivertingLegInformation2_ARG,NULL
307 	},
308 	{
309 		ROSE_ETSI_InterrogateServedUserNumbers,		NULL, 17,
310 			NULL,									rose_enc_etsi_InterrogateServedUserNumbers_RES,
311 			NULL,									rose_dec_etsi_InterrogateServedUserNumbers_RES
312 	},
313 	{
314 		ROSE_ETSI_DivertingLegInformation1,			NULL, 18,
315 			rose_enc_etsi_DivertingLegInformation1_ARG,NULL,
316 			rose_dec_etsi_DivertingLegInformation1_ARG,NULL
317 	},
318 	{
319 		ROSE_ETSI_DivertingLegInformation3,			NULL, 19,
320 			rose_enc_etsi_DivertingLegInformation3_ARG,NULL,
321 			rose_dec_etsi_DivertingLegInformation3_ARG,NULL
322 	},
323 
324 	/*
325 	 * localValue's from Advice-of-Charge-Operations
326 	 * {ccitt identified-organization etsi (0) 182 operations-and-errors (1)}
327 	 *
328 	 * Advice-Of-Charge-at-call-Setup(AOCS)
329 	 * Advice-Of-Charge-During-the-call(AOCD)
330 	 * Advice-Of-Charge-at-the-End-of-the-call(AOCE)
331 	 */
332 	{
333 		ROSE_ETSI_ChargingRequest,					NULL, 30,
334 			rose_enc_etsi_ChargingRequest_ARG,		rose_enc_etsi_ChargingRequest_RES,
335 			rose_dec_etsi_ChargingRequest_ARG,		rose_dec_etsi_ChargingRequest_RES
336 	},
337 	{
338 		ROSE_ETSI_AOCSCurrency,						NULL, 31,
339 			rose_enc_etsi_AOCSCurrency_ARG,			NULL,
340 			rose_dec_etsi_AOCSCurrency_ARG,			NULL
341 	},
342 	{
343 		ROSE_ETSI_AOCSSpecialArr,					NULL, 32,
344 			rose_enc_etsi_AOCSSpecialArr_ARG,		NULL,
345 			rose_dec_etsi_AOCSSpecialArr_ARG,		NULL
346 	},
347 	{
348 		ROSE_ETSI_AOCDCurrency,						NULL, 33,
349 			rose_enc_etsi_AOCDCurrency_ARG,			NULL,
350 			rose_dec_etsi_AOCDCurrency_ARG,			NULL
351 	},
352 	{
353 		ROSE_ETSI_AOCDChargingUnit,					NULL, 34,
354 			rose_enc_etsi_AOCDChargingUnit_ARG,		NULL,
355 			rose_dec_etsi_AOCDChargingUnit_ARG,		NULL
356 	},
357 	{
358 		ROSE_ETSI_AOCECurrency,						NULL, 35,
359 			rose_enc_etsi_AOCECurrency_ARG,			NULL,
360 			rose_dec_etsi_AOCECurrency_ARG,			NULL
361 	},
362 	{
363 		ROSE_ETSI_AOCEChargingUnit,					NULL, 36,
364 			rose_enc_etsi_AOCEChargingUnit_ARG,		NULL,
365 			rose_dec_etsi_AOCEChargingUnit_ARG,		NULL
366 	},
367 
368 	/*
369 	 * localValue's from Explicit-Call-Transfer-Operations-and-Errors
370 	 * {ccitt identified-organization etsi(0) 369 operations-and-errors(1)}
371 	 */
372 	{
373 		ROSE_ETSI_EctExecute,						NULL, 6,
374 			NULL,									NULL,
375 			NULL,									NULL
376 	},
377 
378 	/*
379 	 * globalValue's (OIDs) from Explicit-Call-Transfer-Operations-and-Errors
380 	 * {ccitt identified-organization etsi(0) 369 operations-and-errors(1)}
381 	 */
382 	{
383 		ROSE_ETSI_ExplicitEctExecute,				&rose_etsi_ect, 1,
384 			rose_enc_etsi_ExplicitEctExecute_ARG,	NULL,
385 			rose_dec_etsi_ExplicitEctExecute_ARG,	NULL
386 	},
387 	{
388 		ROSE_ETSI_RequestSubaddress,				&rose_etsi_ect, 2,
389 			NULL,									NULL,
390 			NULL,									NULL
391 	},
392 	{
393 		ROSE_ETSI_SubaddressTransfer,				&rose_etsi_ect, 3,
394 			rose_enc_etsi_SubaddressTransfer_ARG,	NULL,
395 			rose_dec_etsi_SubaddressTransfer_ARG,	NULL
396 	},
397 	{
398 		ROSE_ETSI_EctLinkIdRequest,					&rose_etsi_ect, 4,
399 			NULL,									rose_enc_etsi_EctLinkIdRequest_RES,
400 			NULL,									rose_dec_etsi_EctLinkIdRequest_RES
401 	},
402 	{
403 		ROSE_ETSI_EctInform,						&rose_etsi_ect, 5,
404 			rose_enc_etsi_EctInform_ARG,			NULL,
405 			rose_dec_etsi_EctInform_ARG,			NULL
406 	},
407 	{
408 		ROSE_ETSI_EctLoopTest,						&rose_etsi_ect, 6,
409 			rose_enc_etsi_EctLoopTest_ARG,			rose_enc_etsi_EctLoopTest_RES,
410 			rose_dec_etsi_EctLoopTest_ARG,			rose_dec_etsi_EctLoopTest_RES
411 	},
412 
413 	/*
414 	 * globalValue's (OIDs) from Status-Request-Procedure
415 	 * {itu-t identified-organization etsi(0) 196 status-request-procedure(9)}
416 	 */
417 	{
418 		ROSE_ETSI_StatusRequest,					&rose_etsi_status_request, 1,
419 			rose_enc_etsi_StatusRequest_ARG,		rose_enc_etsi_StatusRequest_RES,
420 			rose_dec_etsi_StatusRequest_ARG,		rose_dec_etsi_StatusRequest_RES
421 	},
422 
423 	/*
424 	 * globalValue's (OIDs) from CCBS-Operations-and-Errors
425 	 * {ccitt identified-organization etsi(0) 359 operations-and-errors(1)}
426 	 */
427 	{
428 		ROSE_ETSI_CallInfoRetain,					&rose_etsi_ccbs, 1,
429 			rose_enc_etsi_CallInfoRetain_ARG,		NULL,
430 			rose_dec_etsi_CallInfoRetain_ARG,		NULL
431 	},
432 	{
433 		ROSE_ETSI_CCBSRequest,						&rose_etsi_ccbs, 2,
434 			rose_enc_etsi_CCBSRequest_ARG,			rose_enc_etsi_CCBSRequest_RES,
435 			rose_dec_etsi_CCBSRequest_ARG,			rose_dec_etsi_CCBSRequest_RES
436 	},
437 	{
438 		ROSE_ETSI_CCBSDeactivate,					&rose_etsi_ccbs, 3,
439 			rose_enc_etsi_CCBSDeactivate_ARG,		NULL,
440 			rose_dec_etsi_CCBSDeactivate_ARG,		NULL
441 	},
442 	{
443 		ROSE_ETSI_CCBSInterrogate,					&rose_etsi_ccbs, 4,
444 			rose_enc_etsi_CCBSInterrogate_ARG,		rose_enc_etsi_CCBSInterrogate_RES,
445 			rose_dec_etsi_CCBSInterrogate_ARG,		rose_dec_etsi_CCBSInterrogate_RES
446 	},
447 	{
448 		ROSE_ETSI_CCBSErase,						&rose_etsi_ccbs, 5,
449 			rose_enc_etsi_CCBSErase_ARG,			NULL,
450 			rose_dec_etsi_CCBSErase_ARG,			NULL
451 	},
452 	{
453 		ROSE_ETSI_CCBSRemoteUserFree,				&rose_etsi_ccbs, 6,
454 			rose_enc_etsi_CCBSRemoteUserFree_ARG,	NULL,
455 			rose_dec_etsi_CCBSRemoteUserFree_ARG,	NULL
456 	},
457 	{
458 		ROSE_ETSI_CCBSCall,							&rose_etsi_ccbs, 7,
459 			rose_enc_etsi_CCBSCall_ARG,				NULL,
460 			rose_dec_etsi_CCBSCall_ARG,				NULL
461 	},
462 	{
463 		ROSE_ETSI_CCBSStatusRequest,				&rose_etsi_ccbs, 8,
464 			rose_enc_etsi_CCBSStatusRequest_ARG,	rose_enc_etsi_CCBSStatusRequest_RES,
465 			rose_dec_etsi_CCBSStatusRequest_ARG,	rose_dec_etsi_CCBSStatusRequest_RES
466 	},
467 	{
468 		ROSE_ETSI_CCBSBFree,						&rose_etsi_ccbs, 9,
469 			rose_enc_etsi_CCBSBFree_ARG,			NULL,
470 			rose_dec_etsi_CCBSBFree_ARG,			NULL
471 	},
472 	{
473 		ROSE_ETSI_EraseCallLinkageID,				&rose_etsi_ccbs, 10,
474 			rose_enc_etsi_EraseCallLinkageID_ARG,	NULL,
475 			rose_dec_etsi_EraseCallLinkageID_ARG,	NULL
476 	},
477 	{
478 		ROSE_ETSI_CCBSStopAlerting,					&rose_etsi_ccbs, 11,
479 			rose_enc_etsi_CCBSStopAlerting_ARG,		NULL,
480 			rose_dec_etsi_CCBSStopAlerting_ARG,		NULL
481 	},
482 
483 	/*
484 	 * globalValue's (OIDs) from CCBS-private-networks-Operations-and-Errors
485 	 * {ccitt identified-organization etsi(0) 359 private-networks-operations-and-errors(2)}
486 	 */
487 	{
488 		ROSE_ETSI_CCBS_T_Request,					&rose_etsi_ccbs_t, 1,
489 			rose_enc_etsi_CCBS_T_Request_ARG,		rose_enc_etsi_CCBS_T_Request_RES,
490 			rose_dec_etsi_CCBS_T_Request_ARG,		rose_dec_etsi_CCBS_T_Request_RES
491 	},
492 	{
493 		ROSE_ETSI_CCBS_T_Call,						&rose_etsi_ccbs_t, 2,
494 			NULL,									NULL,
495 			NULL,									NULL
496 	},
497 	{
498 		ROSE_ETSI_CCBS_T_Suspend,					&rose_etsi_ccbs_t, 3,
499 			NULL,									NULL,
500 			NULL,									NULL
501 	},
502 	{
503 		ROSE_ETSI_CCBS_T_Resume,					&rose_etsi_ccbs_t, 4,
504 			NULL,									NULL,
505 			NULL,									NULL
506 	},
507 	{
508 		ROSE_ETSI_CCBS_T_RemoteUserFree,			&rose_etsi_ccbs_t, 5,
509 			NULL,									NULL,
510 			NULL,									NULL
511 	},
512 	{
513 		ROSE_ETSI_CCBS_T_Available,					&rose_etsi_ccbs_t, 6,
514 			NULL,									NULL,
515 			NULL,									NULL
516 	},
517 
518 	/*
519 	 * globalValue's (OIDs) from CCNR-Operations-and-Errors
520 	 * {ccitt identified-organization etsi(0) 1065 operations-and-errors(1)}
521 	 */
522 	{
523 		ROSE_ETSI_CCNRRequest,						&rose_etsi_ccnr, 1,
524 			rose_enc_etsi_CCNRRequest_ARG,			rose_enc_etsi_CCNRRequest_RES,
525 			rose_dec_etsi_CCNRRequest_ARG,			rose_dec_etsi_CCNRRequest_RES
526 	},
527 	{
528 		ROSE_ETSI_CCNRInterrogate,					&rose_etsi_ccnr, 2,
529 			rose_enc_etsi_CCNRInterrogate_ARG,		rose_enc_etsi_CCNRInterrogate_RES,
530 			rose_dec_etsi_CCNRInterrogate_ARG,		rose_dec_etsi_CCNRInterrogate_RES
531 	},
532 
533 	/*
534 	 * globalValue's (OIDs) from CCNR-private-networks-Operations-and-Errors
535 	 * {ccitt identified-organization etsi(0) 1065 private-networks-operations-and-errors(2)}
536 	 */
537 	{
538 		ROSE_ETSI_CCNR_T_Request,					&rose_etsi_ccnr_t, 1,
539 			rose_enc_etsi_CCNR_T_Request_ARG,		rose_enc_etsi_CCNR_T_Request_RES,
540 			rose_dec_etsi_CCNR_T_Request_ARG,		rose_dec_etsi_CCNR_T_Request_RES
541 	},
542 
543 	/*
544 	 * localValue's from MCID-Operations
545 	 * {ccitt identified-organization etsi(0) 130 operations-and-errors(1)}
546 	 */
547 	{
548 		ROSE_ETSI_MCIDRequest,						NULL, 3,
549 			NULL,									NULL,
550 			NULL,									NULL
551 	},
552 
553 	/*
554 	 * globalValue's (OIDs) from MWI-Operations-and-Errors
555 	 * {ccitt identified-organization etsi(0) 745 operations-and-errors(1)}
556 	 */
557 	{
558 		ROSE_ETSI_MWIActivate,						&rose_etsi_mwi, 1,
559 			rose_enc_etsi_MWIActivate_ARG,			NULL,
560 			rose_dec_etsi_MWIActivate_ARG,			NULL
561 	},
562 	{
563 		ROSE_ETSI_MWIDeactivate,					&rose_etsi_mwi, 2,
564 			rose_enc_etsi_MWIDeactivate_ARG,		NULL,
565 			rose_dec_etsi_MWIDeactivate_ARG,		NULL
566 	},
567 	{
568 		ROSE_ETSI_MWIIndicate,						&rose_etsi_mwi, 3,
569 			rose_enc_etsi_MWIIndicate_ARG,			NULL,
570 			rose_dec_etsi_MWIIndicate_ARG,			NULL
571 	},
572 /* *INDENT-ON* */
573 };
574 
575 
576 /*! \brief ETSI specific error-value converion table */
577 static const struct rose_convert_error rose_etsi_errors[] = {
578 /* *INDENT-OFF* */
579 /*
580  *		error-code,                                 oid_prefix, value
581  *			encode_error_args,                      decode_error_args
582  */
583 	/*
584 	 * localValue Errors from General-Errors
585 	 * {ccitt identified-organization etsi(0) 196 general-errors(2)}
586 	 */
587 	{
588 		ROSE_ERROR_Gen_NotSubscribed,				NULL, 0,
589 			NULL,									NULL
590 	},
591 	{
592 		ROSE_ERROR_Gen_NotAvailable,				NULL, 3,
593 			NULL,									NULL
594 	},
595 	{
596 		ROSE_ERROR_Gen_NotImplemented,				NULL, 4,
597 			NULL,									NULL
598 	},
599 	{
600 		ROSE_ERROR_Gen_InvalidServedUserNr,			NULL, 6,
601 			NULL,									NULL
602 	},
603 	{
604 		ROSE_ERROR_Gen_InvalidCallState,			NULL, 7,
605 			NULL,									NULL
606 	},
607 	{
608 		ROSE_ERROR_Gen_BasicServiceNotProvided,		NULL, 8,
609 			NULL,									NULL
610 	},
611 	{
612 		ROSE_ERROR_Gen_NotIncomingCall,				NULL, 9,
613 			NULL,									NULL
614 	},
615 	{
616 		ROSE_ERROR_Gen_SupplementaryServiceInteractionNotAllowed,NULL, 10,
617 			NULL,									NULL
618 	},
619 	{
620 		ROSE_ERROR_Gen_ResourceUnavailable,			NULL, 11,
621 			NULL,									NULL
622 	},
623 
624 	/*
625 	 * localValue Errors from Diversion-Operations
626 	 * {ccitt identified-organization etsi(0) 207 operations-and-errors(1)}
627 	 */
628 	{
629 		ROSE_ERROR_Div_InvalidDivertedToNr,			NULL, 12,
630 			NULL,									NULL
631 	},
632 	{
633 		ROSE_ERROR_Div_SpecialServiceNr,			NULL, 14,
634 			NULL,									NULL
635 	},
636 	{
637 		ROSE_ERROR_Div_DiversionToServedUserNr,		NULL, 15,
638 			NULL,									NULL
639 	},
640 	{
641 		ROSE_ERROR_Div_IncomingCallAccepted,		NULL, 23,
642 			NULL,									NULL
643 	},
644 	{
645 		ROSE_ERROR_Div_NumberOfDiversionsExceeded,	NULL, 24,
646 			NULL,									NULL
647 	},
648 	{
649 		ROSE_ERROR_Div_NotActivated,				NULL, 46,
650 			NULL,									NULL
651 	},
652 	{
653 		ROSE_ERROR_Div_RequestAlreadyAccepted,		NULL, 48,
654 			NULL,									NULL
655 	},
656 
657 	/*
658 	 * localValue Errors from Advice-of-Charge-Operations
659 	 * {ccitt identified-organization etsi (0) 182 operations-and-errors (1)}
660 	 */
661 	{
662 		ROSE_ERROR_AOC_NoChargingInfoAvailable,		NULL, 26,
663 			NULL,									NULL
664 	},
665 
666 	/*
667 	 * globalValue Errors (OIDs) from Explicit-Call-Transfer-Operations-and-Errors
668 	 * {ccitt identified-organization etsi(0) 369 operations-and-errors(1)}
669 	 */
670 	{
671 		ROSE_ERROR_ECT_LinkIdNotAssignedByNetwork,	&rose_etsi_ect, 21,
672 			NULL,									NULL
673 	},
674 
675 	/*
676 	 * globalValue Errors (OIDs) from CCBS-Operations-and-Errors
677 	 * {ccitt identified-organization etsi(0) 359 operations-and-errors(1)}
678 	 */
679 	{
680 		ROSE_ERROR_CCBS_InvalidCallLinkageID,		&rose_etsi_ccbs, 20,
681 			NULL,									NULL
682 	},
683 	{
684 		ROSE_ERROR_CCBS_InvalidCCBSReference,		&rose_etsi_ccbs, 21,
685 			NULL,									NULL
686 	},
687 	{
688 		ROSE_ERROR_CCBS_LongTermDenial,				&rose_etsi_ccbs, 22,
689 			NULL,									NULL
690 	},
691 	{
692 		ROSE_ERROR_CCBS_ShortTermDenial,			&rose_etsi_ccbs, 23,
693 			NULL,									NULL
694 	},
695 	{
696 		ROSE_ERROR_CCBS_IsAlreadyActivated,			&rose_etsi_ccbs, 24,
697 			NULL,									NULL
698 	},
699 	{
700 		ROSE_ERROR_CCBS_AlreadyAccepted,			&rose_etsi_ccbs, 25,
701 			NULL,									NULL
702 	},
703 	{
704 		ROSE_ERROR_CCBS_OutgoingCCBSQueueFull,		&rose_etsi_ccbs, 26,
705 			NULL,									NULL
706 	},
707 	{
708 		ROSE_ERROR_CCBS_CallFailureReasonNotBusy,	&rose_etsi_ccbs, 27,
709 			NULL,									NULL
710 	},
711 	{
712 		ROSE_ERROR_CCBS_NotReadyForCall,			&rose_etsi_ccbs, 28,
713 			NULL,									NULL
714 	},
715 
716 	/*
717 	 * globalValue Errors (OIDs) from CCBS-private-networks-Operations-and-Errors
718 	 * {ccitt identified-organization etsi(0) 359 private-networks-operations-and-errors(2)}
719 	 */
720 	{
721 		ROSE_ERROR_CCBS_T_LongTermDenial,			&rose_etsi_ccbs_t, 20,
722 			NULL,									NULL
723 	},
724 	{
725 		ROSE_ERROR_CCBS_T_ShortTermDenial,			&rose_etsi_ccbs_t, 21,
726 			NULL,									NULL
727 	},
728 
729 	/*
730 	 * globalValue's (OIDs) from MWI-Operations-and-Errors
731 	 * {ccitt identified-organization etsi(0) 745 operations-and-errors(1)}
732 	 */
733 	{
734 		ROSE_ERROR_MWI_InvalidReceivingUserNr,		&rose_etsi_mwi, 10,
735 			NULL,									NULL
736 	},
737 	{
738 		ROSE_ERROR_MWI_ReceivingUserNotSubscribed,	&rose_etsi_mwi, 11,
739 			NULL,									NULL
740 	},
741 	{
742 		ROSE_ERROR_MWI_ControllingUserNotRegistered,&rose_etsi_mwi, 12,
743 			NULL,									NULL
744 	},
745 	{
746 		ROSE_ERROR_MWI_IndicationNotDelivered,		&rose_etsi_mwi, 13,
747 			NULL,									NULL
748 	},
749 	{
750 		ROSE_ERROR_MWI_MaxNumOfControllingUsersReached,&rose_etsi_mwi, 14,
751 			NULL,									NULL
752 	},
753 	{
754 		ROSE_ERROR_MWI_MaxNumOfActiveInstancesReached,&rose_etsi_mwi, 15,
755 			NULL,									NULL
756 	},
757 /* *INDENT-ON* */
758 };
759 
760 
761 /* ------------------------------------------------------------------- */
762 
763 
764 /*
765  * Note the first value in oid.values[] is really the first two
766  * OID subidentifiers.  They are compressed using this formula:
767  * First_Value = (First_Subidentifier * 40) + Second_Subidentifier
768  */
769 
770 /*! \brief ECMA private-isdn-signalling-domain prefix. */
771 static const struct asn1_oid rose_qsig_isdn_domain = {
772 /* *INDENT-OFF* */
773 	/* {iso(1) identified-organization(3) icd-ecma(12) private-isdn-signalling-domain(9)} */
774 	3, { 43, 12, 9 }
775 /* *INDENT-ON* */
776 };
777 
778 
779 /*! \brief Q.SIG specific invoke/result encode/decode message table */
780 static const struct rose_convert_msg rose_qsig_msgs[] = {
781 /* *INDENT-OFF* */
782 /*
783  *		operation,                                  oid_prefix, value,
784  *			encode_invoke_args,                     encode_result_args,
785  *			decode_invoke_args,                     decode_result_args
786  */
787 	/*
788 	 * localValue's from Q.SIG Name-Operations 4th edition
789 	 * { iso(1) standard(0) pss1-name(13868) name-operations(0) }
790 	 */
791 	{
792 		ROSE_QSIG_CallingName,						NULL, 0,
793 			rose_enc_qsig_CallingName_ARG,			NULL,
794 			rose_dec_qsig_CallingName_ARG,			NULL
795 	},
796 	{
797 		ROSE_QSIG_CalledName,						NULL, 1,
798 			rose_enc_qsig_CalledName_ARG,			NULL,
799 			rose_dec_qsig_CalledName_ARG,			NULL
800 	},
801 	{
802 		ROSE_QSIG_ConnectedName,					NULL, 2,
803 			rose_enc_qsig_ConnectedName_ARG,		NULL,
804 			rose_dec_qsig_ConnectedName_ARG,		NULL
805 	},
806 	{
807 		ROSE_QSIG_BusyName,							NULL, 3,
808 			rose_enc_qsig_BusyName_ARG,				NULL,
809 			rose_dec_qsig_BusyName_ARG,				NULL
810 	},
811 
812 	/*
813 	 * globalValue's (OIDs) from Q.SIG Name-Operations 2nd edition
814 	 * { iso(1) identified-organization(3) icd-ecma(12) standard(0) qsig-name(164) name-operations(0) }
815 	 *
816 	 * This older version of the Q.SIG switch is not supported.
817 	 * However, we will accept receiving these messages anyway.
818 	 */
819 	{
820 		ROSE_QSIG_CallingName,						&rose_qsig_isdn_domain, 0,
821 			rose_enc_qsig_CallingName_ARG,			NULL,
822 			rose_dec_qsig_CallingName_ARG,			NULL
823 	},
824 	{
825 		ROSE_QSIG_CalledName,						&rose_qsig_isdn_domain, 1,
826 			rose_enc_qsig_CalledName_ARG,			NULL,
827 			rose_dec_qsig_CalledName_ARG,			NULL
828 	},
829 	{
830 		ROSE_QSIG_ConnectedName,					&rose_qsig_isdn_domain, 2,
831 			rose_enc_qsig_ConnectedName_ARG,		NULL,
832 			rose_dec_qsig_ConnectedName_ARG,		NULL
833 	},
834 	{
835 		ROSE_QSIG_BusyName,							&rose_qsig_isdn_domain, 3,
836 			rose_enc_qsig_BusyName_ARG,				NULL,
837 			rose_dec_qsig_BusyName_ARG,				NULL
838 	},
839 
840 	/*
841 	 * localValue's from Q.SIG SS-AOC-Operations
842 	 * { iso(1) standard(0) pss1-advice-of-charge(15050) advice-of-charge-operations(0) }
843 	 */
844 	{
845 		ROSE_QSIG_ChargeRequest,					NULL, 59,
846 			rose_enc_qsig_ChargeRequest_ARG,		rose_enc_qsig_ChargeRequest_RES,
847 			rose_dec_qsig_ChargeRequest_ARG,		rose_dec_qsig_ChargeRequest_RES
848 	},
849 	{
850 		ROSE_QSIG_GetFinalCharge,					NULL, 60,
851 			rose_enc_qsig_DummyArg_ARG,				NULL,
852 			rose_dec_qsig_DummyArg_ARG,				NULL
853 	},
854 	{
855 		ROSE_QSIG_AocFinal,							NULL, 61,
856 			rose_enc_qsig_AocFinal_ARG,				NULL,
857 			rose_dec_qsig_AocFinal_ARG,				NULL
858 	},
859 	{
860 		ROSE_QSIG_AocInterim,						NULL, 62,
861 			rose_enc_qsig_AocInterim_ARG,			NULL,
862 			rose_dec_qsig_AocInterim_ARG,			NULL
863 	},
864 	{
865 		ROSE_QSIG_AocRate,							NULL, 63,
866 			rose_enc_qsig_AocRate_ARG,				NULL,
867 			rose_dec_qsig_AocRate_ARG,				NULL
868 	},
869 	{
870 		ROSE_QSIG_AocComplete,						NULL, 64,
871 			rose_enc_qsig_AocComplete_ARG,			rose_enc_qsig_AocComplete_RES,
872 			rose_dec_qsig_AocComplete_ARG,			rose_dec_qsig_AocComplete_RES
873 	},
874 	{
875 		ROSE_QSIG_AocDivChargeReq,					NULL, 65,
876 			rose_enc_qsig_AocDivChargeReq_ARG,		NULL,
877 			rose_dec_qsig_AocDivChargeReq_ARG,		NULL
878 	},
879 
880 	/*
881 	 * localValue's from Q.SIG Call-Transfer-Operations
882 	 * { iso(1) standard(0) pss1-call-transfer(13869) call-transfer-operations(0) }
883 	 */
884 	{
885 		ROSE_QSIG_CallTransferIdentify,				NULL, 7,
886 			rose_enc_qsig_DummyArg_ARG,				rose_enc_qsig_CallTransferIdentify_RES,
887 			rose_dec_qsig_DummyArg_ARG,				rose_dec_qsig_CallTransferIdentify_RES
888 	},
889 	{
890 		ROSE_QSIG_CallTransferAbandon,				NULL, 8,
891 			rose_enc_qsig_DummyArg_ARG,				NULL,
892 			rose_dec_qsig_DummyArg_ARG,				NULL
893 	},
894 	{
895 		ROSE_QSIG_CallTransferInitiate,				NULL, 9,
896 			rose_enc_qsig_CallTransferInitiate_ARG,	rose_enc_qsig_DummyRes_RES,
897 			rose_dec_qsig_CallTransferInitiate_ARG,	rose_dec_qsig_DummyRes_RES
898 	},
899 	{
900 		ROSE_QSIG_CallTransferSetup,				NULL, 10,
901 			rose_enc_qsig_CallTransferSetup_ARG,	rose_enc_qsig_DummyRes_RES,
902 			rose_dec_qsig_CallTransferSetup_ARG,	rose_dec_qsig_DummyRes_RES
903 	},
904 	{
905 		ROSE_QSIG_CallTransferActive,				NULL, 11,
906 			rose_enc_qsig_CallTransferActive_ARG,	NULL,
907 			rose_dec_qsig_CallTransferActive_ARG,	NULL
908 	},
909 	{
910 		ROSE_QSIG_CallTransferComplete,				NULL, 12,
911 			rose_enc_qsig_CallTransferComplete_ARG,	NULL,
912 			rose_dec_qsig_CallTransferComplete_ARG,	NULL
913 	},
914 	{
915 		ROSE_QSIG_CallTransferUpdate,				NULL, 13,
916 			rose_enc_qsig_CallTransferUpdate_ARG,	NULL,
917 			rose_dec_qsig_CallTransferUpdate_ARG,	NULL
918 	},
919 	{
920 		ROSE_QSIG_SubaddressTransfer,				NULL, 14,
921 			rose_enc_qsig_SubaddressTransfer_ARG,	NULL,
922 			rose_dec_qsig_SubaddressTransfer_ARG,	NULL
923 	},
924 
925 	/*
926 	 * NOTE:  I do not have the specification needed to fully support this
927 	 * message.  Fortunately, all I have to do for this message is to switch
928 	 * it to the bridged call leg for 2BCT support.
929 	 */
930 	{
931 		ROSE_QSIG_PathReplacement,					NULL, 4,
932 			NULL,									NULL,
933 			NULL,									NULL
934 	},
935 
936 	/*
937 	 * localValue's from Q.SIG Call-Diversion-Operations
938 	 * { iso(1) standard(0) pss1-call-diversion(13873) call-diversion-operations(0) }
939 	 */
940 	{
941 		ROSE_QSIG_ActivateDiversionQ,				NULL, 15,
942 			rose_enc_qsig_ActivateDiversionQ_ARG,	rose_enc_qsig_DummyRes_RES,
943 			rose_dec_qsig_ActivateDiversionQ_ARG,	rose_dec_qsig_DummyRes_RES
944 	},
945 	{
946 		ROSE_QSIG_DeactivateDiversionQ,				NULL, 16,
947 			rose_enc_qsig_DeactivateDiversionQ_ARG,	rose_enc_qsig_DummyRes_RES,
948 			rose_dec_qsig_DeactivateDiversionQ_ARG,	rose_dec_qsig_DummyRes_RES
949 	},
950 	{
951 		ROSE_QSIG_InterrogateDiversionQ,			NULL, 17,
952 			rose_enc_qsig_InterrogateDiversionQ_ARG,rose_enc_qsig_InterrogateDiversionQ_RES,
953 			rose_dec_qsig_InterrogateDiversionQ_ARG,rose_dec_qsig_InterrogateDiversionQ_RES
954 	},
955 	{
956 		ROSE_QSIG_CheckRestriction,					NULL, 18,
957 			rose_enc_qsig_CheckRestriction_ARG,		rose_enc_qsig_DummyRes_RES,
958 			rose_dec_qsig_CheckRestriction_ARG,		rose_dec_qsig_DummyRes_RES
959 	},
960 	{
961 		ROSE_QSIG_CallRerouting,					NULL, 19,
962 			rose_enc_qsig_CallRerouting_ARG,		rose_enc_qsig_DummyRes_RES,
963 			rose_dec_qsig_CallRerouting_ARG,		rose_dec_qsig_DummyRes_RES
964 	},
965 	{
966 		ROSE_QSIG_DivertingLegInformation1,			NULL, 20,
967 			rose_enc_qsig_DivertingLegInformation1_ARG,NULL,
968 			rose_dec_qsig_DivertingLegInformation1_ARG,NULL
969 	},
970 	{
971 		ROSE_QSIG_DivertingLegInformation2,			NULL, 21,
972 			rose_enc_qsig_DivertingLegInformation2_ARG,NULL,
973 			rose_dec_qsig_DivertingLegInformation2_ARG,NULL
974 	},
975 	{
976 		ROSE_QSIG_DivertingLegInformation3,			NULL, 22,
977 			rose_enc_qsig_DivertingLegInformation3_ARG,NULL,
978 			rose_dec_qsig_DivertingLegInformation3_ARG,NULL
979 	},
980 	{
981 		ROSE_QSIG_CfnrDivertedLegFailed,			NULL, 23,
982 			rose_enc_qsig_DummyArg_ARG,				NULL,
983 			rose_dec_qsig_DummyArg_ARG,				NULL
984 	},
985 
986 	/*
987 	 * localValue's from Q.SIG SS-CC-Operations
988 	 * { iso(1) standard(0) pss1-call-completion(13870) operations(0) }
989 	 */
990 	{
991 		ROSE_QSIG_CcbsRequest,						NULL, 40,
992 			rose_enc_qsig_CcbsRequest_ARG,			rose_enc_qsig_CcbsRequest_RES,
993 			rose_dec_qsig_CcbsRequest_ARG,			rose_dec_qsig_CcbsRequest_RES
994 	},
995 	{
996 		ROSE_QSIG_CcnrRequest,						NULL, 27,
997 			rose_enc_qsig_CcnrRequest_ARG,			rose_enc_qsig_CcnrRequest_RES,
998 			rose_dec_qsig_CcnrRequest_ARG,			rose_dec_qsig_CcnrRequest_RES
999 	},
1000 	{
1001 		ROSE_QSIG_CcCancel,							NULL, 28,
1002 			rose_enq_qsig_CcCancel_ARG,				NULL,
1003 			rose_dec_qsig_CcCancel_ARG,				NULL
1004 	},
1005 	{
1006 		ROSE_QSIG_CcExecPossible,					NULL, 29,
1007 			rose_enq_qsig_CcExecPossible_ARG,		NULL,
1008 			rose_dec_qsig_CcExecPossible_ARG,		NULL
1009 	},
1010 	{
1011 		ROSE_QSIG_CcPathReserve,					NULL, 30,
1012 			rose_enc_qsig_CcPathReserve_ARG,		rose_enc_qsig_CcPathReserve_RES,
1013 			rose_dec_qsig_CcPathReserve_ARG,		rose_dec_qsig_CcPathReserve_RES
1014 	},
1015 	{
1016 		ROSE_QSIG_CcRingout,						NULL, 31,
1017 			rose_enc_qsig_CcRingout_ARG,			NULL,
1018 			rose_dec_qsig_CcRingout_ARG,			NULL
1019 	},
1020 	{
1021 		ROSE_QSIG_CcSuspend,						NULL, 32,
1022 			rose_enc_qsig_CcSuspend_ARG,			NULL,
1023 			rose_dec_qsig_CcSuspend_ARG,			NULL
1024 	},
1025 	{
1026 		ROSE_QSIG_CcResume,							NULL, 33,
1027 			rose_enc_qsig_CcResume_ARG,				NULL,
1028 			rose_dec_qsig_CcResume_ARG,				NULL
1029 	},
1030 
1031 	/*
1032 	 * localValue's from Q.SIG SS-MWI-Operations
1033 	 * { iso(1) standard(0) pss1-message-waiting-indication(15506) message-waiting-operations(0) }
1034 	 */
1035 	{
1036 		ROSE_QSIG_MWIActivate,						NULL, 80,
1037 			rose_enc_qsig_MWIActivate_ARG,			rose_enc_qsig_DummyRes_RES,
1038 			rose_dec_qsig_MWIActivate_ARG,			rose_dec_qsig_DummyRes_RES
1039 	},
1040 	{
1041 		ROSE_QSIG_MWIDeactivate,					NULL, 81,
1042 			rose_enc_qsig_MWIDeactivate_ARG,		rose_enc_qsig_DummyRes_RES,
1043 			rose_dec_qsig_MWIDeactivate_ARG,		rose_dec_qsig_DummyRes_RES
1044 	},
1045 	{
1046 		ROSE_QSIG_MWIInterrogate,					NULL, 82,
1047 			rose_enc_qsig_MWIInterrogate_ARG,		rose_enc_qsig_MWIInterrogate_RES,
1048 			rose_dec_qsig_MWIInterrogate_ARG,		rose_dec_qsig_MWIInterrogate_RES
1049 	},
1050 /* *INDENT-ON* */
1051 };
1052 
1053 
1054 /*! \brief Q.SIG specific error-value converion table */
1055 static const struct rose_convert_error rose_qsig_errors[] = {
1056 /* *INDENT-OFF* */
1057 /*
1058  *		error-code,                                 oid_prefix, value
1059  *			encode_error_args,                      decode_error_args
1060  */
1061 	/*
1062 	 * localValue Errors from General-Error-List
1063 	 * {ccitt identified-organization q 950 general-error-list(1)}
1064 	 */
1065 	{
1066 		ROSE_ERROR_Gen_NotSubscribed,				NULL, 0,
1067 			NULL,									NULL
1068 	},
1069 	{
1070 		ROSE_ERROR_Gen_RejectedByNetwork,			NULL, 1,
1071 			NULL,									NULL
1072 	},
1073 	{
1074 		ROSE_ERROR_Gen_RejectedByUser,				NULL, 2,
1075 			NULL,									NULL
1076 	},
1077 	{
1078 		ROSE_ERROR_Gen_NotAvailable,				NULL, 3,
1079 			NULL,									NULL
1080 	},
1081 	{
1082 		ROSE_ERROR_Gen_InsufficientInformation,		NULL, 5,
1083 			NULL,									NULL
1084 	},
1085 	{
1086 		ROSE_ERROR_Gen_InvalidServedUserNr,			NULL, 6,
1087 			NULL,									NULL
1088 	},
1089 	{
1090 		ROSE_ERROR_Gen_InvalidCallState,			NULL, 7,
1091 			NULL,									NULL
1092 	},
1093 	{
1094 		ROSE_ERROR_Gen_BasicServiceNotProvided,		NULL, 8,
1095 			NULL,									NULL
1096 	},
1097 	{
1098 		ROSE_ERROR_Gen_NotIncomingCall,				NULL, 9,
1099 			NULL,									NULL
1100 	},
1101 	{
1102 		ROSE_ERROR_Gen_SupplementaryServiceInteractionNotAllowed,NULL, 10,
1103 			NULL,									NULL
1104 	},
1105 	{
1106 		ROSE_ERROR_Gen_ResourceUnavailable,			NULL, 11,
1107 			NULL,									NULL
1108 	},
1109 	{
1110 		ROSE_ERROR_Gen_CallFailure,					NULL, 25,
1111 			NULL,									NULL
1112 	},
1113 	{
1114 		ROSE_ERROR_Gen_ProceduralError,				NULL, 43,
1115 			NULL,									NULL
1116 	},
1117 
1118 	/*
1119 	 * From various Q.SIG specifications.
1120 	 * We will ignore the manufacturer specific extension information.
1121 	 */
1122 	{
1123 		ROSE_ERROR_QSIG_Unspecified,				NULL, 1008,
1124 			NULL,									NULL
1125 	},
1126 
1127 	/*
1128 	 * localValue Errors from Q.SIG SS-AOC-Operations
1129 	 * { iso(1) standard(0) pss1-advice-of-charge(15050) advice-of-charge-operations(0) }
1130 	 */
1131 	{
1132 		ROSE_ERROR_QSIG_AOC_FreeOfCharge,			NULL, 1016,
1133 			NULL,									NULL
1134 	},
1135 
1136 	/*
1137 	 * localValue's from Q.SIG Call-Transfer-Operations
1138 	 * { iso(1) standard(0) pss1-call-transfer(13869) call-transfer-operations(0) }
1139 	 */
1140 	{
1141 		ROSE_ERROR_QSIG_CT_InvalidReroutingNumber,	NULL, 1004,
1142 			NULL,									NULL
1143 	},
1144 	{
1145 		ROSE_ERROR_QSIG_CT_UnrecognizedCallIdentity,NULL, 1005,
1146 			NULL,									NULL
1147 	},
1148 	{
1149 		ROSE_ERROR_QSIG_CT_EstablishmentFailure,	NULL, 1006,
1150 			NULL,									NULL
1151 	},
1152 
1153 	/*
1154 	 * localValue's from Q.SIG Call-Diversion-Operations
1155 	 * { iso(1) standard(0) pss1-call-diversion(13873) call-diversion-operations(0) }
1156 	 */
1157 	{
1158 		ROSE_ERROR_Div_InvalidDivertedToNr,			NULL, 12,
1159 			NULL,									NULL
1160 	},
1161 	{
1162 		ROSE_ERROR_Div_SpecialServiceNr,			NULL, 14,
1163 			NULL,									NULL
1164 	},
1165 	{
1166 		ROSE_ERROR_Div_DiversionToServedUserNr,		NULL, 15,
1167 			NULL,									NULL
1168 	},
1169 	{
1170 		ROSE_ERROR_Div_NumberOfDiversionsExceeded,	NULL, 24,
1171 			NULL,									NULL
1172 	},
1173 	{
1174 		ROSE_ERROR_QSIG_Div_TemporarilyUnavailable,	NULL, 1000,
1175 			NULL,									NULL
1176 	},
1177 	{
1178 		ROSE_ERROR_QSIG_Div_NotAuthorized,			NULL, 1007,
1179 			NULL,									NULL
1180 	},
1181 
1182 	/*
1183 	 * localValue's from Q.SIG SS-CC-Operations
1184 	 * { iso(1) standard(0) pss1-call-completion(13870) operations(0) }
1185 	 */
1186 	{
1187 		ROSE_ERROR_QSIG_ShortTermRejection,			NULL, 1010,
1188 			NULL,									NULL
1189 	},
1190 	{
1191 		ROSE_ERROR_QSIG_LongTermRejection,			NULL, 1011,
1192 			NULL,									NULL
1193 	},
1194 	{
1195 		ROSE_ERROR_QSIG_RemoteUserBusyAgain,		NULL, 1012,
1196 			NULL,									NULL
1197 	},
1198 	{
1199 		ROSE_ERROR_QSIG_FailureToMatch,				NULL, 1013,
1200 			NULL,									NULL
1201 	},
1202 	{
1203 		ROSE_ERROR_QSIG_FailedDueToInterworking,	NULL, 1014,
1204 			NULL,									NULL
1205 	},
1206 
1207 	/*
1208 	 * localValue's from Q.SIG SS-MWI-Operations
1209 	 * { iso(1) standard(0) pss1-message-waiting-indication(15506) message-waiting-operations(0) }
1210 	 */
1211 	{
1212 		ROSE_ERROR_QSIG_InvalidMsgCentreId,			NULL, 1018,
1213 			NULL,									NULL
1214 	},
1215 /* *INDENT-ON* */
1216 };
1217 
1218 
1219 /* ------------------------------------------------------------------- */
1220 
1221 
1222 /*! \brief DMS-100 specific invoke/result encode/decode message table */
1223 static const struct rose_convert_msg rose_dms100_msgs[] = {
1224 /* *INDENT-OFF* */
1225 /*
1226  *		operation,                                  oid_prefix, value,
1227  *			encode_invoke_args,                     encode_result_args,
1228  *			decode_invoke_args,                     decode_result_args
1229  */
1230 	{
1231 		ROSE_DMS100_RLT_OperationInd,				NULL, ROSE_DMS100_RLT_OPERATION_IND,
1232 			NULL,									rose_enc_dms100_RLT_OperationInd_RES,
1233 			NULL,									rose_dec_dms100_RLT_OperationInd_RES
1234 	},
1235 	{
1236 		ROSE_DMS100_RLT_ThirdParty,					NULL, ROSE_DMS100_RLT_THIRD_PARTY,
1237 			rose_enc_dms100_RLT_ThirdParty_ARG,		NULL,
1238 			rose_dec_dms100_RLT_ThirdParty_ARG,		NULL
1239 	},
1240 
1241 	/* DMS-100 seems to have pirated some Q.SIG messages */
1242 	/*
1243 	 * localValue's from Q.SIG Name-Operations
1244 	 * { iso(1) standard(0) pss1-name(13868) name-operations(0) }
1245 	 */
1246 	{
1247 		ROSE_QSIG_CallingName,						NULL, 0,
1248 			rose_enc_qsig_CallingName_ARG,			NULL,
1249 			rose_dec_qsig_CallingName_ARG,			NULL
1250 	},
1251 #if 0	/* ROSE_DMS100_RLT_OPERATION_IND, and ROSE_DMS100_RLT_THIRD_PARTY conflict! */
1252 	{
1253 		ROSE_QSIG_CalledName,						NULL, 1,
1254 			rose_enc_qsig_CalledName_ARG,			NULL,
1255 			rose_dec_qsig_CalledName_ARG,			NULL
1256 	},
1257 	{
1258 		ROSE_QSIG_ConnectedName,					NULL, 2,
1259 			rose_enc_qsig_ConnectedName_ARG,		NULL,
1260 			rose_dec_qsig_ConnectedName_ARG,		NULL
1261 	},
1262 	{
1263 		ROSE_QSIG_BusyName,							NULL, 3,
1264 			rose_enc_qsig_BusyName_ARG,				NULL,
1265 			rose_dec_qsig_BusyName_ARG,				NULL
1266 	},
1267 #endif
1268 /* *INDENT-ON* */
1269 };
1270 
1271 
1272 /*! \brief DMS-100 specific error-value converion table */
1273 static const struct rose_convert_error rose_dms100_errors[] = {
1274 /* *INDENT-OFF* */
1275 /*
1276  *		error-code,                                 oid_prefix, value
1277  *			encode_error_args,                      decode_error_args
1278  */
1279 	{
1280 		ROSE_ERROR_DMS100_RLT_BridgeFail,			NULL, 0x10,
1281 			NULL,									NULL
1282 	},
1283 	{
1284 		ROSE_ERROR_DMS100_RLT_CallIDNotFound,		NULL, 0x11,
1285 			NULL,									NULL
1286 	},
1287 	{
1288 		ROSE_ERROR_DMS100_RLT_NotAllowed,			NULL, 0x12,
1289 			NULL,									NULL
1290 	},
1291 	{
1292 		ROSE_ERROR_DMS100_RLT_SwitchEquipCongs,		NULL, 0x13,
1293 			NULL,									NULL
1294 	},
1295 /* *INDENT-ON* */
1296 };
1297 
1298 
1299 /* ------------------------------------------------------------------- */
1300 
1301 
1302 /*
1303  * Note the first value in oid.values[] is really the first two
1304  * OID subidentifiers.  They are compressed using this formula:
1305  * First_Value = (First_Subidentifier * 40) + Second_Subidentifier
1306  */
1307 
1308 static const struct asn1_oid rose_ni2_oid = {
1309 /* *INDENT-OFF* */
1310 	/* { iso(1) member-body(2) usa(840) ansi-t1(10005) operations(0) } */
1311 	4, { 42, 840, 10005, 0 }
1312 /* *INDENT-ON* */
1313 };
1314 
1315 /*! \brief NI2 specific invoke/result encode/decode message table */
1316 static const struct rose_convert_msg rose_ni2_msgs[] = {
1317 /* *INDENT-OFF* */
1318 /*
1319  *		operation,                                  oid_prefix, value,
1320  *			encode_invoke_args,                     encode_result_args,
1321  *			decode_invoke_args,                     decode_result_args
1322  */
1323 	{
1324 		ROSE_NI2_InformationFollowing,				&rose_ni2_oid, 4,
1325 			rose_enc_ni2_InformationFollowing_ARG,	NULL,
1326 			rose_dec_ni2_InformationFollowing_ARG,	NULL
1327 	},
1328 
1329 	/* Also used by PRI_SWITCH_ATT4ESS and PRI_SWITCH_LUCENT5E */
1330 	{
1331 		ROSE_NI2_InitiateTransfer,					&rose_ni2_oid, 8,
1332 			rose_enc_ni2_InitiateTransfer_ARG,		NULL,
1333 			rose_dec_ni2_InitiateTransfer_ARG,		NULL
1334 	},
1335 
1336 	/* NI2 seems to have pirated several Q.SIG messages */
1337 	/*
1338 	 * localValue's from Q.SIG Name-Operations
1339 	 * { iso(1) standard(0) pss1-name(13868) name-operations(0) }
1340 	 */
1341 	{
1342 		ROSE_QSIG_CallingName,						NULL, 0,
1343 			rose_enc_qsig_CallingName_ARG,			NULL,
1344 			rose_dec_qsig_CallingName_ARG,			NULL
1345 	},
1346 	{
1347 		ROSE_QSIG_CalledName,						NULL, 1,
1348 			rose_enc_qsig_CalledName_ARG,			NULL,
1349 			rose_dec_qsig_CalledName_ARG,			NULL
1350 	},
1351 	{
1352 		ROSE_QSIG_ConnectedName,					NULL, 2,
1353 			rose_enc_qsig_ConnectedName_ARG,		NULL,
1354 			rose_dec_qsig_ConnectedName_ARG,		NULL
1355 	},
1356 	{
1357 		ROSE_QSIG_BusyName,							NULL, 3,
1358 			rose_enc_qsig_BusyName_ARG,				NULL,
1359 			rose_dec_qsig_BusyName_ARG,				NULL
1360 	},
1361 /* *INDENT-ON* */
1362 };
1363 
1364 
1365 /*! \brief NI2 specific error-value converion table */
1366 static const struct rose_convert_error rose_ni2_errors[] = {
1367 /* *INDENT-OFF* */
1368 /*
1369  *		error-code,                                 oid_prefix, value
1370  *			encode_error_args,                      decode_error_args
1371  */
1372 	/*
1373 	 * localValue Errors from General-Error-List
1374 	 * {ccitt identified-organization q 950 general-error-list(1)}
1375 	 */
1376 	{
1377 		ROSE_ERROR_Gen_NotSubscribed,				NULL, 0,
1378 			NULL,									NULL
1379 	},
1380 	{
1381 		ROSE_ERROR_Gen_RejectedByNetwork,			NULL, 1,
1382 			NULL,									NULL
1383 	},
1384 	{
1385 		ROSE_ERROR_Gen_RejectedByUser,				NULL, 2,
1386 			NULL,									NULL
1387 	},
1388 	{
1389 		ROSE_ERROR_Gen_NotAvailable,				NULL, 3,
1390 			NULL,									NULL
1391 	},
1392 	{
1393 		ROSE_ERROR_Gen_InsufficientInformation,		NULL, 5,
1394 			NULL,									NULL
1395 	},
1396 	{
1397 		ROSE_ERROR_Gen_InvalidServedUserNr,			NULL, 6,
1398 			NULL,									NULL
1399 	},
1400 	{
1401 		ROSE_ERROR_Gen_InvalidCallState,			NULL, 7,
1402 			NULL,									NULL
1403 	},
1404 	{
1405 		ROSE_ERROR_Gen_BasicServiceNotProvided,		NULL, 8,
1406 			NULL,									NULL
1407 	},
1408 	{
1409 		ROSE_ERROR_Gen_NotIncomingCall,				NULL, 9,
1410 			NULL,									NULL
1411 	},
1412 	{
1413 		ROSE_ERROR_Gen_SupplementaryServiceInteractionNotAllowed,NULL, 10,
1414 			NULL,									NULL
1415 	},
1416 	{
1417 		ROSE_ERROR_Gen_ResourceUnavailable,			NULL, 11,
1418 			NULL,									NULL
1419 	},
1420 	{
1421 		ROSE_ERROR_Gen_CallFailure,					NULL, 25,
1422 			NULL,									NULL
1423 	},
1424 	{
1425 		ROSE_ERROR_Gen_ProceduralError,				NULL, 43,
1426 			NULL,									NULL
1427 	},
1428 /* *INDENT-ON* */
1429 };
1430 
1431 
1432 /* ------------------------------------------------------------------- */
1433 
1434 /*!
1435  * \internal
1436  * \brief Convert the given code value to a string.
1437  *
1438  * \param code Code value to convert to a string.
1439  * \param arr Array to convert the code to a string.
1440  * \param num_elements Number of elements in the conversion array.
1441  *
1442  * \retval String version of the given code value.
1443  */
rose_code2str(int code,const struct rose_code_strings * arr,unsigned num_elements)1444 static const char *rose_code2str(int code, const struct rose_code_strings *arr,
1445 	unsigned num_elements)
1446 {
1447 	static char invalid_code[40];
1448 
1449 	unsigned index;
1450 
1451 	for (index = 0; index < num_elements; ++index) {
1452 		if (arr[index].code == code) {
1453 			return arr[index].name;
1454 		}
1455 	}
1456 
1457 	snprintf(invalid_code, sizeof(invalid_code), "Invalid code:%d 0x%X", code, code);
1458 	return invalid_code;
1459 }
1460 
1461 /*!
1462  * \brief Convert the given operation-value to a string.
1463  *
1464  * \param operation Operation-value to convert to a string.
1465  *
1466  * \retval String version of the given operation-value.
1467  */
rose_operation2str(enum rose_operation operation)1468 const char *rose_operation2str(enum rose_operation operation)
1469 {
1470 	static const struct rose_code_strings arr[] = {
1471 /* *INDENT-OFF* */
1472 		{ ROSE_None,                                "ROSE_None" },
1473 		{ ROSE_Unknown,                             "ROSE_Unknown" },
1474 
1475 		{ ROSE_ETSI_ActivationDiversion,            "ROSE_ETSI_ActivationDiversion" },
1476 		{ ROSE_ETSI_DeactivationDiversion,          "ROSE_ETSI_DeactivationDiversion" },
1477 		{ ROSE_ETSI_ActivationStatusNotificationDiv,"ROSE_ETSI_ActivationStatusNotificationDiv" },
1478 		{ ROSE_ETSI_DeactivationStatusNotificationDiv,"ROSE_ETSI_DeactivationStatusNotificationDiv" },
1479 		{ ROSE_ETSI_InterrogationDiversion,         "ROSE_ETSI_InterrogationDiversion" },
1480 		{ ROSE_ETSI_DiversionInformation,           "ROSE_ETSI_DiversionInformation" },
1481 		{ ROSE_ETSI_CallDeflection,                 "ROSE_ETSI_CallDeflection" },
1482 		{ ROSE_ETSI_CallRerouting,                  "ROSE_ETSI_CallRerouting" },
1483 		{ ROSE_ETSI_DivertingLegInformation2,       "ROSE_ETSI_DivertingLegInformation2" },
1484 		{ ROSE_ETSI_InterrogateServedUserNumbers,   "ROSE_ETSI_InterrogateServedUserNumbers" },
1485 		{ ROSE_ETSI_DivertingLegInformation1,       "ROSE_ETSI_DivertingLegInformation1" },
1486 		{ ROSE_ETSI_DivertingLegInformation3,       "ROSE_ETSI_DivertingLegInformation3" },
1487 
1488 		{ ROSE_ETSI_EctExecute,                     "ROSE_ETSI_EctExecute" },
1489 		{ ROSE_ETSI_ExplicitEctExecute,             "ROSE_ETSI_ExplicitEctExecute" },
1490 		{ ROSE_ETSI_RequestSubaddress,              "ROSE_ETSI_RequestSubaddress" },
1491 		{ ROSE_ETSI_SubaddressTransfer,             "ROSE_ETSI_SubaddressTransfer" },
1492 		{ ROSE_ETSI_EctLinkIdRequest,               "ROSE_ETSI_EctLinkIdRequest" },
1493 		{ ROSE_ETSI_EctInform,                      "ROSE_ETSI_EctInform" },
1494 		{ ROSE_ETSI_EctLoopTest,                    "ROSE_ETSI_EctLoopTest" },
1495 
1496 		{ ROSE_ETSI_ChargingRequest,                "ROSE_ETSI_ChargingRequest" },
1497 		{ ROSE_ETSI_AOCSCurrency,                   "ROSE_ETSI_AOCSCurrency" },
1498 		{ ROSE_ETSI_AOCSSpecialArr,                 "ROSE_ETSI_AOCSSpecialArr" },
1499 		{ ROSE_ETSI_AOCDCurrency,                   "ROSE_ETSI_AOCDCurrency" },
1500 		{ ROSE_ETSI_AOCDChargingUnit,               "ROSE_ETSI_AOCDChargingUnit" },
1501 		{ ROSE_ETSI_AOCECurrency,                   "ROSE_ETSI_AOCECurrency" },
1502 		{ ROSE_ETSI_AOCEChargingUnit,               "ROSE_ETSI_AOCEChargingUnit" },
1503 
1504 		{ ROSE_ETSI_StatusRequest,                  "ROSE_ETSI_StatusRequest" },
1505 
1506 		{ ROSE_ETSI_CallInfoRetain,                 "ROSE_ETSI_CallInfoRetain" },
1507 		{ ROSE_ETSI_EraseCallLinkageID,             "ROSE_ETSI_EraseCallLinkageID" },
1508 		{ ROSE_ETSI_CCBSDeactivate,                 "ROSE_ETSI_CCBSDeactivate" },
1509 		{ ROSE_ETSI_CCBSErase,                      "ROSE_ETSI_CCBSErase" },
1510 		{ ROSE_ETSI_CCBSRemoteUserFree,             "ROSE_ETSI_CCBSRemoteUserFree" },
1511 		{ ROSE_ETSI_CCBSCall,                       "ROSE_ETSI_CCBSCall" },
1512 		{ ROSE_ETSI_CCBSStatusRequest,              "ROSE_ETSI_CCBSStatusRequest" },
1513 		{ ROSE_ETSI_CCBSBFree,                      "ROSE_ETSI_CCBSBFree" },
1514 		{ ROSE_ETSI_CCBSStopAlerting,               "ROSE_ETSI_CCBSStopAlerting" },
1515 
1516 		{ ROSE_ETSI_CCBSRequest,                    "ROSE_ETSI_CCBSRequest" },
1517 		{ ROSE_ETSI_CCBSInterrogate,                "ROSE_ETSI_CCBSInterrogate" },
1518 
1519 		{ ROSE_ETSI_CCNRRequest,                    "ROSE_ETSI_CCNRRequest" },
1520 		{ ROSE_ETSI_CCNRInterrogate,                "ROSE_ETSI_CCNRInterrogate" },
1521 
1522 		{ ROSE_ETSI_CCBS_T_Call,                    "ROSE_ETSI_CCBS_T_Call" },
1523 		{ ROSE_ETSI_CCBS_T_Suspend,                 "ROSE_ETSI_CCBS_T_Suspend" },
1524 		{ ROSE_ETSI_CCBS_T_Resume,                  "ROSE_ETSI_CCBS_T_Resume" },
1525 		{ ROSE_ETSI_CCBS_T_RemoteUserFree,          "ROSE_ETSI_CCBS_T_RemoteUserFree" },
1526 		{ ROSE_ETSI_CCBS_T_Available,               "ROSE_ETSI_CCBS_T_Available" },
1527 
1528 		{ ROSE_ETSI_CCBS_T_Request,                 "ROSE_ETSI_CCBS_T_Request" },
1529 
1530 		{ ROSE_ETSI_CCNR_T_Request,                 "ROSE_ETSI_CCNR_T_Request" },
1531 
1532 		{ ROSE_ETSI_MCIDRequest,                    "ROSE_ETSI_MCIDRequest" },
1533 
1534 		{ ROSE_ETSI_MWIActivate,                    "ROSE_ETSI_MWIActivate" },
1535 		{ ROSE_ETSI_MWIDeactivate,                  "ROSE_ETSI_MWIDeactivate" },
1536 		{ ROSE_ETSI_MWIIndicate,                    "ROSE_ETSI_MWIIndicate" },
1537 
1538 		{ ROSE_QSIG_CallingName,                    "ROSE_QSIG_CallingName" },
1539 		{ ROSE_QSIG_CalledName,                     "ROSE_QSIG_CalledName" },
1540 		{ ROSE_QSIG_ConnectedName,                  "ROSE_QSIG_ConnectedName" },
1541 		{ ROSE_QSIG_BusyName,                       "ROSE_QSIG_BusyName" },
1542 
1543 		{ ROSE_QSIG_ChargeRequest,                  "ROSE_QSIG_ChargeRequest" },
1544 		{ ROSE_QSIG_GetFinalCharge,                 "ROSE_QSIG_GetFinalCharge" },
1545 		{ ROSE_QSIG_AocFinal,                       "ROSE_QSIG_AocFinal" },
1546 		{ ROSE_QSIG_AocInterim,                     "ROSE_QSIG_AocInterim" },
1547 		{ ROSE_QSIG_AocRate,                        "ROSE_QSIG_AocRate" },
1548 		{ ROSE_QSIG_AocComplete,                    "ROSE_QSIG_AocComplete" },
1549 		{ ROSE_QSIG_AocDivChargeReq,                "ROSE_QSIG_AocDivChargeReq" },
1550 
1551 		{ ROSE_QSIG_CallTransferIdentify,           "ROSE_QSIG_CallTransferIdentify" },
1552 		{ ROSE_QSIG_CallTransferAbandon,            "ROSE_QSIG_CallTransferAbandon" },
1553 		{ ROSE_QSIG_CallTransferInitiate,           "ROSE_QSIG_CallTransferInitiate" },
1554 		{ ROSE_QSIG_CallTransferSetup,              "ROSE_QSIG_CallTransferSetup" },
1555 		{ ROSE_QSIG_CallTransferActive,             "ROSE_QSIG_CallTransferActive" },
1556 		{ ROSE_QSIG_CallTransferComplete,           "ROSE_QSIG_CallTransferComplete" },
1557 		{ ROSE_QSIG_CallTransferUpdate,             "ROSE_QSIG_CallTransferUpdate" },
1558 		{ ROSE_QSIG_SubaddressTransfer,             "ROSE_QSIG_SubaddressTransfer" },
1559 
1560 		{ ROSE_QSIG_PathReplacement,                "ROSE_QSIG_PathReplacement" },
1561 
1562 		{ ROSE_QSIG_ActivateDiversionQ,             "ROSE_QSIG_ActivateDiversionQ" },
1563 		{ ROSE_QSIG_DeactivateDiversionQ,           "ROSE_QSIG_DeactivateDiversionQ" },
1564 		{ ROSE_QSIG_InterrogateDiversionQ,          "ROSE_QSIG_InterrogateDiversionQ" },
1565 		{ ROSE_QSIG_CheckRestriction,               "ROSE_QSIG_CheckRestriction" },
1566 		{ ROSE_QSIG_CallRerouting,                  "ROSE_QSIG_CallRerouting" },
1567 		{ ROSE_QSIG_DivertingLegInformation1,       "ROSE_QSIG_DivertingLegInformation1" },
1568 		{ ROSE_QSIG_DivertingLegInformation2,       "ROSE_QSIG_DivertingLegInformation2" },
1569 		{ ROSE_QSIG_DivertingLegInformation3,       "ROSE_QSIG_DivertingLegInformation3" },
1570 		{ ROSE_QSIG_CfnrDivertedLegFailed,          "ROSE_QSIG_CfnrDivertedLegFailed" },
1571 
1572 		{ ROSE_QSIG_CcbsRequest,                    "ROSE_QSIG_CcbsRequest" },
1573 		{ ROSE_QSIG_CcnrRequest,                    "ROSE_QSIG_CcnrRequest" },
1574 		{ ROSE_QSIG_CcCancel,                       "ROSE_QSIG_CcCancel" },
1575 		{ ROSE_QSIG_CcExecPossible,                 "ROSE_QSIG_CcExecPossible" },
1576 		{ ROSE_QSIG_CcPathReserve,                  "ROSE_QSIG_CcPathReserve" },
1577 		{ ROSE_QSIG_CcRingout,                      "ROSE_QSIG_CcRingout" },
1578 		{ ROSE_QSIG_CcSuspend,                      "ROSE_QSIG_CcSuspend" },
1579 		{ ROSE_QSIG_CcResume,                       "ROSE_QSIG_CcResume" },
1580 
1581 		{ ROSE_QSIG_MWIActivate,                    "ROSE_QSIG_MWIActivate" },
1582 		{ ROSE_QSIG_MWIDeactivate,                  "ROSE_QSIG_MWIDeactivate" },
1583 		{ ROSE_QSIG_MWIInterrogate,                 "ROSE_QSIG_MWIInterrogate" },
1584 
1585 		{ ROSE_DMS100_RLT_OperationInd,             "ROSE_DMS100_RLT_OperationInd" },
1586 		{ ROSE_DMS100_RLT_ThirdParty,               "ROSE_DMS100_RLT_ThirdParty" },
1587 
1588 		{ ROSE_NI2_InformationFollowing,            "ROSE_NI2_InformationFollowing" },
1589 		{ ROSE_NI2_InitiateTransfer,                "ROSE_NI2_InitiateTransfer" },
1590 /* *INDENT-ON* */
1591 	};
1592 
1593 	return rose_code2str(operation, arr, ARRAY_LEN(arr));
1594 }
1595 
1596 /*!
1597  * \brief Convert the given error-value to a string.
1598  *
1599  * \param code Error-value to convert to a string.
1600  *
1601  * \retval String version of the given error-value.
1602  */
rose_error2str(enum rose_error_code code)1603 const char *rose_error2str(enum rose_error_code code)
1604 {
1605 	static const struct rose_code_strings arr[] = {
1606 /* *INDENT-OFF* */
1607 		{ ROSE_ERROR_None,                            "No error occurred" },
1608 		{ ROSE_ERROR_Unknown,                         "Unknown error-value code" },
1609 
1610 		{ ROSE_ERROR_Gen_NotSubscribed,               "General: Not Subscribed" },
1611 		{ ROSE_ERROR_Gen_NotAvailable,                "General: Not Available" },
1612 		{ ROSE_ERROR_Gen_NotImplemented,              "General: Not Implemented" },
1613 		{ ROSE_ERROR_Gen_InvalidServedUserNr,         "General: Invalid Served User Number" },
1614 		{ ROSE_ERROR_Gen_InvalidCallState,            "General: Invalid Call State" },
1615 		{ ROSE_ERROR_Gen_BasicServiceNotProvided,     "General: Basic Service Not Provided" },
1616 		{ ROSE_ERROR_Gen_NotIncomingCall,             "General: Not Incoming Call" },
1617 		{ ROSE_ERROR_Gen_SupplementaryServiceInteractionNotAllowed,"General: Supplementary Service Interaction Not Allowed" },
1618 		{ ROSE_ERROR_Gen_ResourceUnavailable,         "General: Resource Unavailable" },
1619 
1620 		/* Additional Q.950 General-Errors for Q.SIG */
1621 		{ ROSE_ERROR_Gen_RejectedByNetwork,           "General: Rejected By Network" },
1622 		{ ROSE_ERROR_Gen_RejectedByUser,              "General: Rejected By User" },
1623 		{ ROSE_ERROR_Gen_InsufficientInformation,     "General: Insufficient Information" },
1624 		{ ROSE_ERROR_Gen_CallFailure,                 "General: Call Failure" },
1625 		{ ROSE_ERROR_Gen_ProceduralError,             "General: Procedural Error" },
1626 
1627 		{ ROSE_ERROR_Div_InvalidDivertedToNr,         "Diversion: Invalid Diverted To Number" },
1628 		{ ROSE_ERROR_Div_SpecialServiceNr,            "Diversion: Special Service Number" },
1629 		{ ROSE_ERROR_Div_DiversionToServedUserNr,     "Diversion: Diversion To Served User Number" },
1630 		{ ROSE_ERROR_Div_IncomingCallAccepted,        "Diversion: Incoming Call Accepted" },
1631 		{ ROSE_ERROR_Div_NumberOfDiversionsExceeded,  "Diversion: Number Of Diversions Exceeded" },
1632 		{ ROSE_ERROR_Div_NotActivated,                "Diversion: Not Activated" },
1633 		{ ROSE_ERROR_Div_RequestAlreadyAccepted,      "Diversion: Request Already Accepted" },
1634 
1635 		{ ROSE_ERROR_AOC_NoChargingInfoAvailable,     "AOC: No Charging Info Available" },
1636 
1637 		{ ROSE_ERROR_ECT_LinkIdNotAssignedByNetwork,  "ECT: Link ID Not Assigned By Network" },
1638 
1639 		{ ROSE_ERROR_CCBS_InvalidCallLinkageID,       "CCBS: Invalid Call Linkage ID" },
1640 		{ ROSE_ERROR_CCBS_InvalidCCBSReference,       "CCBS: Invalid CCBS Reference" },
1641 		{ ROSE_ERROR_CCBS_LongTermDenial,             "CCBS: Long Term Denial" },
1642 		{ ROSE_ERROR_CCBS_ShortTermDenial,            "CCBS: Short Term Denial" },
1643 		{ ROSE_ERROR_CCBS_IsAlreadyActivated,         "CCBS: Is Already Activated" },
1644 		{ ROSE_ERROR_CCBS_AlreadyAccepted,            "CCBS: Already Accepted" },
1645 		{ ROSE_ERROR_CCBS_OutgoingCCBSQueueFull,      "CCBS: Outgoing CCBS Queue Full" },
1646 		{ ROSE_ERROR_CCBS_CallFailureReasonNotBusy,   "CCBS: Call Failure Reason Not Busy" },
1647 		{ ROSE_ERROR_CCBS_NotReadyForCall,            "CCBS: Not Ready For Call" },
1648 
1649 		{ ROSE_ERROR_CCBS_T_LongTermDenial,           "CCBS-T: Long Term Denial" },
1650 		{ ROSE_ERROR_CCBS_T_ShortTermDenial,          "CCBS-T: Short Term Denial" },
1651 
1652 		{ ROSE_ERROR_MWI_InvalidReceivingUserNr,      "MWI: Invalid Receiving User Number" },
1653 		{ ROSE_ERROR_MWI_ReceivingUserNotSubscribed,  "MWI: Receiving User Not Subscribed" },
1654 		{ ROSE_ERROR_MWI_ControllingUserNotRegistered,"MWI: Controlling User Not Registered" },
1655 		{ ROSE_ERROR_MWI_IndicationNotDelivered,      "MWI: Indication Not Delivered" },
1656 		{ ROSE_ERROR_MWI_MaxNumOfControllingUsersReached,"MWI: Max Num Of Controlling Users Reached" },
1657 		{ ROSE_ERROR_MWI_MaxNumOfActiveInstancesReached,"MWI: Max Num Of Active Instances Reached" },
1658 
1659 		/* Q.SIG specific errors */
1660 		{ ROSE_ERROR_QSIG_Unspecified,                "Unspecified" },
1661 
1662 		{ ROSE_ERROR_QSIG_AOC_FreeOfCharge,           "AOC: FreeOfCharge" },
1663 
1664 		{ ROSE_ERROR_QSIG_CT_InvalidReroutingNumber,  "CT: Invalid Rerouting Number" },
1665 		{ ROSE_ERROR_QSIG_CT_UnrecognizedCallIdentity,"CT: Unrecognized Call Identity" },
1666 		{ ROSE_ERROR_QSIG_CT_EstablishmentFailure,    "CT: Establishment Failure" },
1667 
1668 		{ ROSE_ERROR_QSIG_Div_TemporarilyUnavailable, "Diversion: Temporarily Unavailable" },
1669 		{ ROSE_ERROR_QSIG_Div_NotAuthorized,          "Diversion: Not Authorized" },
1670 
1671 		{ ROSE_ERROR_QSIG_ShortTermRejection,         "CC: Short Term Rejection" },
1672 		{ ROSE_ERROR_QSIG_LongTermRejection,          "CC: Long Term Rejection" },
1673 		{ ROSE_ERROR_QSIG_RemoteUserBusyAgain,        "CC: Remote User Busy Again" },
1674 		{ ROSE_ERROR_QSIG_FailureToMatch,             "CC: Failure To Match" },
1675 		{ ROSE_ERROR_QSIG_FailedDueToInterworking,    "CC: Failed Due To Interworking" },
1676 
1677 		{ ROSE_ERROR_QSIG_InvalidMsgCentreId,         "MWI: Invalid Message Center ID" },
1678 
1679 		/* DMS-100 specific errors */
1680 		{ ROSE_ERROR_DMS100_RLT_BridgeFail,           "RLT: Bridge Fail" },
1681 		{ ROSE_ERROR_DMS100_RLT_CallIDNotFound,       "RLT: Call ID Not Found" },
1682 		{ ROSE_ERROR_DMS100_RLT_NotAllowed,           "RLT: Not Allowed" },
1683 		{ ROSE_ERROR_DMS100_RLT_SwitchEquipCongs,     "RLT: Switch Equip Congs" },
1684 /* *INDENT-ON* */
1685 	};
1686 
1687 	return rose_code2str(code, arr, ARRAY_LEN(arr));
1688 }
1689 
1690 /*!
1691  * \brief Convert the given reject problem-value to a string.
1692  *
1693  * \param code Reject problem-value to convert to a string.
1694  *
1695  * \retval String version of the given reject problem-value.
1696  */
rose_reject2str(enum rose_reject_code code)1697 const char *rose_reject2str(enum rose_reject_code code)
1698 {
1699 	static const struct rose_code_strings arr[] = {
1700 /* *INDENT-OFF* */
1701 		{ ROSE_REJECT_None,                           "No reject occurred" },
1702 		{ ROSE_REJECT_Unknown,                        "Unknown reject code" },
1703 
1704 		{ ROSE_REJECT_Gen_UnrecognizedComponent,      "General: Unrecognized Component" },
1705 		{ ROSE_REJECT_Gen_MistypedComponent,          "General: Mistyped Component" },
1706 		{ ROSE_REJECT_Gen_BadlyStructuredComponent,   "General: Badly Structured Component" },
1707 
1708 		{ ROSE_REJECT_Inv_DuplicateInvocation,        "Invoke: Duplicate Invocation" },
1709 		{ ROSE_REJECT_Inv_UnrecognizedOperation,      "Invoke: Unrecognized Operation" },
1710 		{ ROSE_REJECT_Inv_MistypedArgument,           "Invoke: Mistyped Argument" },
1711 		{ ROSE_REJECT_Inv_ResourceLimitation,         "Invoke: Resource Limitation" },
1712 		{ ROSE_REJECT_Inv_InitiatorReleasing,         "Invoke: Initiator Releasing" },
1713 		{ ROSE_REJECT_Inv_UnrecognizedLinkedID,       "Invoke: Unrecognized Linked ID" },
1714 		{ ROSE_REJECT_Inv_LinkedResponseUnexpected,   "Invoke: Linked Response Unexpected" },
1715 		{ ROSE_REJECT_Inv_UnexpectedChildOperation,   "Invoke: Unexpected Child Operation" },
1716 
1717 		{ ROSE_REJECT_Res_UnrecognizedInvocation,     "Result: Unrecognized Invocation" },
1718 		{ ROSE_REJECT_Res_ResultResponseUnexpected,   "Result: Result Response Unexpected" },
1719 		{ ROSE_REJECT_Res_MistypedResult,             "Result: Mistyped Result" },
1720 
1721 		{ ROSE_REJECT_Err_UnrecognizedInvocation,     "Error: Unrecognized Invocation" },
1722 		{ ROSE_REJECT_Err_ErrorResponseUnexpected,    "Error: Error Response Unexpected" },
1723 		{ ROSE_REJECT_Err_UnrecognizedError,          "Error: Unrecognized Error" },
1724 		{ ROSE_REJECT_Err_UnexpectedError,            "Error: Unexpected Error" },
1725 		{ ROSE_REJECT_Err_MistypedParameter,          "Error: Mistyped Parameter" },
1726 /* *INDENT-ON* */
1727 	};
1728 
1729 	return rose_code2str(code, arr, ARRAY_LEN(arr));
1730 }
1731 
1732 /*!
1733  * \internal
1734  * \brief Find an operation message conversion entry using the operation code.
1735  *
1736  * \param ctrl D channel controller for diagnostic messages or global options.
1737  * \param operation Library operation-value code.
1738  *
1739  * \retval Message conversion entry on success.
1740  * \retval NULL on error.
1741  */
rose_find_msg_by_op_code(struct pri * ctrl,enum rose_operation operation)1742 static const struct rose_convert_msg *rose_find_msg_by_op_code(struct pri *ctrl,
1743 	enum rose_operation operation)
1744 {
1745 	const struct rose_convert_msg *found;
1746 	const struct rose_convert_msg *table;
1747 	size_t num_entries;
1748 	size_t index;
1749 
1750 	/* Determine which message conversion table to use */
1751 	switch (ctrl->switchtype) {
1752 	case PRI_SWITCH_EUROISDN_T1:
1753 	case PRI_SWITCH_EUROISDN_E1:
1754 		table = rose_etsi_msgs;
1755 		num_entries = ARRAY_LEN(rose_etsi_msgs);
1756 		break;
1757 	case PRI_SWITCH_QSIG:
1758 		table = rose_qsig_msgs;
1759 		num_entries = ARRAY_LEN(rose_qsig_msgs);
1760 		break;
1761 	case PRI_SWITCH_DMS100:
1762 		table = rose_dms100_msgs;
1763 		num_entries = ARRAY_LEN(rose_dms100_msgs);
1764 		break;
1765 	case PRI_SWITCH_ATT4ESS:
1766 	case PRI_SWITCH_LUCENT5E:
1767 	case PRI_SWITCH_NI2:
1768 		table = rose_ni2_msgs;
1769 		num_entries = ARRAY_LEN(rose_ni2_msgs);
1770 		break;
1771 	default:
1772 		return NULL;
1773 	}
1774 
1775 	/* Search for the table entry */
1776 	found = NULL;
1777 	for (index = 0; index < num_entries; ++index) {
1778 		if (table[index].operation == operation) {
1779 			found = &table[index];
1780 			break;
1781 		}
1782 	}
1783 
1784 	return found;
1785 }
1786 
1787 /*!
1788  * \internal
1789  * \brief Find an operation message conversion entry using the
1790  * operation-value OID value or localValue.
1791  *
1792  * \param ctrl D channel controller for diagnostic messages or global options.
1793  * \param oid Search for the full OID if not NULL.
1794  * \param local Search for the localValue if OID is NULL.
1795  *
1796  * \retval Message conversion entry on success.
1797  * \retval NULL on error.
1798  */
rose_find_msg_by_op_val(struct pri * ctrl,const struct asn1_oid * oid,unsigned local)1799 static const struct rose_convert_msg *rose_find_msg_by_op_val(struct pri *ctrl,
1800 	const struct asn1_oid *oid, unsigned local)
1801 {
1802 	const struct rose_convert_msg *found;
1803 	const struct rose_convert_msg *table;
1804 	size_t num_entries;
1805 	size_t index;
1806 	int sub_index;
1807 
1808 	/* Determine which message conversion table to use */
1809 	switch (ctrl->switchtype) {
1810 	case PRI_SWITCH_EUROISDN_T1:
1811 	case PRI_SWITCH_EUROISDN_E1:
1812 		table = rose_etsi_msgs;
1813 		num_entries = ARRAY_LEN(rose_etsi_msgs);
1814 		break;
1815 	case PRI_SWITCH_QSIG:
1816 		table = rose_qsig_msgs;
1817 		num_entries = ARRAY_LEN(rose_qsig_msgs);
1818 		break;
1819 	case PRI_SWITCH_DMS100:
1820 		table = rose_dms100_msgs;
1821 		num_entries = ARRAY_LEN(rose_dms100_msgs);
1822 		break;
1823 	case PRI_SWITCH_ATT4ESS:
1824 	case PRI_SWITCH_LUCENT5E:
1825 	case PRI_SWITCH_NI2:
1826 		table = rose_ni2_msgs;
1827 		num_entries = ARRAY_LEN(rose_ni2_msgs);
1828 		break;
1829 	default:
1830 		return NULL;
1831 	}
1832 
1833 	/* Search for the table entry */
1834 	found = NULL;
1835 	if (oid) {
1836 		/* Search for an OID entry */
1837 		local = oid->value[oid->num_values - 1];
1838 		for (index = 0; index < num_entries; ++index) {
1839 			if (table[index].value == local && table[index].oid_prefix
1840 				&& table[index].oid_prefix->num_values == oid->num_values - 1) {
1841 				/* Now lets match the OID prefix subidentifiers */
1842 				for (sub_index = oid->num_values - 2; 0 <= sub_index; --sub_index) {
1843 					if (oid->value[sub_index]
1844 						!= table[index].oid_prefix->value[sub_index]) {
1845 						break;
1846 					}
1847 				}
1848 				if (sub_index == -1) {
1849 					/* All of the OID subidentifiers matched */
1850 					found = &table[index];
1851 					break;
1852 				}
1853 			}
1854 		}
1855 	} else {
1856 		/* Search for a localValue entry */
1857 		for (index = 0; index < num_entries; ++index) {
1858 			if (table[index].value == local && !table[index].oid_prefix) {
1859 				found = &table[index];
1860 				break;
1861 			}
1862 		}
1863 	}
1864 
1865 	return found;
1866 }
1867 
1868 /*!
1869  * \internal
1870  * \brief Find an error conversion entry using the error code.
1871  *
1872  * \param ctrl D channel controller for diagnostic messages or global options.
1873  * \param code Library error-value code.
1874  *
1875  * \retval Error conversion entry on success.
1876  * \retval NULL on error.
1877  */
rose_find_error_by_op_code(struct pri * ctrl,enum rose_error_code code)1878 static const struct rose_convert_error *rose_find_error_by_op_code(struct pri *ctrl,
1879 	enum rose_error_code code)
1880 {
1881 	const struct rose_convert_error *found;
1882 	const struct rose_convert_error *table;
1883 	size_t num_entries;
1884 	size_t index;
1885 
1886 	/* Determine which error conversion table to use */
1887 	switch (ctrl->switchtype) {
1888 	case PRI_SWITCH_EUROISDN_T1:
1889 	case PRI_SWITCH_EUROISDN_E1:
1890 		table = rose_etsi_errors;
1891 		num_entries = ARRAY_LEN(rose_etsi_errors);
1892 		break;
1893 	case PRI_SWITCH_QSIG:
1894 		table = rose_qsig_errors;
1895 		num_entries = ARRAY_LEN(rose_qsig_errors);
1896 		break;
1897 	case PRI_SWITCH_DMS100:
1898 		table = rose_dms100_errors;
1899 		num_entries = ARRAY_LEN(rose_dms100_errors);
1900 		break;
1901 	case PRI_SWITCH_ATT4ESS:
1902 	case PRI_SWITCH_LUCENT5E:
1903 	case PRI_SWITCH_NI2:
1904 		table = rose_ni2_errors;
1905 		num_entries = ARRAY_LEN(rose_ni2_errors);
1906 		break;
1907 	default:
1908 		return NULL;
1909 	}
1910 
1911 	/* Search for the table entry */
1912 	found = NULL;
1913 	for (index = 0; index < num_entries; ++index) {
1914 		if (table[index].code == code) {
1915 			found = &table[index];
1916 			break;
1917 		}
1918 	}
1919 
1920 	return found;
1921 }
1922 
1923 /*!
1924  * \internal
1925  * \brief Find an error conversion entry using the
1926  * error-value OID value or localValue.
1927  *
1928  * \param ctrl D channel controller for diagnostic messages or global options.
1929  * \param oid Search for the full OID if not NULL.
1930  * \param local Search for the localValue if OID is NULL.
1931  *
1932  * \retval Error conversion entry on success.
1933  * \retval NULL on error.
1934  */
rose_find_error_by_op_val(struct pri * ctrl,const struct asn1_oid * oid,unsigned local)1935 static const struct rose_convert_error *rose_find_error_by_op_val(struct pri *ctrl,
1936 	const struct asn1_oid *oid, unsigned local)
1937 {
1938 	const struct rose_convert_error *found;
1939 	const struct rose_convert_error *table;
1940 	size_t num_entries;
1941 	size_t index;
1942 	int sub_index;
1943 
1944 	/* Determine which error conversion table to use */
1945 	switch (ctrl->switchtype) {
1946 	case PRI_SWITCH_EUROISDN_T1:
1947 	case PRI_SWITCH_EUROISDN_E1:
1948 		table = rose_etsi_errors;
1949 		num_entries = ARRAY_LEN(rose_etsi_errors);
1950 		break;
1951 	case PRI_SWITCH_QSIG:
1952 		table = rose_qsig_errors;
1953 		num_entries = ARRAY_LEN(rose_qsig_errors);
1954 		break;
1955 	case PRI_SWITCH_DMS100:
1956 		table = rose_dms100_errors;
1957 		num_entries = ARRAY_LEN(rose_dms100_errors);
1958 		break;
1959 	case PRI_SWITCH_ATT4ESS:
1960 	case PRI_SWITCH_LUCENT5E:
1961 	case PRI_SWITCH_NI2:
1962 		table = rose_ni2_errors;
1963 		num_entries = ARRAY_LEN(rose_ni2_errors);
1964 		break;
1965 	default:
1966 		return NULL;
1967 	}
1968 
1969 	/* Search for the table entry */
1970 	found = NULL;
1971 	if (oid) {
1972 		/* Search for an OID entry */
1973 		local = oid->value[oid->num_values - 1];
1974 		for (index = 0; index < num_entries; ++index) {
1975 			if (table[index].value == local && table[index].oid_prefix
1976 				&& table[index].oid_prefix->num_values == oid->num_values - 1) {
1977 				/* Now lets match the OID prefix subidentifiers */
1978 				for (sub_index = oid->num_values - 2; 0 <= sub_index; --sub_index) {
1979 					if (oid->value[sub_index]
1980 						!= table[index].oid_prefix->value[sub_index]) {
1981 						break;
1982 					}
1983 				}
1984 				if (sub_index == -1) {
1985 					/* All of the OID subidentifiers matched */
1986 					found = &table[index];
1987 					break;
1988 				}
1989 			}
1990 		}
1991 	} else {
1992 		/* Search for a localValue entry */
1993 		for (index = 0; index < num_entries; ++index) {
1994 			if (table[index].value == local && !table[index].oid_prefix) {
1995 				found = &table[index];
1996 				break;
1997 			}
1998 		}
1999 	}
2000 
2001 	return found;
2002 }
2003 
2004 /*!
2005  * \internal
2006  * \brief Encode the Facility ie component operation-value.
2007  *
2008  * \param pos Starting position to encode the operation-value.
2009  * \param end End of ASN.1 encoding data buffer.
2010  * \param oid_prefix Encode as an OID if not NULL.
2011  * \param local Encode as a localValue if oid_prefix is NULL
2012  * else it is the last OID subidentifier.
2013  *
2014  * \retval Start of the next ASN.1 component to encode on success.
2015  * \retval NULL on error.
2016  */
rose_enc_operation_value(unsigned char * pos,unsigned char * end,const struct asn1_oid * oid_prefix,unsigned local)2017 static unsigned char *rose_enc_operation_value(unsigned char *pos, unsigned char *end,
2018 	const struct asn1_oid *oid_prefix, unsigned local)
2019 {
2020 	struct asn1_oid oid;
2021 
2022 	if (oid_prefix) {
2023 		if (ARRAY_LEN(oid_prefix->value) <= oid_prefix->num_values) {
2024 			return NULL;
2025 		}
2026 		oid = *oid_prefix;
2027 		oid.value[oid.num_values++] = local;
2028 		return asn1_enc_oid(pos, end, ASN1_TYPE_OBJECT_IDENTIFIER, &oid);
2029 	} else {
2030 		return asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, local);
2031 	}
2032 }
2033 
2034 /*! \brief Mapped to rose_enc_operation_value() */
2035 #define rose_enc_error_value(pos, end, oid_prefix, local)	\
2036 	rose_enc_operation_value(pos, end, oid_prefix, local)
2037 
2038 /*!
2039  * \brief Encode the invoke component for a ROSE message.
2040  *
2041  * \param ctrl D channel controller for diagnostic messages or global options.
2042  * \param pos Starting position to encode ASN.1 message.
2043  * \param end End of ASN.1 encoding data buffer.
2044  * \param msg ROSE invoke message to encode.
2045  *
2046  * \retval Start of the next ASN.1 component to encode on success.
2047  * \retval NULL on error.
2048  */
rose_encode_invoke(struct pri * ctrl,unsigned char * pos,unsigned char * end,const struct rose_msg_invoke * msg)2049 unsigned char *rose_encode_invoke(struct pri *ctrl, unsigned char *pos,
2050 	unsigned char *end, const struct rose_msg_invoke *msg)
2051 {
2052 	const struct rose_convert_msg *convert;
2053 	unsigned char *seq_len;
2054 
2055 	convert = rose_find_msg_by_op_code(ctrl, msg->operation);
2056 	if (!convert) {
2057 		return NULL;
2058 	}
2059 
2060 	ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ROSE_TAG_COMPONENT_INVOKE);
2061 
2062 	ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, msg->invoke_id));
2063 	if (msg->linked_id_present) {
2064 		ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
2065 			msg->linked_id));
2066 	}
2067 	ASN1_CALL(pos, rose_enc_operation_value(pos, end, convert->oid_prefix,
2068 		convert->value));
2069 
2070 	if (convert->encode_invoke_args) {
2071 		ASN1_CALL(pos, convert->encode_invoke_args(ctrl, pos, end, &msg->args));
2072 	}
2073 
2074 	ASN1_CONSTRUCTED_END(seq_len, pos, end);
2075 
2076 	return pos;
2077 }
2078 
2079 /*!
2080  * \brief Encode the result component for a ROSE message.
2081  *
2082  * \param ctrl D channel controller for diagnostic messages or global options.
2083  * \param pos Starting position to encode ASN.1 message.
2084  * \param end End of ASN.1 encoding data buffer.
2085  * \param msg ROSE result message to encode.
2086  *
2087  * \retval Start of the next ASN.1 component to encode on success.
2088  * \retval NULL on error.
2089  */
rose_encode_result(struct pri * ctrl,unsigned char * pos,unsigned char * end,const struct rose_msg_result * msg)2090 unsigned char *rose_encode_result(struct pri *ctrl, unsigned char *pos,
2091 	unsigned char *end, const struct rose_msg_result *msg)
2092 {
2093 	const struct rose_convert_msg *convert;
2094 	unsigned char *seq_len;
2095 	unsigned char *op_seq_len;
2096 
2097 	ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ROSE_TAG_COMPONENT_RESULT);
2098 
2099 	ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, msg->invoke_id));
2100 
2101 	if (msg->operation != ROSE_None) {
2102 		convert = rose_find_msg_by_op_code(ctrl, msg->operation);
2103 		if (!convert) {
2104 			return NULL;
2105 		}
2106 
2107 		ASN1_CONSTRUCTED_BEGIN(op_seq_len, pos, end, ASN1_TYPE_SEQUENCE);
2108 
2109 		ASN1_CALL(pos, rose_enc_operation_value(pos, end, convert->oid_prefix,
2110 			convert->value));
2111 
2112 		if (convert->encode_result_args) {
2113 			ASN1_CALL(pos, convert->encode_result_args(ctrl, pos, end, &msg->args));
2114 		}
2115 
2116 		ASN1_CONSTRUCTED_END(op_seq_len, pos, end);
2117 	}
2118 
2119 	ASN1_CONSTRUCTED_END(seq_len, pos, end);
2120 
2121 	return pos;
2122 }
2123 
2124 /*!
2125  * \brief Encode the error component for a ROSE message.
2126  *
2127  * \param ctrl D channel controller for diagnostic messages or global options.
2128  * \param pos Starting position to encode ASN.1 message.
2129  * \param end End of ASN.1 encoding data buffer.
2130  * \param msg ROSE error message to encode.
2131  *
2132  * \retval Start of the next ASN.1 component to encode on success.
2133  * \retval NULL on error.
2134  */
rose_encode_error(struct pri * ctrl,unsigned char * pos,unsigned char * end,const struct rose_msg_error * msg)2135 unsigned char *rose_encode_error(struct pri *ctrl, unsigned char *pos,
2136 	unsigned char *end, const struct rose_msg_error *msg)
2137 {
2138 	const struct rose_convert_error *convert;
2139 	unsigned char *seq_len;
2140 
2141 	convert = rose_find_error_by_op_code(ctrl, msg->code);
2142 	if (!convert) {
2143 		return NULL;
2144 	}
2145 
2146 	ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ROSE_TAG_COMPONENT_ERROR);
2147 
2148 	ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, msg->invoke_id));
2149 	ASN1_CALL(pos, rose_enc_error_value(pos, end, convert->oid_prefix, convert->value));
2150 	if (convert->encode_error_args) {
2151 		ASN1_CALL(pos, convert->encode_error_args(ctrl, pos, end, &msg->args));
2152 	}
2153 
2154 	ASN1_CONSTRUCTED_END(seq_len, pos, end);
2155 
2156 	return pos;
2157 }
2158 
2159 /*!
2160  * \brief Encode the reject component for a ROSE message.
2161  *
2162  * \param ctrl D channel controller for diagnostic messages or global options.
2163  * \param pos Starting position to encode ASN.1 message.
2164  * \param end End of ASN.1 encoding data buffer.
2165  * \param msg ROSE reject message to encode.
2166  *
2167  * \retval Start of the next ASN.1 component to encode on success.
2168  * \retval NULL on error.
2169  */
rose_encode_reject(struct pri * ctrl,unsigned char * pos,unsigned char * end,const struct rose_msg_reject * msg)2170 unsigned char *rose_encode_reject(struct pri *ctrl, unsigned char *pos,
2171 	unsigned char *end, const struct rose_msg_reject *msg)
2172 {
2173 	unsigned char *seq_len;
2174 	unsigned tag;
2175 
2176 	ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ROSE_TAG_COMPONENT_REJECT);
2177 
2178 	/* Encode Invoke ID */
2179 	if (msg->invoke_id_present) {
2180 		ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, msg->invoke_id));
2181 	} else {
2182 		ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
2183 	}
2184 
2185 	/* Encode the reject problem */
2186 	switch (msg->code & ~0xFF) {
2187 	case ROSE_REJECT_BASE(ROSE_REJECT_BASE_General):
2188 		tag = ASN1_CLASS_CONTEXT_SPECIFIC | 0;
2189 		break;
2190 	case ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke):
2191 		tag = ASN1_CLASS_CONTEXT_SPECIFIC | 1;
2192 		break;
2193 	case ROSE_REJECT_BASE(ROSE_REJECT_BASE_Result):
2194 		tag = ASN1_CLASS_CONTEXT_SPECIFIC | 2;
2195 		break;
2196 	case ROSE_REJECT_BASE(ROSE_REJECT_BASE_Error):
2197 		tag = ASN1_CLASS_CONTEXT_SPECIFIC | 3;
2198 		break;
2199 	default:
2200 		return NULL;
2201 	}
2202 	ASN1_CALL(pos, asn1_enc_int(pos, end, tag, msg->code & 0xFF));
2203 
2204 	ASN1_CONSTRUCTED_END(seq_len, pos, end);
2205 
2206 	return pos;
2207 }
2208 
2209 /*!
2210  * \brief Encode the ROSE message.
2211  *
2212  * \param ctrl D channel controller for diagnostic messages or global options.
2213  * \param pos Starting position to encode ASN.1 message.
2214  * \param end End of ASN.1 encoding data buffer.
2215  * \param msg ROSE message to encode.
2216  *
2217  * \retval Start of the next ASN.1 component to encode on success.
2218  * \retval NULL on error.
2219  *
2220  * \note This function only encodes the ROSE contents.  It does not include
2221  * the protocol profile, NFE, NPP, and interpretation octets defined in
2222  * a facility ie that may precede the ROSE contents.  These header octets
2223  * may already be stored in the encompassing buffer before the starting
2224  * position given here.
2225  */
rose_encode(struct pri * ctrl,unsigned char * pos,unsigned char * end,const struct rose_message * msg)2226 unsigned char *rose_encode(struct pri *ctrl, unsigned char *pos, unsigned char *end,
2227 	const struct rose_message *msg)
2228 {
2229 	switch (msg->type) {
2230 	case ROSE_COMP_TYPE_INVOKE:
2231 		pos = rose_encode_invoke(ctrl, pos, end, &msg->component.invoke);
2232 		break;
2233 	case ROSE_COMP_TYPE_RESULT:
2234 		pos = rose_encode_result(ctrl, pos, end, &msg->component.result);
2235 		break;
2236 	case ROSE_COMP_TYPE_ERROR:
2237 		pos = rose_encode_error(ctrl, pos, end, &msg->component.error);
2238 		break;
2239 	case ROSE_COMP_TYPE_REJECT:
2240 		pos = rose_encode_reject(ctrl, pos, end, &msg->component.reject);
2241 		break;
2242 	default:
2243 		pos = NULL;
2244 		break;
2245 	}
2246 
2247 	return pos;
2248 }
2249 
2250 /*!
2251  * \internal
2252  * \brief Encode the NetworkFacilityExtension type.
2253  *
2254  * \param ctrl D channel controller for diagnostic messages or global options.
2255  * \param pos Starting position to encode ASN.1 component.
2256  * \param end End of ASN.1 encoding data buffer.
2257  * \param nfe Network Facility Extension information to encode.
2258  *
2259  * \retval Start of the next ASN.1 component to encode on success.
2260  * \retval NULL on error.
2261  */
fac_enc_nfe(struct pri * ctrl,unsigned char * pos,unsigned char * end,const struct facNetworkFacilityExtension * nfe)2262 static unsigned char *fac_enc_nfe(struct pri *ctrl, unsigned char *pos,
2263 	unsigned char *end, const struct facNetworkFacilityExtension *nfe)
2264 {
2265 	unsigned char *seq_len;
2266 	unsigned char *explicit_len;
2267 
2268 	ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 10);
2269 
2270 	ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
2271 		nfe->source_entity));
2272 	if (nfe->source_number.length) {
2273 		/* EXPLICIT tag */
2274 		ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
2275 		ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &nfe->source_number));
2276 		ASN1_CONSTRUCTED_END(explicit_len, pos, end);
2277 	}
2278 	ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
2279 		nfe->destination_entity));
2280 	if (nfe->destination_number.length) {
2281 		/* EXPLICIT tag */
2282 		ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
2283 		ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &nfe->destination_number));
2284 		ASN1_CONSTRUCTED_END(explicit_len, pos, end);
2285 	}
2286 
2287 	ASN1_CONSTRUCTED_END(seq_len, pos, end);
2288 
2289 	return pos;
2290 }
2291 
2292 /*!
2293  * \brief Encode the facility extension header.
2294  *
2295  * \param ctrl D channel controller for diagnostic messages or global options.
2296  * \param pos Starting position to encode ASN.1 component.
2297  * \param end End of ASN.1 encoding data buffer.
2298  * \param header Facility extension information to encode.
2299  *
2300  * \retval Start of the next ASN.1 component to encode on success.
2301  * \retval NULL on error.
2302  */
fac_enc_extension_header(struct pri * ctrl,unsigned char * pos,unsigned char * end,const struct fac_extension_header * header)2303 unsigned char *fac_enc_extension_header(struct pri *ctrl, unsigned char *pos,
2304 	unsigned char *end, const struct fac_extension_header *header)
2305 {
2306 	if (header->nfe_present) {
2307 		ASN1_CALL(pos, fac_enc_nfe(ctrl, pos, end, &header->nfe));
2308 	}
2309 	if (header->npp_present) {
2310 		ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 18,
2311 			header->npp));
2312 	}
2313 	if (header->interpretation_present) {
2314 		ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 11,
2315 			header->interpretation));
2316 	}
2317 
2318 	return pos;
2319 }
2320 
2321 /*!
2322  * \brief Encode the facility ie contents header.
2323  *
2324  * \param ctrl D channel controller for diagnostic messages or global options.
2325  * \param pos Starting position to encode the facility ie contents.
2326  * \param end End of facility ie contents encoding data buffer.
2327  * \param header Facility extension header data to encode (NULL if none).
2328  *
2329  * \retval Start of the next ASN.1 component to encode on success.
2330  * \retval NULL on error.
2331  */
facility_encode_header(struct pri * ctrl,unsigned char * pos,unsigned char * end,const struct fac_extension_header * header)2332 unsigned char *facility_encode_header(struct pri *ctrl, unsigned char *pos,
2333 	unsigned char *end, const struct fac_extension_header *header)
2334 {
2335 	/* Make sure we have some room. */
2336 	if (end < pos + 2) {
2337 		return NULL;
2338 	}
2339 
2340 	switch (ctrl->switchtype) {
2341 	case PRI_SWITCH_EUROISDN_T1:
2342 	case PRI_SWITCH_EUROISDN_E1:
2343 		*pos++ = 0x80 | Q932_PROTOCOL_ROSE;
2344 		header = NULL;
2345 		break;
2346 	case PRI_SWITCH_QSIG:
2347 		*pos++ = 0x80 | Q932_PROTOCOL_EXTENSIONS;
2348 		break;
2349 	case PRI_SWITCH_DMS100:
2350 		*pos++ = Q932_PROTOCOL_ROSE;	/* DON'T set the EXT bit yet. */
2351 		*pos++ = 0x80 | ROSE_DMS100_RLT_SERVICE_ID;
2352 		header = NULL;
2353 		break;
2354 	case PRI_SWITCH_ATT4ESS:
2355 	case PRI_SWITCH_LUCENT5E:
2356 	case PRI_SWITCH_NI2:
2357 		if (header) {
2358 			*pos++ = 0x80 | Q932_PROTOCOL_EXTENSIONS;
2359 		} else {
2360 			*pos++ = 0x80 | Q932_PROTOCOL_ROSE;
2361 		}
2362 		break;
2363 	default:
2364 		return NULL;
2365 	}
2366 
2367 	if (header) {
2368 		ASN1_CALL(pos, fac_enc_extension_header(ctrl, pos, end, header));
2369 	}
2370 
2371 	return pos;
2372 }
2373 
2374 /*!
2375  * \internal
2376  * \brief Decode the ROSE invoke message.
2377  *
2378  * \param ctrl D channel controller for diagnostic messages or global options.
2379  * \param tag Component tag that identified this structure.
2380  * \param pos Starting position of the ASN.1 component length.
2381  * \param end End of ASN.1 decoding data buffer.
2382  * \param msg ROSE invoke message data to fill.
2383  *
2384  * \retval Start of the next ASN.1 component on success.
2385  * \retval NULL on error.
2386  */
rose_decode_invoke(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,struct rose_msg_invoke * msg)2387 static const unsigned char *rose_decode_invoke(struct pri *ctrl, unsigned tag,
2388 	const unsigned char *pos, const unsigned char *end, struct rose_msg_invoke *msg)
2389 {
2390 	int32_t value;
2391 	int length;
2392 	int seq_offset;
2393 	const unsigned char *seq_end;
2394 	const struct rose_convert_msg *convert;
2395 	struct asn1_oid oid;
2396 	unsigned local;
2397 
2398 	if (ctrl->debug & PRI_DEBUG_APDU) {
2399 		pri_message(ctrl, "INVOKE Component %s\n", asn1_tag2str(tag));
2400 	}
2401 	ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
2402 	ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
2403 
2404 	ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
2405 	ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
2406 	ASN1_CALL(pos, asn1_dec_int(ctrl, "invokeId", tag, pos, seq_end, &value));
2407 	msg->invoke_id = value;
2408 
2409 	ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
2410 	if (tag == (ASN1_CLASS_CONTEXT_SPECIFIC | 0)) {
2411 		ASN1_CALL(pos, asn1_dec_int(ctrl, "linkedId", tag, pos, seq_end, &value));
2412 		msg->linked_id = value;
2413 		msg->linked_id_present = 1;
2414 
2415 		ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
2416 	} else {
2417 		msg->linked_id_present = 0;
2418 	}
2419 
2420 	/* Decode operation-value */
2421 	switch (tag) {
2422 	case ASN1_TYPE_INTEGER:
2423 		ASN1_CALL(pos, asn1_dec_int(ctrl, "operationValue", tag, pos, seq_end, &value));
2424 		local = value;
2425 		oid.num_values = 0;
2426 		break;
2427 	case ASN1_TYPE_OBJECT_IDENTIFIER:
2428 		ASN1_CALL(pos, asn1_dec_oid(ctrl, "operationValue", tag, pos, seq_end, &oid));
2429 		local = 0;
2430 		break;
2431 	default:
2432 		ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
2433 		return NULL;
2434 	}
2435 	convert = rose_find_msg_by_op_val(ctrl, (oid.num_values == 0) ? NULL : &oid, local);
2436 	if (convert) {
2437 		msg->operation = convert->operation;
2438 	} else {
2439 		msg->operation = ROSE_Unknown;
2440 	}
2441 	if (ctrl->debug & PRI_DEBUG_APDU) {
2442 		pri_message(ctrl, "  operationValue = %s\n", rose_operation2str(msg->operation));
2443 	}
2444 
2445 	/* Decode any expected invoke arguments */
2446 	if (convert && convert->decode_invoke_args) {
2447 		ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
2448 		ASN1_CALL(pos, convert->decode_invoke_args(ctrl, tag, pos, seq_end, &msg->args));
2449 	}
2450 
2451 	ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
2452 
2453 	return pos;
2454 }
2455 
2456 /*!
2457  * \internal
2458  * \brief Decode the ROSE result message.
2459  *
2460  * \param ctrl D channel controller for diagnostic messages or global options.
2461  * \param tag Component tag that identified this structure.
2462  * \param pos Starting position of the ASN.1 component length.
2463  * \param end End of ASN.1 decoding data buffer.
2464  * \param msg ROSE result message data to fill.
2465  *
2466  * \retval Start of the next ASN.1 component on success.
2467  * \retval NULL on error.
2468  */
rose_decode_result(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,struct rose_msg_result * msg)2469 static const unsigned char *rose_decode_result(struct pri *ctrl, unsigned tag,
2470 	const unsigned char *pos, const unsigned char *end, struct rose_msg_result *msg)
2471 {
2472 	int32_t value;
2473 	int length;
2474 	int seq_offset;
2475 	int op_seq_offset;
2476 	const unsigned char *seq_end;
2477 	const unsigned char *op_seq_end;
2478 	const struct rose_convert_msg *convert;
2479 	struct asn1_oid oid;
2480 	unsigned local;
2481 
2482 	if (ctrl->debug & PRI_DEBUG_APDU) {
2483 		pri_message(ctrl, "RESULT Component %s\n", asn1_tag2str(tag));
2484 	}
2485 	ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
2486 	ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
2487 
2488 	ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
2489 	ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
2490 	ASN1_CALL(pos, asn1_dec_int(ctrl, "invokeId", tag, pos, seq_end, &value));
2491 	msg->invoke_id = value;
2492 
2493 	/* Decode optional operation sequence */
2494 	if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
2495 		ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
2496 		ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
2497 		if (ctrl->debug & PRI_DEBUG_APDU) {
2498 			pri_message(ctrl, "  operation %s\n", asn1_tag2str(tag));
2499 		}
2500 		ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
2501 		ASN1_END_SETUP(op_seq_end, op_seq_offset, length, pos, seq_end);
2502 
2503 		/* Decode operation-value */
2504 		ASN1_CALL(pos, asn1_dec_tag(pos, op_seq_end, &tag));
2505 		switch (tag) {
2506 		case ASN1_TYPE_INTEGER:
2507 			ASN1_CALL(pos, asn1_dec_int(ctrl, "operationValue", tag, pos, op_seq_end,
2508 				&value));
2509 			local = value;
2510 			oid.num_values = 0;
2511 			break;
2512 		case ASN1_TYPE_OBJECT_IDENTIFIER:
2513 			ASN1_CALL(pos, asn1_dec_oid(ctrl, "operationValue", tag, pos, op_seq_end,
2514 				&oid));
2515 			local = 0;
2516 			break;
2517 		default:
2518 			ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
2519 			return NULL;
2520 		}
2521 		convert =
2522 			rose_find_msg_by_op_val(ctrl, (oid.num_values == 0) ? NULL : &oid, local);
2523 		if (convert) {
2524 			msg->operation = convert->operation;
2525 		} else {
2526 			msg->operation = ROSE_Unknown;
2527 		}
2528 		if (ctrl->debug & PRI_DEBUG_APDU) {
2529 			pri_message(ctrl, "  operationValue = %s\n",
2530 				rose_operation2str(msg->operation));
2531 		}
2532 
2533 		/* Decode any expected result arguments */
2534 		if (convert && convert->decode_result_args) {
2535 			ASN1_CALL(pos, asn1_dec_tag(pos, op_seq_end, &tag));
2536 			ASN1_CALL(pos, convert->decode_result_args(ctrl, tag, pos, op_seq_end,
2537 				&msg->args));
2538 		}
2539 
2540 		ASN1_END_FIXUP(ctrl, pos, op_seq_offset, op_seq_end, seq_end);
2541 	} else {
2542 		msg->operation = ROSE_None;
2543 	}
2544 
2545 	ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
2546 
2547 	return pos;
2548 }
2549 
2550 /*!
2551  * \internal
2552  * \brief Decode the ROSE error message.
2553  *
2554  * \param ctrl D channel controller for diagnostic messages or global options.
2555  * \param tag Component tag that identified this structure.
2556  * \param pos Starting position of the ASN.1 component length.
2557  * \param end End of ASN.1 decoding data buffer.
2558  * \param msg ROSE error message data to fill.
2559  *
2560  * \retval Start of the next ASN.1 component on success.
2561  * \retval NULL on error.
2562  */
rose_decode_error(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,struct rose_msg_error * msg)2563 static const unsigned char *rose_decode_error(struct pri *ctrl, unsigned tag,
2564 	const unsigned char *pos, const unsigned char *end, struct rose_msg_error *msg)
2565 {
2566 	int32_t value;
2567 	int length;
2568 	int seq_offset;
2569 	const unsigned char *seq_end;
2570 	const struct rose_convert_error *convert;
2571 	struct asn1_oid oid;
2572 	unsigned local;
2573 
2574 	if (ctrl->debug & PRI_DEBUG_APDU) {
2575 		pri_message(ctrl, "ERROR Component %s\n", asn1_tag2str(tag));
2576 	}
2577 	ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
2578 	ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
2579 
2580 	ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
2581 	ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
2582 	ASN1_CALL(pos, asn1_dec_int(ctrl, "invokeId", tag, pos, seq_end, &value));
2583 	msg->invoke_id = value;
2584 
2585 	/* Decode error-value */
2586 	ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
2587 	switch (tag) {
2588 	case ASN1_TYPE_INTEGER:
2589 		ASN1_CALL(pos, asn1_dec_int(ctrl, "errorValue", tag, pos, seq_end, &value));
2590 		local = value;
2591 		oid.num_values = 0;
2592 		break;
2593 	case ASN1_TYPE_OBJECT_IDENTIFIER:
2594 		ASN1_CALL(pos, asn1_dec_oid(ctrl, "errorValue", tag, pos, seq_end, &oid));
2595 		local = 0;
2596 		break;
2597 	default:
2598 		ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
2599 		return NULL;
2600 	}
2601 	convert =
2602 		rose_find_error_by_op_val(ctrl, (oid.num_values == 0) ? NULL : &oid, local);
2603 	if (convert) {
2604 		msg->code = convert->code;
2605 	} else {
2606 		msg->code = ROSE_ERROR_Unknown;
2607 	}
2608 	if (ctrl->debug & PRI_DEBUG_APDU) {
2609 		pri_message(ctrl, "  errorValue = %s\n", rose_error2str(msg->code));
2610 	}
2611 
2612 	/* Decode any expected error parameters */
2613 	if (convert && convert->decode_error_args) {
2614 		ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
2615 		ASN1_CALL(pos, convert->decode_error_args(ctrl, tag, pos, seq_end, &msg->args));
2616 	}
2617 
2618 	ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
2619 
2620 	return pos;
2621 }
2622 
2623 /*!
2624  * \internal
2625  * \brief Decode the ROSE reject message.
2626  *
2627  * \param ctrl D channel controller for diagnostic messages or global options.
2628  * \param tag Component tag that identified this structure.
2629  * \param pos Starting position of the ASN.1 component length.
2630  * \param end End of ASN.1 decoding data buffer.
2631  * \param msg ROSE reject message data to fill.
2632  *
2633  * \retval Start of the next ASN.1 component on success.
2634  * \retval NULL on error.
2635  */
rose_decode_reject(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,struct rose_msg_reject * msg)2636 static const unsigned char *rose_decode_reject(struct pri *ctrl, unsigned tag,
2637 	const unsigned char *pos, const unsigned char *end, struct rose_msg_reject *msg)
2638 {
2639 	int32_t value;
2640 	int length;
2641 	int seq_offset;
2642 	const unsigned char *seq_end;
2643 
2644 	if (ctrl->debug & PRI_DEBUG_APDU) {
2645 		pri_message(ctrl, "REJECT Component %s\n", asn1_tag2str(tag));
2646 	}
2647 	ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
2648 	ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
2649 
2650 	/* Invoke ID choice */
2651 	ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
2652 	switch (tag) {
2653 	case ASN1_TYPE_INTEGER:
2654 		ASN1_CALL(pos, asn1_dec_int(ctrl, "invokeId", tag, pos, seq_end, &value));
2655 		msg->invoke_id = value;
2656 		msg->invoke_id_present = 1;
2657 		break;
2658 	case ASN1_TYPE_NULL:
2659 		ASN1_CALL(pos, asn1_dec_null(ctrl, "invokeId", tag, pos, seq_end));
2660 		msg->invoke_id_present = 0;
2661 		break;
2662 	default:
2663 		ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
2664 		return NULL;
2665 	}
2666 
2667 	/* Problem choice */
2668 	ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
2669 	switch (tag) {
2670 	case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
2671 		ASN1_CALL(pos, asn1_dec_int(ctrl, "problemGeneral", tag, pos, seq_end, &value));
2672 		msg->code = ROSE_REJECT_BASE(ROSE_REJECT_BASE_General) | (value & 0xFF);
2673 		break;
2674 	case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
2675 		ASN1_CALL(pos, asn1_dec_int(ctrl, "problemInvoke", tag, pos, seq_end, &value));
2676 		msg->code = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke) | (value & 0xFF);
2677 		break;
2678 	case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
2679 		ASN1_CALL(pos, asn1_dec_int(ctrl, "problemResult", tag, pos, seq_end, &value));
2680 		msg->code = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Result) | (value & 0xFF);
2681 		break;
2682 	case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
2683 		ASN1_CALL(pos, asn1_dec_int(ctrl, "problemError", tag, pos, seq_end, &value));
2684 		msg->code = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Error) | (value & 0xFF);
2685 		break;
2686 	default:
2687 		ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
2688 		return NULL;
2689 	}
2690 	if (ctrl->debug & PRI_DEBUG_APDU) {
2691 		pri_message(ctrl, "  problem = %s\n", rose_reject2str(msg->code));
2692 	}
2693 
2694 	ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
2695 
2696 	return pos;
2697 }
2698 
2699 /*!
2700  * \brief Decode the ROSE message into the given buffer.
2701  *
2702  * \param ctrl D channel controller for diagnostic messages or global options.
2703  * \param pos Starting position of the ASN.1 component.
2704  * \param end End of ASN.1 decoding data buffer.
2705  * \param msg Decoded ROSE message contents.
2706  *
2707  * \retval Start of the next ASN.1 component on success.
2708  * \retval NULL on error.
2709  *
2710  * \note This function only decodes the ROSE contents.  It does not check
2711  * for the protocol profile, NFE, NPP, and interpretation octets defined in
2712  * a facility ie that may preceed the ROSE contents.  These header octets
2713  * may already have been consumed from the encompasing buffer before the
2714  * buffer given here.
2715  */
rose_decode(struct pri * ctrl,const unsigned char * pos,const unsigned char * end,struct rose_message * msg)2716 const unsigned char *rose_decode(struct pri *ctrl, const unsigned char *pos,
2717 	const unsigned char *end, struct rose_message *msg)
2718 {
2719 	unsigned tag;
2720 
2721 	ASN1_CALL(pos, asn1_dec_tag(pos, end, &tag));
2722 	switch (tag) {
2723 	case ROSE_TAG_COMPONENT_INVOKE:
2724 		msg->type = ROSE_COMP_TYPE_INVOKE;
2725 		ASN1_CALL(pos, rose_decode_invoke(ctrl, tag, pos, end, &msg->component.invoke));
2726 		break;
2727 	case ROSE_TAG_COMPONENT_RESULT:
2728 		msg->type = ROSE_COMP_TYPE_RESULT;
2729 		ASN1_CALL(pos, rose_decode_result(ctrl, tag, pos, end, &msg->component.result));
2730 		break;
2731 	case ROSE_TAG_COMPONENT_ERROR:
2732 		msg->type = ROSE_COMP_TYPE_ERROR;
2733 		ASN1_CALL(pos, rose_decode_error(ctrl, tag, pos, end, &msg->component.error));
2734 		break;
2735 	case ROSE_TAG_COMPONENT_REJECT:
2736 		msg->type = ROSE_COMP_TYPE_REJECT;
2737 		ASN1_CALL(pos, rose_decode_reject(ctrl, tag, pos, end, &msg->component.reject));
2738 		break;
2739 	default:
2740 		msg->type = ROSE_COMP_TYPE_INVALID;
2741 		ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
2742 		return NULL;
2743 	}
2744 
2745 	return pos;
2746 }
2747 
2748 /*!
2749  * \internal
2750  * \brief Decode the NetworkFacilityExtension argument parameters.
2751  *
2752  * \param ctrl D channel controller for any diagnostic messages.
2753  * \param name Field name
2754  * \param tag Component tag that identified this production.
2755  * \param pos Starting position of the ASN.1 component length.
2756  * \param end End of ASN.1 decoding data buffer.
2757  * \param nfe Parameter storage to fill.
2758  *
2759  * \retval Start of the next ASN.1 component on success.
2760  * \retval NULL on error.
2761  */
fac_dec_nfe(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct facNetworkFacilityExtension * nfe)2762 static const unsigned char *fac_dec_nfe(struct pri *ctrl, const char *name, unsigned tag,
2763 	const unsigned char *pos, const unsigned char *end,
2764 	struct facNetworkFacilityExtension *nfe)
2765 {
2766 	int length;
2767 	int seq_offset;
2768 	int explicit_offset;
2769 	const unsigned char *seq_end;
2770 	const unsigned char *explicit_end;
2771 	const unsigned char *save_pos;
2772 	int32_t value;
2773 
2774 	if (ctrl->debug & PRI_DEBUG_APDU) {
2775 		pri_message(ctrl, "  %s NetworkFacilityExtension %s\n", name, asn1_tag2str(tag));
2776 	}
2777 	ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
2778 	ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
2779 
2780 	ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
2781 	ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
2782 	ASN1_CALL(pos, asn1_dec_int(ctrl, "sourceEntity", tag, pos, seq_end, &value));
2783 	nfe->source_entity = value;
2784 
2785 	ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
2786 	if (tag == (ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1)) {
2787 		/* Remove EXPLICIT tag */
2788 		if (ctrl->debug & PRI_DEBUG_APDU) {
2789 			pri_message(ctrl, "  Explicit %s\n", asn1_tag2str(tag));
2790 		}
2791 		ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
2792 		ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
2793 
2794 		ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
2795 		ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "sourceEntityAddress", tag, pos,
2796 			seq_end, &nfe->source_number));
2797 
2798 		ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
2799 
2800 		ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
2801 	} else {
2802 		nfe->source_number.length = 0;
2803 	}
2804 
2805 	ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
2806 	ASN1_CALL(pos, asn1_dec_int(ctrl, "destinationEntity", tag, pos, seq_end, &value));
2807 	nfe->destination_entity = value;
2808 
2809 	nfe->destination_number.length = 0;
2810 	if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
2811 		save_pos = pos;
2812 		ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
2813 		if (tag == (ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3)) {
2814 			/* Remove EXPLICIT tag */
2815 			if (ctrl->debug & PRI_DEBUG_APDU) {
2816 				pri_message(ctrl, "  Explicit %s\n", asn1_tag2str(tag));
2817 			}
2818 			ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
2819 			ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
2820 
2821 			ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
2822 			ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "destinationEntityAddress", tag,
2823 				pos, seq_end, &nfe->destination_number));
2824 
2825 			ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
2826 		} else {
2827 			pos = save_pos;
2828 		}
2829 	}
2830 
2831 	ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
2832 
2833 	return pos;
2834 }
2835 
2836 /*!
2837  * \brief Decode the extension header argument parameters.
2838  *
2839  * \param ctrl D channel controller for any diagnostic messages.
2840  * \param pos Starting position of the ASN.1 component.
2841  * \param end End of ASN.1 decoding data buffer.
2842  * \param header Parameter storage to fill.
2843  *
2844  * \retval Start of the next ASN.1 component on success.
2845  * \retval NULL on error.
2846  */
fac_dec_extension_header(struct pri * ctrl,const unsigned char * pos,const unsigned char * end,struct fac_extension_header * header)2847 const unsigned char *fac_dec_extension_header(struct pri *ctrl, const unsigned char *pos,
2848 	const unsigned char *end, struct fac_extension_header *header)
2849 {
2850 	int32_t value;
2851 	unsigned tag;
2852 	const unsigned char *save_pos;
2853 
2854 	/*
2855 	 * For simplicity we are not checking the order of
2856 	 * the optional header components.
2857 	 */
2858 	header->nfe_present = 0;
2859 	header->npp_present = 0;
2860 	header->interpretation_present = 0;
2861 	while (pos < end) {
2862 		save_pos = pos;
2863 		ASN1_CALL(pos, asn1_dec_tag(pos, end, &tag));
2864 		switch (tag) {
2865 		case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 10:
2866 			ASN1_CALL(pos, fac_dec_nfe(ctrl, "nfe", tag, pos, end, &header->nfe));
2867 			header->nfe_present = 1;
2868 			break;
2869 		case ASN1_CLASS_CONTEXT_SPECIFIC | 18:
2870 			ASN1_CALL(pos, asn1_dec_int(ctrl, "networkProtocolProfile", tag, pos, end,
2871 				&value));
2872 			header->npp = value;
2873 			header->npp_present = 1;
2874 			break;
2875 		case ASN1_CLASS_CONTEXT_SPECIFIC | 11:
2876 			ASN1_CALL(pos, asn1_dec_int(ctrl, "interpretation", tag, pos, end, &value));
2877 			header->interpretation = value;
2878 			header->interpretation_present = 1;
2879 			break;
2880 		default:
2881 			pos = save_pos;
2882 			goto cancel_options;
2883 		}
2884 	}
2885 cancel_options:;
2886 
2887 	return pos;
2888 }
2889 
2890 /*!
2891  * \brief Decode the facility ie contents header.
2892  *
2893  * \param ctrl D channel controller for any diagnostic messages.
2894  * \param pos Starting position of the facility ie contents.
2895  * \param end End of facility ie contents.
2896  * \param header Parameter storage to fill.
2897  *
2898  * \retval Start of the next ASN.1 component on success (ROSE message).
2899  * \retval NULL on error.
2900  */
facility_decode_header(struct pri * ctrl,const unsigned char * pos,const unsigned char * end,struct fac_extension_header * header)2901 const unsigned char *facility_decode_header(struct pri *ctrl, const unsigned char *pos,
2902 	const unsigned char *end, struct fac_extension_header *header)
2903 {
2904 	/* Make sure we have enough room for the protocol profile ie octet(s) */
2905 	if (end < pos + 2) {
2906 		return NULL;
2907 	}
2908 	switch (*pos & Q932_PROTOCOL_MASK) {
2909 	case Q932_PROTOCOL_ROSE:
2910 	case Q932_PROTOCOL_EXTENSIONS:
2911 		break;
2912 	default:
2913 		return NULL;
2914 	}
2915 	if (!(*pos & 0x80)) {
2916 		/* DMS-100 Service indicator octet - Just ignore for now */
2917 		++pos;
2918 	}
2919 	++pos;
2920 
2921 	if (ctrl->debug & PRI_DEBUG_APDU) {
2922 		asn1_dump(ctrl, pos, end);
2923 	}
2924 
2925 	pos = fac_dec_extension_header(ctrl, pos, end, header);
2926 	return pos;
2927 }
2928 
2929 /*!
2930  * \brief Decode the facility ie contents for debug purposes.
2931  *
2932  * \param ctrl D channel controller for any diagnostic messages.
2933  * \param buf Buffer containing the facility ie contents.
2934  * \param length Length of facility ie contents.
2935  *
2936  * \return Nothing
2937  *
2938  * \note Should only be called if PRI_DEBUG_APDU is enabled.  Otherwise,
2939  * it it does nothing useful.
2940  */
facility_decode_dump(struct pri * ctrl,const unsigned char * buf,size_t length)2941 void facility_decode_dump(struct pri *ctrl, const unsigned char *buf, size_t length)
2942 {
2943 	const unsigned char *pos;
2944 	const unsigned char *end;
2945 	union {
2946 		struct fac_extension_header header;
2947 		struct rose_message rose;
2948 	} discard;
2949 
2950 	end = buf + length;
2951 	pos = facility_decode_header(ctrl, buf, end, &discard.header);
2952 	while (pos && pos < end) {
2953 		pos = rose_decode(ctrl, pos, end, &discard.rose);
2954 	}
2955 }
2956 
2957 /* ------------------------------------------------------------------- */
2958 /* end rose.c */
2959