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