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 Q.SIG ROSE Advice-Of-Charge (AOC) operations
30 *
31 * SS-AOC-Operations ECMA-212 Annex E Table E.1
32 *
33 * \author Richard Mudgett <rmudgett@digium.com>
34 */
35
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
44
45 /* ------------------------------------------------------------------- */
46
47 /*!
48 * \internal
49 * \brief Encode the Time type.
50 *
51 * \param ctrl D channel controller for diagnostic messages or global options.
52 * \param pos Starting position to encode ASN.1 component.
53 * \param end End of ASN.1 encoding data buffer.
54 * \param tag Component tag to identify the encoded component.
55 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
56 * tags it otherwise.
57 * \param time Time information to encode.
58 *
59 * \retval Start of the next ASN.1 component to encode on success.
60 * \retval NULL on error.
61 */
rose_enc_qsig_AOC_Time(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseQsigAOCTime * time)62 static unsigned char *rose_enc_qsig_AOC_Time(struct pri *ctrl, unsigned char *pos,
63 unsigned char *end, unsigned tag, const struct roseQsigAOCTime *time)
64 {
65 unsigned char *seq_len;
66
67 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
68
69 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
70 time->length));
71 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2, time->scale));
72
73 ASN1_CONSTRUCTED_END(seq_len, pos, end);
74
75 return pos;
76 }
77
78 /*!
79 * \internal
80 * \brief Encode the Amount type.
81 *
82 * \param ctrl D channel controller for diagnostic messages or global options.
83 * \param pos Starting position to encode ASN.1 component.
84 * \param end End of ASN.1 encoding data buffer.
85 * \param tag Component tag to identify the encoded component.
86 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
87 * tags it otherwise.
88 * \param amount Amount information to encode.
89 *
90 * \retval Start of the next ASN.1 component to encode on success.
91 * \retval NULL on error.
92 */
rose_enc_qsig_AOC_Amount(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseQsigAOCAmount * amount)93 static unsigned char *rose_enc_qsig_AOC_Amount(struct pri *ctrl, unsigned char *pos,
94 unsigned char *end, unsigned tag, const struct roseQsigAOCAmount *amount)
95 {
96 unsigned char *seq_len;
97
98 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
99
100 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
101 amount->currency));
102 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
103 amount->multiplier));
104
105 ASN1_CONSTRUCTED_END(seq_len, pos, end);
106
107 return pos;
108 }
109
110 /*!
111 * \internal
112 * \brief Encode the RecordedCurrency type.
113 *
114 * \param ctrl D channel controller for diagnostic messages or global options.
115 * \param pos Starting position to encode ASN.1 component.
116 * \param end End of ASN.1 encoding data buffer.
117 * \param tag Component tag to identify the encoded component.
118 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
119 * tags it otherwise.
120 * \param recorded Recorded currency information to encode.
121 *
122 * \retval Start of the next ASN.1 component to encode on success.
123 * \retval NULL on error.
124 */
rose_enc_qsig_AOC_RecordedCurrency(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseQsigAOCRecordedCurrency * recorded)125 static unsigned char *rose_enc_qsig_AOC_RecordedCurrency(struct pri *ctrl,
126 unsigned char *pos, unsigned char *end, unsigned tag,
127 const struct roseQsigAOCRecordedCurrency *recorded)
128 {
129 unsigned char *seq_len;
130
131 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
132
133 ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
134 recorded->currency, sizeof(recorded->currency) - 1));
135 ASN1_CALL(pos, rose_enc_qsig_AOC_Amount(ctrl, pos, end,
136 ASN1_CLASS_CONTEXT_SPECIFIC | 2, &recorded->amount));
137
138 ASN1_CONSTRUCTED_END(seq_len, pos, end);
139
140 return pos;
141 }
142
143 /*!
144 * \internal
145 * \brief Encode the DurationCurrency type.
146 *
147 * \param ctrl D channel controller for diagnostic messages or global options.
148 * \param pos Starting position to encode ASN.1 component.
149 * \param end End of ASN.1 encoding data buffer.
150 * \param tag Component tag to identify the encoded component.
151 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
152 * tags it otherwise.
153 * \param duration Duration currency information to encode.
154 *
155 * \retval Start of the next ASN.1 component to encode on success.
156 * \retval NULL on error.
157 */
rose_enc_qsig_AOC_DurationCurrency(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseQsigAOCDurationCurrency * duration)158 static unsigned char *rose_enc_qsig_AOC_DurationCurrency(struct pri *ctrl,
159 unsigned char *pos, unsigned char *end, unsigned tag,
160 const struct roseQsigAOCDurationCurrency *duration)
161 {
162 unsigned char *seq_len;
163
164 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
165
166 ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
167 duration->currency, sizeof(duration->currency) - 1));
168 ASN1_CALL(pos, rose_enc_qsig_AOC_Amount(ctrl, pos, end,
169 ASN1_CLASS_CONTEXT_SPECIFIC | 2, &duration->amount));
170 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
171 duration->charging_type));
172 ASN1_CALL(pos, rose_enc_qsig_AOC_Time(ctrl, pos, end,
173 ASN1_CLASS_CONTEXT_SPECIFIC | 4, &duration->time));
174 if (duration->granularity_present) {
175 ASN1_CALL(pos, rose_enc_qsig_AOC_Time(ctrl, pos, end,
176 ASN1_CLASS_CONTEXT_SPECIFIC | 5, &duration->granularity));
177 }
178
179 ASN1_CONSTRUCTED_END(seq_len, pos, end);
180
181 return pos;
182 }
183
184 /*!
185 * \internal
186 * \brief Encode the FlatRateCurrency type.
187 *
188 * \param ctrl D channel controller for diagnostic messages or global options.
189 * \param pos Starting position to encode ASN.1 component.
190 * \param end End of ASN.1 encoding data buffer.
191 * \param tag Component tag to identify the encoded component.
192 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
193 * tags it otherwise.
194 * \param flat_rate Flat rate currency information to encode.
195 *
196 * \retval Start of the next ASN.1 component to encode on success.
197 * \retval NULL on error.
198 */
rose_enc_qsig_AOC_FlatRateCurrency(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseQsigAOCFlatRateCurrency * flat_rate)199 static unsigned char *rose_enc_qsig_AOC_FlatRateCurrency(struct pri *ctrl,
200 unsigned char *pos, unsigned char *end, unsigned tag,
201 const struct roseQsigAOCFlatRateCurrency *flat_rate)
202 {
203 unsigned char *seq_len;
204
205 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
206
207 ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
208 flat_rate->currency, sizeof(flat_rate->currency) - 1));
209 ASN1_CALL(pos, rose_enc_qsig_AOC_Amount(ctrl, pos, end,
210 ASN1_CLASS_CONTEXT_SPECIFIC | 2, &flat_rate->amount));
211
212 ASN1_CONSTRUCTED_END(seq_len, pos, end);
213
214 return pos;
215 }
216
217 /*!
218 * \internal
219 * \brief Encode the VolumeRateCurrency type.
220 *
221 * \param ctrl D channel controller for diagnostic messages or global options.
222 * \param pos Starting position to encode ASN.1 component.
223 * \param end End of ASN.1 encoding data buffer.
224 * \param tag Component tag to identify the encoded component.
225 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
226 * tags it otherwise.
227 * \param volume_rate Volume rate currency information to encode.
228 *
229 * \retval Start of the next ASN.1 component to encode on success.
230 * \retval NULL on error.
231 */
rose_enc_qsig_AOC_VolumeRateCurrency(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseQsigAOCVolumeRateCurrency * volume_rate)232 static unsigned char *rose_enc_qsig_AOC_VolumeRateCurrency(struct pri *ctrl,
233 unsigned char *pos, unsigned char *end, unsigned tag,
234 const struct roseQsigAOCVolumeRateCurrency *volume_rate)
235 {
236 unsigned char *seq_len;
237
238 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
239
240 ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
241 volume_rate->currency, sizeof(volume_rate->currency) - 1));
242 ASN1_CALL(pos, rose_enc_qsig_AOC_Amount(ctrl, pos, end,
243 ASN1_CLASS_CONTEXT_SPECIFIC | 2, &volume_rate->amount));
244 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
245 volume_rate->unit));
246
247 ASN1_CONSTRUCTED_END(seq_len, pos, end);
248
249 return pos;
250 }
251
252 /*!
253 * \internal
254 * \brief Encode the AOCSCurrencyInfo type.
255 *
256 * \param ctrl D channel controller for diagnostic messages or global options.
257 * \param pos Starting position to encode ASN.1 component.
258 * \param end End of ASN.1 encoding data buffer.
259 * \param tag Component tag to identify the encoded component.
260 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
261 * tags it otherwise.
262 * \param currency_info Currency information record to encode.
263 *
264 * \retval Start of the next ASN.1 component to encode on success.
265 * \retval NULL on error.
266 */
rose_enc_qsig_AOCSCurrencyInfo(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseQsigAOCSCurrencyInfo * currency_info)267 static unsigned char *rose_enc_qsig_AOCSCurrencyInfo(struct pri *ctrl,
268 unsigned char *pos, unsigned char *end, unsigned tag,
269 const struct roseQsigAOCSCurrencyInfo *currency_info)
270 {
271 unsigned char *seq_len;
272
273 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
274
275 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
276 currency_info->charged_item));
277
278 switch (currency_info->currency_type) {
279 case 0: /* specialChargingCode */
280 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
281 currency_info->u.special_charging_code));
282 break;
283 case 1: /* durationCurrency */
284 ASN1_CALL(pos, rose_enc_qsig_AOC_DurationCurrency(ctrl, pos, end,
285 ASN1_CLASS_CONTEXT_SPECIFIC | 1, ¤cy_info->u.duration));
286 break;
287 case 2: /* flatRateCurrency */
288 ASN1_CALL(pos, rose_enc_qsig_AOC_FlatRateCurrency(ctrl, pos, end,
289 ASN1_CLASS_CONTEXT_SPECIFIC | 2, ¤cy_info->u.flat_rate));
290 break;
291 case 3: /* volumeRateCurrency */
292 ASN1_CALL(pos, rose_enc_qsig_AOC_VolumeRateCurrency(ctrl, pos, end,
293 ASN1_CLASS_CONTEXT_SPECIFIC | 3, ¤cy_info->u.volume_rate));
294 break;
295 case 4: /* freeOfCharge */
296 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4));
297 break;
298 case 5: /* currencyInfoNotAvailable */
299 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5));
300 break;
301 case 6: /* freeOfChargeFromBeginning */
302 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 6));
303 break;
304 default:
305 ASN1_ENC_ERROR(ctrl, "Unknown currency type");
306 return NULL;
307 }
308
309 ASN1_CONSTRUCTED_END(seq_len, pos, end);
310
311 return pos;
312 }
313
314 /*!
315 * \internal
316 * \brief Encode the AOCSCurrencyInfoList type.
317 *
318 * \param ctrl D channel controller for diagnostic messages or global options.
319 * \param pos Starting position to encode ASN.1 component.
320 * \param end End of ASN.1 encoding data buffer.
321 * \param tag Component tag to identify the encoded component.
322 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
323 * tags it otherwise.
324 * \param currency_info Currency information list to encode.
325 *
326 * \retval Start of the next ASN.1 component to encode on success.
327 * \retval NULL on error.
328 */
rose_enc_qsig_AOCSCurrencyInfoList(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseQsigAOCSCurrencyInfoList * currency_info)329 static unsigned char *rose_enc_qsig_AOCSCurrencyInfoList(struct pri *ctrl,
330 unsigned char *pos, unsigned char *end, unsigned tag,
331 const struct roseQsigAOCSCurrencyInfoList *currency_info)
332 {
333 unsigned index;
334 unsigned char *seq_len;
335
336 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
337
338 for (index = 0; index < currency_info->num_records; ++index) {
339 ASN1_CALL(pos, rose_enc_qsig_AOCSCurrencyInfo(ctrl, pos, end, ASN1_TAG_SEQUENCE,
340 ¤cy_info->list[index]));
341 }
342
343 ASN1_CONSTRUCTED_END(seq_len, pos, end);
344
345 return pos;
346 }
347
348 /*!
349 * \internal
350 * \brief Encode the ChargingAssociation type.
351 *
352 * \param ctrl D channel controller for diagnostic messages or global options.
353 * \param pos Starting position to encode ASN.1 component.
354 * \param end End of ASN.1 encoding data buffer.
355 * \param charging Charging association information to encode.
356 *
357 * \retval Start of the next ASN.1 component to encode on success.
358 * \retval NULL on error.
359 */
rose_enc_qsig_AOC_ChargingAssociation(struct pri * ctrl,unsigned char * pos,unsigned char * end,const struct roseQsigAOCChargingAssociation * charging)360 static unsigned char *rose_enc_qsig_AOC_ChargingAssociation(struct pri *ctrl,
361 unsigned char *pos, unsigned char *end,
362 const struct roseQsigAOCChargingAssociation *charging)
363 {
364 unsigned char *explicit_len;
365
366 switch (charging->type) {
367 case 0: /* charge_identifier */
368 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, charging->id));
369 break;
370 case 1: /* charged_number */
371 /* EXPLICIT tag */
372 ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
373 ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &charging->number));
374 ASN1_CONSTRUCTED_END(explicit_len, pos, end);
375 break;
376 default:
377 ASN1_ENC_ERROR(ctrl, "Unknown ChargingAssociation type");
378 return NULL;
379 }
380
381 return pos;
382 }
383
384 /*!
385 * \brief Encode the Q.SIG ChargeRequest invoke facility ie arguments.
386 *
387 * \param ctrl D channel controller for diagnostic messages or global options.
388 * \param pos Starting position to encode ASN.1 component.
389 * \param end End of ASN.1 encoding data buffer.
390 * \param args Arguments to encode in the buffer.
391 *
392 * \retval Start of the next ASN.1 component to encode on success.
393 * \retval NULL on error.
394 */
rose_enc_qsig_ChargeRequest_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)395 unsigned char *rose_enc_qsig_ChargeRequest_ARG(struct pri *ctrl, unsigned char *pos,
396 unsigned char *end, const union rose_msg_invoke_args *args)
397 {
398 unsigned index;
399 unsigned char *seq_len;
400 unsigned char *advice_len;
401 const struct roseQsigChargeRequestArg_ARG *charge_request;
402
403 charge_request = &args->qsig.ChargeRequest;
404
405 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
406
407 /* SEQUENCE SIZE(0..7) OF AdviceModeCombination */
408 ASN1_CONSTRUCTED_BEGIN(advice_len, pos, end, ASN1_TAG_SEQUENCE);
409 for (index = 0; index < charge_request->num_records; ++index) {
410 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
411 charge_request->advice_mode_combinations[index]));
412 }
413 ASN1_CONSTRUCTED_END(advice_len, pos, end);
414
415 /* No extension to encode */
416
417 ASN1_CONSTRUCTED_END(seq_len, pos, end);
418
419 return pos;
420 }
421
422 /*!
423 * \brief Encode the Q.SIG ChargeRequest result facility ie arguments.
424 *
425 * \param ctrl D channel controller for diagnostic messages or global options.
426 * \param pos Starting position to encode ASN.1 component.
427 * \param end End of ASN.1 encoding data buffer.
428 * \param args Arguments to encode in the buffer.
429 *
430 * \retval Start of the next ASN.1 component to encode on success.
431 * \retval NULL on error.
432 */
rose_enc_qsig_ChargeRequest_RES(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_result_args * args)433 unsigned char *rose_enc_qsig_ChargeRequest_RES(struct pri *ctrl, unsigned char *pos,
434 unsigned char *end, const union rose_msg_result_args *args)
435 {
436 unsigned char *seq_len;
437 const struct roseQsigChargeRequestRes_RES *charge_request;
438
439 charge_request = &args->qsig.ChargeRequest;
440
441 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
442
443 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
444 charge_request->advice_mode_combination));
445
446 /* No extension to encode */
447
448 ASN1_CONSTRUCTED_END(seq_len, pos, end);
449
450 return pos;
451 }
452
453 /*!
454 * \brief Encode the Q.SIG AocFinal invoke facility ie arguments.
455 *
456 * \param ctrl D channel controller for diagnostic messages or global options.
457 * \param pos Starting position to encode ASN.1 component.
458 * \param end End of ASN.1 encoding data buffer.
459 * \param args Arguments to encode in the buffer.
460 *
461 * \retval Start of the next ASN.1 component to encode on success.
462 * \retval NULL on error.
463 */
rose_enc_qsig_AocFinal_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)464 unsigned char *rose_enc_qsig_AocFinal_ARG(struct pri *ctrl, unsigned char *pos,
465 unsigned char *end, const union rose_msg_invoke_args *args)
466 {
467 unsigned char *seq_len;
468 unsigned char *specific_len;
469 const struct roseQsigAocFinalArg_ARG *aoc_final;
470
471 aoc_final = &args->qsig.AocFinal;
472
473 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
474
475 switch (aoc_final->type) {
476 case 0: /* charge_not_available */
477 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0));
478 break;
479 case 1: /* free_of_charge */
480 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
481 break;
482 case 2: /* specific_currency */
483 ASN1_CONSTRUCTED_BEGIN(specific_len, pos, end, ASN1_TAG_SEQUENCE);
484
485 ASN1_CALL(pos, rose_enc_qsig_AOC_RecordedCurrency(ctrl, pos, end,
486 ASN1_CLASS_CONTEXT_SPECIFIC | 1, &aoc_final->specific.recorded));
487
488 if (aoc_final->specific.billing_id_present) {
489 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
490 aoc_final->specific.billing_id));
491 }
492
493 ASN1_CONSTRUCTED_END(specific_len, pos, end);
494 break;
495 default:
496 ASN1_ENC_ERROR(ctrl, "Unknown AocFinal type");
497 return NULL;
498 }
499
500 if (aoc_final->charging_association_present) {
501 ASN1_CALL(pos, rose_enc_qsig_AOC_ChargingAssociation(ctrl, pos, end,
502 &aoc_final->charging_association));
503 }
504
505 /* No extension to encode */
506
507 ASN1_CONSTRUCTED_END(seq_len, pos, end);
508
509 return pos;
510 }
511
512 /*!
513 * \brief Encode the Q.SIG AocInterim invoke facility ie arguments.
514 *
515 * \param ctrl D channel controller for diagnostic messages or global options.
516 * \param pos Starting position to encode ASN.1 component.
517 * \param end End of ASN.1 encoding data buffer.
518 * \param args Arguments to encode in the buffer.
519 *
520 * \retval Start of the next ASN.1 component to encode on success.
521 * \retval NULL on error.
522 */
rose_enc_qsig_AocInterim_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)523 unsigned char *rose_enc_qsig_AocInterim_ARG(struct pri *ctrl, unsigned char *pos,
524 unsigned char *end, const union rose_msg_invoke_args *args)
525 {
526 unsigned char *seq_len;
527 unsigned char *specific_len;
528 const struct roseQsigAocInterimArg_ARG *aoc_interim;
529
530 aoc_interim = &args->qsig.AocInterim;
531
532 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
533
534 switch (aoc_interim->type) {
535 case 0: /* charge_not_available */
536 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0));
537 break;
538 case 1: /* free_of_charge */
539 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
540 break;
541 case 2: /* specific_currency */
542 ASN1_CONSTRUCTED_BEGIN(specific_len, pos, end, ASN1_TAG_SEQUENCE);
543
544 ASN1_CALL(pos, rose_enc_qsig_AOC_RecordedCurrency(ctrl, pos, end,
545 ASN1_CLASS_CONTEXT_SPECIFIC | 1, &aoc_interim->specific.recorded));
546
547 if (aoc_interim->specific.billing_id_present) {
548 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
549 aoc_interim->specific.billing_id));
550 }
551
552 ASN1_CONSTRUCTED_END(specific_len, pos, end);
553 break;
554 default:
555 ASN1_ENC_ERROR(ctrl, "Unknown AocInterim type");
556 return NULL;
557 }
558
559 /* No extension to encode */
560
561 ASN1_CONSTRUCTED_END(seq_len, pos, end);
562
563 return pos;
564 }
565
566 /*!
567 * \brief Encode the Q.SIG AocRate invoke facility ie arguments.
568 *
569 * \param ctrl D channel controller for diagnostic messages or global options.
570 * \param pos Starting position to encode ASN.1 component.
571 * \param end End of ASN.1 encoding data buffer.
572 * \param args Arguments to encode in the buffer.
573 *
574 * \retval Start of the next ASN.1 component to encode on success.
575 * \retval NULL on error.
576 */
rose_enc_qsig_AocRate_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)577 unsigned char *rose_enc_qsig_AocRate_ARG(struct pri *ctrl, unsigned char *pos,
578 unsigned char *end, const union rose_msg_invoke_args *args)
579 {
580 unsigned char *seq_len;
581 const struct roseQsigAocRateArg_ARG *aoc_rate;
582
583 aoc_rate = &args->qsig.AocRate;
584
585 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
586
587 switch (aoc_rate->type) {
588 case 0: /* charge_not_available */
589 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
590 break;
591 case 1: /* currency_info_list */
592 ASN1_CALL(pos, rose_enc_qsig_AOCSCurrencyInfoList(ctrl, pos, end,
593 ASN1_TAG_SEQUENCE, &aoc_rate->currency_info));
594 break;
595 default:
596 ASN1_ENC_ERROR(ctrl, "Unknown AocRate type");
597 return NULL;
598 }
599
600 /* No extension to encode */
601
602 ASN1_CONSTRUCTED_END(seq_len, pos, end);
603
604 return pos;
605 }
606
607 /*!
608 * \brief Encode the Q.SIG AocComplete invoke facility ie arguments.
609 *
610 * \param ctrl D channel controller for diagnostic messages or global options.
611 * \param pos Starting position to encode ASN.1 component.
612 * \param end End of ASN.1 encoding data buffer.
613 * \param args Arguments to encode in the buffer.
614 *
615 * \retval Start of the next ASN.1 component to encode on success.
616 * \retval NULL on error.
617 */
rose_enc_qsig_AocComplete_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)618 unsigned char *rose_enc_qsig_AocComplete_ARG(struct pri *ctrl, unsigned char *pos,
619 unsigned char *end, const union rose_msg_invoke_args *args)
620 {
621 unsigned char *seq_len;
622 const struct roseQsigAocCompleteArg_ARG *aoc_complete;
623
624 aoc_complete = &args->qsig.AocComplete;
625
626 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
627
628 ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
629 &aoc_complete->charged_user_number));
630
631 if (aoc_complete->charging_association_present) {
632 ASN1_CALL(pos, rose_enc_qsig_AOC_ChargingAssociation(ctrl, pos, end,
633 &aoc_complete->charging_association));
634 }
635
636 /* No extension to encode */
637
638 ASN1_CONSTRUCTED_END(seq_len, pos, end);
639
640 return pos;
641 }
642
643 /*!
644 * \brief Encode the Q.SIG AocComplete result facility ie arguments.
645 *
646 * \param ctrl D channel controller for diagnostic messages or global options.
647 * \param pos Starting position to encode ASN.1 component.
648 * \param end End of ASN.1 encoding data buffer.
649 * \param args Arguments to encode in the buffer.
650 *
651 * \retval Start of the next ASN.1 component to encode on success.
652 * \retval NULL on error.
653 */
rose_enc_qsig_AocComplete_RES(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_result_args * args)654 unsigned char *rose_enc_qsig_AocComplete_RES(struct pri *ctrl, unsigned char *pos,
655 unsigned char *end, const union rose_msg_result_args *args)
656 {
657 unsigned char *seq_len;
658 const struct roseQsigAocCompleteRes_RES *aoc_complete;
659
660 aoc_complete = &args->qsig.AocComplete;
661
662 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
663
664 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
665 aoc_complete->charging_option));
666
667 /* No extension to encode */
668
669 ASN1_CONSTRUCTED_END(seq_len, pos, end);
670
671 return pos;
672 }
673
674 /*!
675 * \brief Encode the Q.SIG AocDivChargeReq invoke facility ie arguments.
676 *
677 * \param ctrl D channel controller for diagnostic messages or global options.
678 * \param pos Starting position to encode ASN.1 component.
679 * \param end End of ASN.1 encoding data buffer.
680 * \param args Arguments to encode in the buffer.
681 *
682 * \retval Start of the next ASN.1 component to encode on success.
683 * \retval NULL on error.
684 */
rose_enc_qsig_AocDivChargeReq_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)685 unsigned char *rose_enc_qsig_AocDivChargeReq_ARG(struct pri *ctrl, unsigned char *pos,
686 unsigned char *end, const union rose_msg_invoke_args *args)
687 {
688 unsigned char *seq_len;
689 const struct roseQsigAocDivChargeReqArg_ARG *aoc_div_charge_req;
690
691 aoc_div_charge_req = &args->qsig.AocDivChargeReq;
692
693 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
694
695 ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
696 &aoc_div_charge_req->diverting_user_number));
697
698 if (aoc_div_charge_req->charging_association_present) {
699 ASN1_CALL(pos, rose_enc_qsig_AOC_ChargingAssociation(ctrl, pos, end,
700 &aoc_div_charge_req->charging_association));
701 }
702
703 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
704 aoc_div_charge_req->diversion_type));
705
706 /* No extension to encode */
707
708 ASN1_CONSTRUCTED_END(seq_len, pos, end);
709
710 return pos;
711 }
712
713 /*!
714 * \internal
715 * \brief Decode the Time type.
716 *
717 * \param ctrl D channel controller for diagnostic messages or global options.
718 * \param name Field name
719 * \param tag Component tag that identified this production.
720 * \param pos Starting position of the ASN.1 component length.
721 * \param end End of ASN.1 decoding data buffer.
722 * \param time Parameter storage to fill.
723 *
724 * \retval Start of the next ASN.1 component on success.
725 * \retval NULL on error.
726 */
rose_dec_qsig_AOC_Time(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseQsigAOCTime * time)727 static const unsigned char *rose_dec_qsig_AOC_Time(struct pri *ctrl, const char *name,
728 unsigned tag, const unsigned char *pos, const unsigned char *end,
729 struct roseQsigAOCTime *time)
730 {
731 int32_t value;
732 int length;
733 int seq_offset;
734 const unsigned char *seq_end;
735
736 if (ctrl->debug & PRI_DEBUG_APDU) {
737 pri_message(ctrl, " %s Time %s\n", name, asn1_tag2str(tag));
738 }
739 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
740 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
741
742 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
743 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
744 ASN1_CALL(pos, asn1_dec_int(ctrl, "lengthOfTimeUnit", tag, pos, seq_end, &value));
745 time->length = value;
746
747 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
748 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
749 ASN1_CALL(pos, asn1_dec_int(ctrl, "scale", tag, pos, seq_end, &value));
750 time->scale = value;
751
752 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
753
754 return pos;
755 }
756
757 /*!
758 * \internal
759 * \brief Decode the Amount type.
760 *
761 * \param ctrl D channel controller for diagnostic messages or global options.
762 * \param name Field name
763 * \param tag Component tag that identified this production.
764 * \param pos Starting position of the ASN.1 component length.
765 * \param end End of ASN.1 decoding data buffer.
766 * \param amount Parameter storage to fill.
767 *
768 * \retval Start of the next ASN.1 component on success.
769 * \retval NULL on error.
770 */
rose_dec_qsig_AOC_Amount(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseQsigAOCAmount * amount)771 static const unsigned char *rose_dec_qsig_AOC_Amount(struct pri *ctrl, const char *name,
772 unsigned tag, const unsigned char *pos, const unsigned char *end,
773 struct roseQsigAOCAmount *amount)
774 {
775 int32_t value;
776 int length;
777 int seq_offset;
778 const unsigned char *seq_end;
779
780 if (ctrl->debug & PRI_DEBUG_APDU) {
781 pri_message(ctrl, " %s Amount %s\n", name, asn1_tag2str(tag));
782 }
783 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
784 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
785
786 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
787 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
788 ASN1_CALL(pos, asn1_dec_int(ctrl, "currencyAmount", tag, pos, seq_end, &value));
789 amount->currency = value;
790
791 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
792 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
793 ASN1_CALL(pos, asn1_dec_int(ctrl, "multiplier", tag, pos, seq_end, &value));
794 amount->multiplier = value;
795
796 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
797
798 return pos;
799 }
800
801 /*!
802 * \internal
803 * \brief Decode the RecordedCurrency type.
804 *
805 * \param ctrl D channel controller for diagnostic messages or global options.
806 * \param name Field name
807 * \param tag Component tag that identified this production.
808 * \param pos Starting position of the ASN.1 component length.
809 * \param end End of ASN.1 decoding data buffer.
810 * \param recorded Parameter storage to fill.
811 *
812 * \retval Start of the next ASN.1 component on success.
813 * \retval NULL on error.
814 */
rose_dec_qsig_AOC_RecordedCurrency(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseQsigAOCRecordedCurrency * recorded)815 static const unsigned char *rose_dec_qsig_AOC_RecordedCurrency(struct pri *ctrl,
816 const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
817 struct roseQsigAOCRecordedCurrency *recorded)
818 {
819 int length;
820 int seq_offset;
821 const unsigned char *seq_end;
822 size_t str_len;
823
824 if (ctrl->debug & PRI_DEBUG_APDU) {
825 pri_message(ctrl, " %s RecordedCurrency %s\n", name, asn1_tag2str(tag));
826 }
827 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
828 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
829
830 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
831 ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
832 ASN1_CALL(pos, asn1_dec_string_max(ctrl, "rCurrency", tag, pos, seq_end,
833 sizeof(recorded->currency), recorded->currency, &str_len));
834
835 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
836 ASN1_CHECK_TAG(ctrl, tag, tag,
837 ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
838 ASN1_CALL(pos, rose_dec_qsig_AOC_Amount(ctrl, "rAmount", tag, pos, seq_end,
839 &recorded->amount));
840
841 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
842
843 return pos;
844 }
845
846 /*!
847 * \internal
848 * \brief Decode the DurationCurrency type.
849 *
850 * \param ctrl D channel controller for diagnostic messages or global options.
851 * \param name Field name
852 * \param tag Component tag that identified this production.
853 * \param pos Starting position of the ASN.1 component length.
854 * \param end End of ASN.1 decoding data buffer.
855 * \param duration Parameter storage to fill.
856 *
857 * \retval Start of the next ASN.1 component on success.
858 * \retval NULL on error.
859 */
rose_dec_qsig_AOC_DurationCurrency(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseQsigAOCDurationCurrency * duration)860 static const unsigned char *rose_dec_qsig_AOC_DurationCurrency(struct pri *ctrl,
861 const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
862 struct roseQsigAOCDurationCurrency *duration)
863 {
864 int32_t value;
865 int length;
866 int seq_offset;
867 const unsigned char *seq_end;
868 size_t str_len;
869
870 if (ctrl->debug & PRI_DEBUG_APDU) {
871 pri_message(ctrl, " %s DurationCurrency %s\n", name, asn1_tag2str(tag));
872 }
873 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
874 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
875
876 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
877 ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
878 ASN1_CALL(pos, asn1_dec_string_max(ctrl, "dCurrency", tag, pos, seq_end,
879 sizeof(duration->currency), duration->currency, &str_len));
880
881 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
882 ASN1_CHECK_TAG(ctrl, tag, tag,
883 ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
884 ASN1_CALL(pos, rose_dec_qsig_AOC_Amount(ctrl, "dAmount", tag, pos, seq_end,
885 &duration->amount));
886
887 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
888 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
889 ASN1_CALL(pos, asn1_dec_int(ctrl, "dChargingType", tag, pos, seq_end, &value));
890 duration->charging_type = value;
891
892 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
893 ASN1_CHECK_TAG(ctrl, tag, tag,
894 ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 4);
895 ASN1_CALL(pos, rose_dec_qsig_AOC_Time(ctrl, "dTime", tag, pos, seq_end,
896 &duration->time));
897
898 if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
899 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
900 ASN1_CHECK_TAG(ctrl, tag, tag,
901 ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 5);
902 ASN1_CALL(pos, rose_dec_qsig_AOC_Time(ctrl, "dGranularity", tag, pos, seq_end,
903 &duration->granularity));
904 duration->granularity_present = 1;
905 } else {
906 duration->granularity_present = 0;
907 }
908
909 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
910
911 return pos;
912 }
913
914 /*!
915 * \internal
916 * \brief Decode the FlatRateCurrency type.
917 *
918 * \param ctrl D channel controller for diagnostic messages or global options.
919 * \param name Field name
920 * \param tag Component tag that identified this production.
921 * \param pos Starting position of the ASN.1 component length.
922 * \param end End of ASN.1 decoding data buffer.
923 * \param flat_rate Parameter storage to fill.
924 *
925 * \retval Start of the next ASN.1 component on success.
926 * \retval NULL on error.
927 */
rose_dec_qsig_AOC_FlatRateCurrency(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseQsigAOCFlatRateCurrency * flat_rate)928 static const unsigned char *rose_dec_qsig_AOC_FlatRateCurrency(struct pri *ctrl,
929 const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
930 struct roseQsigAOCFlatRateCurrency *flat_rate)
931 {
932 int length;
933 int seq_offset;
934 const unsigned char *seq_end;
935 size_t str_len;
936
937 if (ctrl->debug & PRI_DEBUG_APDU) {
938 pri_message(ctrl, " %s FlatRateCurrency %s\n", name, asn1_tag2str(tag));
939 }
940 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
941 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
942
943 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
944 ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
945 ASN1_CALL(pos, asn1_dec_string_max(ctrl, "fRCurrency", tag, pos, seq_end,
946 sizeof(flat_rate->currency), flat_rate->currency, &str_len));
947
948 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
949 ASN1_CHECK_TAG(ctrl, tag, tag,
950 ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
951 ASN1_CALL(pos, rose_dec_qsig_AOC_Amount(ctrl, "fRAmount", tag, pos, seq_end,
952 &flat_rate->amount));
953
954 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
955
956 return pos;
957 }
958
959 /*!
960 * \internal
961 * \brief Decode the VolumeRateCurrency type.
962 *
963 * \param ctrl D channel controller for diagnostic messages or global options.
964 * \param name Field name
965 * \param tag Component tag that identified this production.
966 * \param pos Starting position of the ASN.1 component length.
967 * \param end End of ASN.1 decoding data buffer.
968 * \param volume_rate Parameter storage to fill.
969 *
970 * \retval Start of the next ASN.1 component on success.
971 * \retval NULL on error.
972 */
rose_dec_qsig_AOC_VolumeRateCurrency(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseQsigAOCVolumeRateCurrency * volume_rate)973 static const unsigned char *rose_dec_qsig_AOC_VolumeRateCurrency(struct pri *ctrl,
974 const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
975 struct roseQsigAOCVolumeRateCurrency *volume_rate)
976 {
977 int32_t value;
978 int length;
979 int seq_offset;
980 const unsigned char *seq_end;
981 size_t str_len;
982
983 if (ctrl->debug & PRI_DEBUG_APDU) {
984 pri_message(ctrl, " %s VolumeRateCurrency %s\n", name, asn1_tag2str(tag));
985 }
986 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
987 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
988
989 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
990 ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
991 ASN1_CALL(pos, asn1_dec_string_max(ctrl, "vRCurrency", tag, pos, seq_end,
992 sizeof(volume_rate->currency), volume_rate->currency, &str_len));
993
994 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
995 ASN1_CHECK_TAG(ctrl, tag, tag,
996 ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
997 ASN1_CALL(pos, rose_dec_qsig_AOC_Amount(ctrl, "vRAmount", tag, pos, seq_end,
998 &volume_rate->amount));
999
1000 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1001 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
1002 ASN1_CALL(pos, asn1_dec_int(ctrl, "vRVolumeUnit", tag, pos, seq_end, &value));
1003 volume_rate->unit = value;
1004
1005 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1006
1007 return pos;
1008 }
1009
1010 /*!
1011 * \internal
1012 * \brief Decode the AOCSCurrencyInfo type.
1013 *
1014 * \param ctrl D channel controller for diagnostic messages or global options.
1015 * \param name Field name
1016 * \param tag Component tag that identified this production.
1017 * \param pos Starting position of the ASN.1 component length.
1018 * \param end End of ASN.1 decoding data buffer.
1019 * \param currency_info Parameter storage to fill.
1020 *
1021 * \retval Start of the next ASN.1 component on success.
1022 * \retval NULL on error.
1023 */
rose_dec_qsig_AOCSCurrencyInfo(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseQsigAOCSCurrencyInfo * currency_info)1024 static const unsigned char *rose_dec_qsig_AOCSCurrencyInfo(struct pri *ctrl,
1025 const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
1026 struct roseQsigAOCSCurrencyInfo *currency_info)
1027 {
1028 int32_t value;
1029 int length;
1030 int seq_offset;
1031 const unsigned char *seq_end;
1032
1033 if (ctrl->debug & PRI_DEBUG_APDU) {
1034 pri_message(ctrl, " %s AOCSCurrencyInfo %s\n", name, asn1_tag2str(tag));
1035 }
1036 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1037 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
1038
1039 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1040 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
1041 ASN1_CALL(pos, asn1_dec_int(ctrl, "chargedItem", tag, pos, seq_end, &value));
1042 currency_info->charged_item = value;
1043
1044 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1045 switch (tag) {
1046 case ASN1_TYPE_INTEGER:
1047 currency_info->currency_type = 0; /* specialChargingCode */
1048 ASN1_CALL(pos, asn1_dec_int(ctrl, "specialChargingCode", tag, pos, seq_end,
1049 &value));
1050 currency_info->u.special_charging_code = value;
1051 break;
1052 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
1053 currency_info->currency_type = 1; /* durationCurrency */
1054 ASN1_CALL(pos, rose_dec_qsig_AOC_DurationCurrency(ctrl, "durationCurrency", tag,
1055 pos, seq_end, ¤cy_info->u.duration));
1056 break;
1057 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
1058 currency_info->currency_type = 2; /* flatRateCurrency */
1059 ASN1_CALL(pos, rose_dec_qsig_AOC_FlatRateCurrency(ctrl, "flatRateCurrency", tag,
1060 pos, seq_end, ¤cy_info->u.flat_rate));
1061 break;
1062 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
1063 currency_info->currency_type = 3; /* volumeRateCurrency */
1064 ASN1_CALL(pos, rose_dec_qsig_AOC_VolumeRateCurrency(ctrl, "volumeRateCurrency",
1065 tag, pos, seq_end, ¤cy_info->u.volume_rate));
1066 break;
1067 case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
1068 currency_info->currency_type = 4; /* freeOfCharge */
1069 ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, seq_end));
1070 break;
1071 case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
1072 currency_info->currency_type = 5; /* currencyInfoNotAvailable */
1073 ASN1_CALL(pos, asn1_dec_null(ctrl, "currencyInfoNotAvailable", tag, pos,
1074 seq_end));
1075 break;
1076 case ASN1_CLASS_CONTEXT_SPECIFIC | 6:
1077 currency_info->currency_type = 6; /* freeOfChargeFromBeginning */
1078 ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfChargeFromBeginning", tag, pos,
1079 seq_end));
1080 break;
1081 default:
1082 ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
1083 return NULL;
1084 }
1085
1086 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1087
1088 return pos;
1089 }
1090
1091 /*!
1092 * \internal
1093 * \brief Decode the AOCSCurrencyInfoList type.
1094 *
1095 * \param ctrl D channel controller for diagnostic messages or global options.
1096 * \param name Field name
1097 * \param tag Component tag that identified this production.
1098 * \param pos Starting position of the ASN.1 component length.
1099 * \param end End of ASN.1 decoding data buffer.
1100 * \param currency_info Parameter storage to fill.
1101 *
1102 * \retval Start of the next ASN.1 component on success.
1103 * \retval NULL on error.
1104 */
rose_dec_qsig_AOCSCurrencyInfoList(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseQsigAOCSCurrencyInfoList * currency_info)1105 static const unsigned char *rose_dec_qsig_AOCSCurrencyInfoList(struct pri *ctrl,
1106 const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
1107 struct roseQsigAOCSCurrencyInfoList *currency_info)
1108 {
1109 int length;
1110 int seq_offset;
1111 const unsigned char *seq_end;
1112
1113 if (ctrl->debug & PRI_DEBUG_APDU) {
1114 pri_message(ctrl, " %s AOCSCurrencyInfoList %s\n", name, asn1_tag2str(tag));
1115 }
1116 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1117 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
1118
1119 currency_info->num_records = 0;
1120 while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
1121 if (currency_info->num_records < ARRAY_LEN(currency_info->list)) {
1122 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1123 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
1124 ASN1_CALL(pos, rose_dec_qsig_AOCSCurrencyInfo(ctrl, "listEntry", tag, pos,
1125 seq_end, ¤cy_info->list[currency_info->num_records]));
1126 ++currency_info->num_records;
1127 } else {
1128 /* Too many records */
1129 return NULL;
1130 }
1131 }
1132
1133 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1134
1135 return pos;
1136 }
1137
1138 /*!
1139 * \internal
1140 * \brief Decode the ChargingAssociation type.
1141 *
1142 * \param ctrl D channel controller for diagnostic messages or global options.
1143 * \param name Field name
1144 * \param tag Component tag that identified this production.
1145 * \param pos Starting position of the ASN.1 component length.
1146 * \param end End of ASN.1 decoding data buffer.
1147 * \param charging Parameter storage to fill.
1148 *
1149 * \retval Start of the next ASN.1 component on success.
1150 * \retval NULL on error.
1151 */
rose_dec_qsig_AOC_ChargingAssociation(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseQsigAOCChargingAssociation * charging)1152 static const unsigned char *rose_dec_qsig_AOC_ChargingAssociation(struct pri *ctrl,
1153 const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
1154 struct roseQsigAOCChargingAssociation *charging)
1155 {
1156 int32_t value;
1157 int length;
1158 int explicit_offset;
1159 const unsigned char *explicit_end;
1160
1161 if (ctrl->debug & PRI_DEBUG_APDU) {
1162 pri_message(ctrl, " %s ChargingAssociation\n", name);
1163 }
1164 switch (tag) {
1165 case ASN1_TYPE_INTEGER:
1166 charging->type = 0; /* charge_identifier */
1167 ASN1_CALL(pos, asn1_dec_int(ctrl, "chargeIdentifier", tag, pos, end, &value));
1168 charging->id = value;
1169 break;
1170 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
1171 charging->type = 1; /* charged_number */
1172
1173 /* Remove EXPLICIT tag */
1174 if (ctrl->debug & PRI_DEBUG_APDU) {
1175 pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
1176 }
1177 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1178 ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, end);
1179
1180 ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
1181 ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "chargedNumber", tag, pos,
1182 explicit_end, &charging->number));
1183
1184 ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, end);
1185 break;
1186 default:
1187 ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
1188 return NULL;
1189 }
1190
1191 return pos;
1192 }
1193
1194 /*!
1195 * \brief Decode the Q.SIG ChargeRequest invoke argument parameters.
1196 *
1197 * \param ctrl D channel controller for diagnostic messages or global options.
1198 * \param tag Component tag that identified this structure.
1199 * \param pos Starting position of the ASN.1 component length.
1200 * \param end End of ASN.1 decoding data buffer.
1201 * \param args Arguments to fill in from the decoded buffer.
1202 *
1203 * \retval Start of the next ASN.1 component on success.
1204 * \retval NULL on error.
1205 */
rose_dec_qsig_ChargeRequest_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)1206 const unsigned char *rose_dec_qsig_ChargeRequest_ARG(struct pri *ctrl, unsigned tag,
1207 const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
1208 {
1209 int32_t value;
1210 int length;
1211 int seq_offset;
1212 int advice_offset;
1213 const unsigned char *seq_end;
1214 const unsigned char *advice_end;
1215 struct roseQsigChargeRequestArg_ARG *charge_request;
1216
1217 charge_request = &args->qsig.ChargeRequest;
1218
1219 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
1220 if (ctrl->debug & PRI_DEBUG_APDU) {
1221 pri_message(ctrl, " ChargeRequest %s\n", asn1_tag2str(tag));
1222 }
1223 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1224 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
1225
1226 /* SEQUENCE SIZE(0..7) OF AdviceModeCombination */
1227 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1228 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
1229 if (ctrl->debug & PRI_DEBUG_APDU) {
1230 pri_message(ctrl, " adviceModeCombinations %s\n", asn1_tag2str(tag));
1231 }
1232 ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
1233 ASN1_END_SETUP(advice_end, advice_offset, length, pos, seq_end);
1234
1235 /* Decode SIZE(0..7) OF AdviceModeCombination */
1236 charge_request->num_records = 0;
1237 while (pos < advice_end && *pos != ASN1_INDEF_TERM) {
1238 if (charge_request->num_records <
1239 ARRAY_LEN(charge_request->advice_mode_combinations)) {
1240 ASN1_CALL(pos, asn1_dec_tag(pos, advice_end, &tag));
1241 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
1242 ASN1_CALL(pos, asn1_dec_int(ctrl, "adviceModeCombination", tag, pos,
1243 advice_end, &value));
1244 charge_request->advice_mode_combinations[charge_request->num_records] =
1245 value;
1246 ++charge_request->num_records;
1247 } else {
1248 /* Too many records */
1249 return NULL;
1250 }
1251 }
1252
1253 ASN1_END_FIXUP(ctrl, pos, advice_offset, advice_end, seq_end);
1254
1255 /* Fixup will skip over any OPTIONAL manufacturer extension information */
1256 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1257
1258 return pos;
1259 }
1260
1261 /*!
1262 * \brief Decode the Q.SIG ChargeRequest result argument parameters.
1263 *
1264 * \param ctrl D channel controller for diagnostic messages or global options.
1265 * \param tag Component tag that identified this structure.
1266 * \param pos Starting position of the ASN.1 component length.
1267 * \param end End of ASN.1 decoding data buffer.
1268 * \param args Arguments to fill in from the decoded buffer.
1269 *
1270 * \retval Start of the next ASN.1 component on success.
1271 * \retval NULL on error.
1272 */
rose_dec_qsig_ChargeRequest_RES(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_result_args * args)1273 const unsigned char *rose_dec_qsig_ChargeRequest_RES(struct pri *ctrl, unsigned tag,
1274 const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
1275 {
1276 int32_t value;
1277 int length;
1278 int seq_offset;
1279 const unsigned char *seq_end;
1280 struct roseQsigChargeRequestRes_RES *charge_request;
1281
1282 charge_request = &args->qsig.ChargeRequest;
1283
1284 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
1285 if (ctrl->debug & PRI_DEBUG_APDU) {
1286 pri_message(ctrl, " ChargeRequest %s\n", asn1_tag2str(tag));
1287 }
1288 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1289 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
1290
1291 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1292 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
1293 ASN1_CALL(pos, asn1_dec_int(ctrl, "adviceModeCombination", tag, pos, seq_end,
1294 &value));
1295 charge_request->advice_mode_combination = value;
1296
1297 /* Fixup will skip over any OPTIONAL manufacturer extension information */
1298 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1299
1300 return pos;
1301 }
1302
1303 /*!
1304 * \brief Decode the Q.SIG AocFinal invoke argument parameters.
1305 *
1306 * \param ctrl D channel controller for diagnostic messages or global options.
1307 * \param tag Component tag that identified this structure.
1308 * \param pos Starting position of the ASN.1 component length.
1309 * \param end End of ASN.1 decoding data buffer.
1310 * \param args Arguments to fill in from the decoded buffer.
1311 *
1312 * \retval Start of the next ASN.1 component on success.
1313 * \retval NULL on error.
1314 */
rose_dec_qsig_AocFinal_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)1315 const unsigned char *rose_dec_qsig_AocFinal_ARG(struct pri *ctrl, unsigned tag,
1316 const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
1317 {
1318 int32_t value;
1319 int length;
1320 int seq_offset;
1321 int specific_offset;
1322 const unsigned char *seq_end;
1323 const unsigned char *specific_end;
1324 const unsigned char *save_pos;
1325 struct roseQsigAocFinalArg_ARG *aoc_final;
1326
1327 aoc_final = &args->qsig.AocFinal;
1328
1329 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
1330 if (ctrl->debug & PRI_DEBUG_APDU) {
1331 pri_message(ctrl, " AocFinal %s\n", asn1_tag2str(tag));
1332 }
1333 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1334 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
1335
1336 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1337 switch (tag) {
1338 case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
1339 aoc_final->type = 0; /* charge_not_available */
1340 ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, seq_end));
1341 break;
1342 case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
1343 aoc_final->type = 1; /* free_of_charge */
1344 ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, seq_end));
1345 break;
1346 case ASN1_TAG_SEQUENCE:
1347 aoc_final->type = 2; /* specific_currency */
1348 if (ctrl->debug & PRI_DEBUG_APDU) {
1349 pri_message(ctrl, " specificCurrency %s\n", asn1_tag2str(tag));
1350 }
1351 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1352 ASN1_END_SETUP(specific_end, specific_offset, length, pos, seq_end);
1353
1354 ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
1355 ASN1_CHECK_TAG(ctrl, tag, tag,
1356 ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
1357 ASN1_CALL(pos, rose_dec_qsig_AOC_RecordedCurrency(ctrl, "recordedCurrency", tag,
1358 pos, specific_end, &aoc_final->specific.recorded));
1359
1360 if (pos < specific_end && *pos != ASN1_INDEF_TERM) {
1361 ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
1362 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
1363 ASN1_CALL(pos, asn1_dec_int(ctrl, "finalBillingId", tag, pos, specific_end,
1364 &value));
1365 aoc_final->specific.billing_id = value;
1366 aoc_final->specific.billing_id_present = 1;
1367 } else {
1368 aoc_final->specific.billing_id_present = 0;
1369 }
1370
1371 ASN1_END_FIXUP(ctrl, pos, specific_offset, specific_end, seq_end);
1372 break;
1373 default:
1374 ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
1375 return NULL;
1376 }
1377
1378 /*
1379 * A sequence specifies an ordered list of component types.
1380 * However, for simplicity we are not checking the order of
1381 * the remaining optional components.
1382 */
1383 aoc_final->charging_association_present = 0;
1384 while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
1385 save_pos = pos;
1386 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1387 switch (tag) {
1388 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
1389 case ASN1_TYPE_INTEGER:
1390 ASN1_CALL(pos, rose_dec_qsig_AOC_ChargingAssociation(ctrl,
1391 "chargingAssociation", tag, pos, seq_end,
1392 &aoc_final->charging_association));
1393 aoc_final->charging_association_present = 1;
1394 break;
1395 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
1396 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
1397 if (ctrl->debug & PRI_DEBUG_APDU) {
1398 pri_message(ctrl, " finalArgExtension %s\n", asn1_tag2str(tag));
1399 }
1400 /* Fixup will skip over the manufacturer extension information */
1401 default:
1402 pos = save_pos;
1403 goto cancel_options;
1404 }
1405 }
1406 cancel_options:;
1407
1408 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1409
1410 return pos;
1411 }
1412
1413 /*!
1414 * \brief Decode the Q.SIG AocInterim invoke argument parameters.
1415 *
1416 * \param ctrl D channel controller for diagnostic messages or global options.
1417 * \param tag Component tag that identified this structure.
1418 * \param pos Starting position of the ASN.1 component length.
1419 * \param end End of ASN.1 decoding data buffer.
1420 * \param args Arguments to fill in from the decoded buffer.
1421 *
1422 * \retval Start of the next ASN.1 component on success.
1423 * \retval NULL on error.
1424 */
rose_dec_qsig_AocInterim_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)1425 const unsigned char *rose_dec_qsig_AocInterim_ARG(struct pri *ctrl, unsigned tag,
1426 const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
1427 {
1428 int32_t value;
1429 int length;
1430 int seq_offset;
1431 int specific_offset;
1432 const unsigned char *seq_end;
1433 const unsigned char *specific_end;
1434 struct roseQsigAocInterimArg_ARG *aoc_interim;
1435
1436 aoc_interim = &args->qsig.AocInterim;
1437
1438 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
1439 if (ctrl->debug & PRI_DEBUG_APDU) {
1440 pri_message(ctrl, " AocInterim %s\n", asn1_tag2str(tag));
1441 }
1442 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1443 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
1444
1445 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1446 switch (tag) {
1447 case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
1448 aoc_interim->type = 0; /* charge_not_available */
1449 ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, seq_end));
1450 break;
1451 case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
1452 aoc_interim->type = 1; /* free_of_charge */
1453 ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, seq_end));
1454 break;
1455 case ASN1_TAG_SEQUENCE:
1456 aoc_interim->type = 2; /* specific_currency */
1457 if (ctrl->debug & PRI_DEBUG_APDU) {
1458 pri_message(ctrl, " specificCurrency %s\n", asn1_tag2str(tag));
1459 }
1460 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1461 ASN1_END_SETUP(specific_end, specific_offset, length, pos, seq_end);
1462
1463 ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
1464 ASN1_CHECK_TAG(ctrl, tag, tag,
1465 ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
1466 ASN1_CALL(pos, rose_dec_qsig_AOC_RecordedCurrency(ctrl, "recordedCurrency", tag,
1467 pos, specific_end, &aoc_interim->specific.recorded));
1468
1469 if (pos < specific_end && *pos != ASN1_INDEF_TERM) {
1470 ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
1471 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
1472 ASN1_CALL(pos, asn1_dec_int(ctrl, "interimBillingId", tag, pos, specific_end,
1473 &value));
1474 aoc_interim->specific.billing_id = value;
1475 aoc_interim->specific.billing_id_present = 1;
1476 } else {
1477 aoc_interim->specific.billing_id_present = 0;
1478 }
1479
1480 ASN1_END_FIXUP(ctrl, pos, specific_offset, specific_end, seq_end);
1481 break;
1482 default:
1483 ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
1484 return NULL;
1485 }
1486
1487 /* Fixup will skip over any OPTIONAL manufacturer extension information */
1488 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1489
1490 return pos;
1491 }
1492
1493 /*!
1494 * \brief Decode the Q.SIG AocRate invoke argument parameters.
1495 *
1496 * \param ctrl D channel controller for diagnostic messages or global options.
1497 * \param tag Component tag that identified this structure.
1498 * \param pos Starting position of the ASN.1 component length.
1499 * \param end End of ASN.1 decoding data buffer.
1500 * \param args Arguments to fill in from the decoded buffer.
1501 *
1502 * \retval Start of the next ASN.1 component on success.
1503 * \retval NULL on error.
1504 */
rose_dec_qsig_AocRate_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)1505 const unsigned char *rose_dec_qsig_AocRate_ARG(struct pri *ctrl, unsigned tag,
1506 const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
1507 {
1508 int length;
1509 int seq_offset;
1510 const unsigned char *seq_end;
1511 struct roseQsigAocRateArg_ARG *aoc_rate;
1512
1513 aoc_rate = &args->qsig.AocRate;
1514
1515 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
1516 if (ctrl->debug & PRI_DEBUG_APDU) {
1517 pri_message(ctrl, " AocRate %s\n", asn1_tag2str(tag));
1518 }
1519 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1520 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
1521
1522 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1523 switch (tag) {
1524 case ASN1_TYPE_NULL:
1525 aoc_rate->type = 0; /* charge_not_available */
1526 ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, seq_end));
1527 break;
1528 case ASN1_TAG_SEQUENCE:
1529 aoc_rate->type = 1; /* currency_info_list */
1530 ASN1_CALL(pos, rose_dec_qsig_AOCSCurrencyInfoList(ctrl, "aocSCurrencyInfoList",
1531 tag, pos, seq_end, &aoc_rate->currency_info));
1532 break;
1533 default:
1534 ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
1535 return NULL;
1536 }
1537
1538 /* Fixup will skip over any OPTIONAL manufacturer extension information */
1539 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1540
1541 return pos;
1542 }
1543
1544 /*!
1545 * \brief Decode the Q.SIG AocComplete invoke argument parameters.
1546 *
1547 * \param ctrl D channel controller for diagnostic messages or global options.
1548 * \param tag Component tag that identified this structure.
1549 * \param pos Starting position of the ASN.1 component length.
1550 * \param end End of ASN.1 decoding data buffer.
1551 * \param args Arguments to fill in from the decoded buffer.
1552 *
1553 * \retval Start of the next ASN.1 component on success.
1554 * \retval NULL on error.
1555 */
rose_dec_qsig_AocComplete_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)1556 const unsigned char *rose_dec_qsig_AocComplete_ARG(struct pri *ctrl, unsigned tag,
1557 const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
1558 {
1559 int length;
1560 int seq_offset;
1561 const unsigned char *seq_end;
1562 const unsigned char *save_pos;
1563 struct roseQsigAocCompleteArg_ARG *aoc_complete;
1564
1565 aoc_complete = &args->qsig.AocComplete;
1566
1567 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
1568 if (ctrl->debug & PRI_DEBUG_APDU) {
1569 pri_message(ctrl, " AocComplete %s\n", asn1_tag2str(tag));
1570 }
1571 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1572 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
1573
1574 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1575 ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "chargedUser", tag, pos, seq_end,
1576 &aoc_complete->charged_user_number));
1577
1578 /*
1579 * A sequence specifies an ordered list of component types.
1580 * However, for simplicity we are not checking the order of
1581 * the remaining optional components.
1582 */
1583 aoc_complete->charging_association_present = 0;
1584 while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
1585 save_pos = pos;
1586 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1587 switch (tag) {
1588 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
1589 case ASN1_TYPE_INTEGER:
1590 ASN1_CALL(pos, rose_dec_qsig_AOC_ChargingAssociation(ctrl,
1591 "chargingAssociation", tag, pos, seq_end,
1592 &aoc_complete->charging_association));
1593 aoc_complete->charging_association_present = 1;
1594 break;
1595 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
1596 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
1597 if (ctrl->debug & PRI_DEBUG_APDU) {
1598 pri_message(ctrl, " completeArgExtension %s\n", asn1_tag2str(tag));
1599 }
1600 /* Fixup will skip over the manufacturer extension information */
1601 default:
1602 pos = save_pos;
1603 goto cancel_options;
1604 }
1605 }
1606 cancel_options:;
1607
1608 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1609
1610 return pos;
1611 }
1612
1613 /*!
1614 * \brief Decode the Q.SIG AocComplete result argument parameters.
1615 *
1616 * \param ctrl D channel controller for diagnostic messages or global options.
1617 * \param tag Component tag that identified this structure.
1618 * \param pos Starting position of the ASN.1 component length.
1619 * \param end End of ASN.1 decoding data buffer.
1620 * \param args Arguments to fill in from the decoded buffer.
1621 *
1622 * \retval Start of the next ASN.1 component on success.
1623 * \retval NULL on error.
1624 */
rose_dec_qsig_AocComplete_RES(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_result_args * args)1625 const unsigned char *rose_dec_qsig_AocComplete_RES(struct pri *ctrl, unsigned tag,
1626 const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
1627 {
1628 int32_t value;
1629 int length;
1630 int seq_offset;
1631 const unsigned char *seq_end;
1632 struct roseQsigAocCompleteRes_RES *aoc_complete;
1633
1634 aoc_complete = &args->qsig.AocComplete;
1635
1636 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
1637 if (ctrl->debug & PRI_DEBUG_APDU) {
1638 pri_message(ctrl, " AocComplete %s\n", asn1_tag2str(tag));
1639 }
1640 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1641 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
1642
1643 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1644 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
1645 ASN1_CALL(pos, asn1_dec_int(ctrl, "chargingOption", tag, pos, seq_end, &value));
1646 aoc_complete->charging_option = value;
1647
1648 /* Fixup will skip over any OPTIONAL manufacturer extension information */
1649 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1650
1651 return pos;
1652 }
1653
1654 /*!
1655 * \brief Decode the Q.SIG AocDivChargeReq invoke argument parameters.
1656 *
1657 * \param ctrl D channel controller for diagnostic messages or global options.
1658 * \param tag Component tag that identified this structure.
1659 * \param pos Starting position of the ASN.1 component length.
1660 * \param end End of ASN.1 decoding data buffer.
1661 * \param args Arguments to fill in from the decoded buffer.
1662 *
1663 * \retval Start of the next ASN.1 component on success.
1664 * \retval NULL on error.
1665 */
rose_dec_qsig_AocDivChargeReq_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)1666 const unsigned char *rose_dec_qsig_AocDivChargeReq_ARG(struct pri *ctrl, unsigned tag,
1667 const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
1668 {
1669 int32_t value;
1670 int length;
1671 int seq_offset;
1672 const unsigned char *seq_end;
1673 struct roseQsigAocDivChargeReqArg_ARG *aoc_div_charge_req;
1674
1675 aoc_div_charge_req = &args->qsig.AocDivChargeReq;
1676
1677 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
1678 if (ctrl->debug & PRI_DEBUG_APDU) {
1679 pri_message(ctrl, " AocDivChargeReq %s\n", asn1_tag2str(tag));
1680 }
1681 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1682 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
1683
1684 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1685 ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "divertingUser", tag, pos, seq_end,
1686 &aoc_div_charge_req->diverting_user_number));
1687
1688 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1689 switch (tag) {
1690 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
1691 case ASN1_TYPE_INTEGER:
1692 ASN1_CALL(pos, rose_dec_qsig_AOC_ChargingAssociation(ctrl, "chargingAssociation",
1693 tag, pos, seq_end, &aoc_div_charge_req->charging_association));
1694 aoc_div_charge_req->charging_association_present = 1;
1695
1696 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1697 break;
1698 default:
1699 aoc_div_charge_req->charging_association_present = 0;
1700 break;
1701 }
1702
1703 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
1704 ASN1_CALL(pos, asn1_dec_int(ctrl, "diversionType", tag, pos, seq_end, &value));
1705 aoc_div_charge_req->diversion_type = value;
1706
1707 /* Fixup will skip over any OPTIONAL manufacturer extension information */
1708 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1709
1710 return pos;
1711 }
1712
1713 /* ------------------------------------------------------------------- */
1714 /* end rose_qsig_aoc.c */
1715