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 SS-MWI-Operations
30 *
31 * SS-MWI-Operations ECMA-242 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 MsgCentreId 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 msg_centre_id
55 *
56 * \retval Start of the next ASN.1 component to encode on success.
57 * \retval NULL on error.
58 */
rose_enc_qsig_MsgCentreId(struct pri * ctrl,unsigned char * pos,unsigned char * end,const struct roseQsigMsgCentreId * msg_centre_id)59 static unsigned char *rose_enc_qsig_MsgCentreId(struct pri *ctrl, unsigned char *pos,
60 unsigned char *end, const struct roseQsigMsgCentreId *msg_centre_id)
61 {
62 unsigned char *seq_len;
63
64 switch (msg_centre_id->type) {
65 case 0: /* integer */
66 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
67 msg_centre_id->u.integer));
68 break;
69 case 1: /* partyNumber */
70 /* EXPLICIT tag */
71 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
72 ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &msg_centre_id->u.number));
73 ASN1_CONSTRUCTED_END(seq_len, pos, end);
74 break;
75 case 2: /* numericString */
76 ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
77 msg_centre_id->u.str, sizeof(msg_centre_id->u.str) - 1));
78 break;
79 default:
80 ASN1_ENC_ERROR(ctrl, "Unknown MsgCentreId type");
81 return NULL;
82 }
83
84 return pos;
85 }
86
87 /*!
88 * \brief Encode the MWIActivate invoke facility ie arguments.
89 *
90 * \param ctrl D channel controller for diagnostic messages or global options.
91 * \param pos Starting position to encode ASN.1 component.
92 * \param end End of ASN.1 encoding data buffer.
93 * \param args Arguments to encode in the buffer.
94 *
95 * \retval Start of the next ASN.1 component to encode on success.
96 * \retval NULL on error.
97 */
rose_enc_qsig_MWIActivate_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)98 unsigned char *rose_enc_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned char *pos,
99 unsigned char *end, const union rose_msg_invoke_args *args)
100 {
101 const struct roseQsigMWIActivateArg *mwi_activate;
102 unsigned char *seq_len;
103 unsigned char *explicit_len;
104
105 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
106
107 mwi_activate = &args->qsig.MWIActivate;
108 ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
109 &mwi_activate->served_user_number));
110 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
111 mwi_activate->basic_service));
112 if (mwi_activate->msg_centre_id_present) {
113 ASN1_CALL(pos, rose_enc_qsig_MsgCentreId(ctrl, pos, end,
114 &mwi_activate->msg_centre_id));
115 }
116 if (mwi_activate->number_of_messages_present) {
117 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
118 mwi_activate->number_of_messages));
119 }
120 if (mwi_activate->originating_number.length) {
121 /* EXPLICIT tag */
122 ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4);
123 ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
124 &mwi_activate->originating_number));
125 ASN1_CONSTRUCTED_END(explicit_len, pos, end);
126 }
127 if (mwi_activate->timestamp_present) {
128 ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_GENERALIZED_TIME,
129 mwi_activate->timestamp.str, sizeof(mwi_activate->timestamp.str) - 1));
130 }
131 if (mwi_activate->priority_present) {
132 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5,
133 mwi_activate->priority));
134 }
135
136 /* No extension to encode */
137
138 ASN1_CONSTRUCTED_END(seq_len, pos, end);
139
140 return pos;
141 }
142
143 /*!
144 * \brief Encode the MWIDeactivate invoke facility ie arguments.
145 *
146 * \param ctrl D channel controller for diagnostic messages or global options.
147 * \param pos Starting position to encode ASN.1 component.
148 * \param end End of ASN.1 encoding data buffer.
149 * \param args Arguments to encode in the buffer.
150 *
151 * \retval Start of the next ASN.1 component to encode on success.
152 * \retval NULL on error.
153 */
rose_enc_qsig_MWIDeactivate_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)154 unsigned char *rose_enc_qsig_MWIDeactivate_ARG(struct pri *ctrl, unsigned char *pos,
155 unsigned char *end, const union rose_msg_invoke_args *args)
156 {
157 const struct roseQsigMWIDeactivateArg *mwi_deactivate;
158 unsigned char *seq_len;
159
160 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
161
162 mwi_deactivate = &args->qsig.MWIDeactivate;
163 ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
164 &mwi_deactivate->served_user_number));
165 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
166 mwi_deactivate->basic_service));
167 if (mwi_deactivate->msg_centre_id_present) {
168 ASN1_CALL(pos, rose_enc_qsig_MsgCentreId(ctrl, pos, end,
169 &mwi_deactivate->msg_centre_id));
170 }
171
172 /* No extension to encode */
173
174 ASN1_CONSTRUCTED_END(seq_len, pos, end);
175
176 return pos;
177 }
178
179 /*!
180 * \brief Encode the MWIInterrogate invoke facility ie arguments.
181 *
182 * \param ctrl D channel controller for diagnostic messages or global options.
183 * \param pos Starting position to encode ASN.1 component.
184 * \param end End of ASN.1 encoding data buffer.
185 * \param args Arguments to encode in the buffer.
186 *
187 * \retval Start of the next ASN.1 component to encode on success.
188 * \retval NULL on error.
189 */
rose_enc_qsig_MWIInterrogate_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)190 unsigned char *rose_enc_qsig_MWIInterrogate_ARG(struct pri *ctrl, unsigned char *pos,
191 unsigned char *end, const union rose_msg_invoke_args *args)
192 {
193 const struct roseQsigMWIInterrogateArg *mwi_interrogate;
194 unsigned char *seq_len;
195
196 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
197
198 mwi_interrogate = &args->qsig.MWIInterrogate;
199 ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
200 &mwi_interrogate->served_user_number));
201 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
202 mwi_interrogate->basic_service));
203 if (mwi_interrogate->msg_centre_id_present) {
204 ASN1_CALL(pos, rose_enc_qsig_MsgCentreId(ctrl, pos, end,
205 &mwi_interrogate->msg_centre_id));
206 }
207
208 /* No extension to encode */
209
210 ASN1_CONSTRUCTED_END(seq_len, pos, end);
211
212 return pos;
213 }
214
215 /*!
216 * \internal
217 * \brief Encode the MWIInterrogateResElt type.
218 *
219 * \param ctrl D channel controller for diagnostic messages or global options.
220 * \param pos Starting position to encode ASN.1 component.
221 * \param end End of ASN.1 encoding data buffer.
222 * \param tag Component tag to identify the encoded component.
223 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
224 * tags it otherwise.
225 * \param record
226 *
227 * \retval Start of the next ASN.1 component to encode on success.
228 * \retval NULL on error.
229 */
rose_enc_qsig_MWIInterrogateResElt(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseQsigMWIInterrogateResElt * record)230 static unsigned char *rose_enc_qsig_MWIInterrogateResElt(struct pri *ctrl,
231 unsigned char *pos, unsigned char *end, unsigned tag,
232 const struct roseQsigMWIInterrogateResElt *record)
233 {
234 unsigned char *seq_len;
235 unsigned char *explicit_len;
236
237 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
238
239 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED, record->basic_service));
240 if (record->msg_centre_id_present) {
241 ASN1_CALL(pos, rose_enc_qsig_MsgCentreId(ctrl, pos, end,
242 &record->msg_centre_id));
243 }
244 if (record->number_of_messages_present) {
245 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
246 record->number_of_messages));
247 }
248 if (record->originating_number.length) {
249 /* EXPLICIT tag */
250 ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4);
251 ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
252 &record->originating_number));
253 ASN1_CONSTRUCTED_END(explicit_len, pos, end);
254 }
255 if (record->timestamp_present) {
256 ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_GENERALIZED_TIME,
257 record->timestamp.str, sizeof(record->timestamp.str) - 1));
258 }
259 if (record->priority_present) {
260 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5,
261 record->priority));
262 }
263
264 /* No extension to encode */
265
266 ASN1_CONSTRUCTED_END(seq_len, pos, end);
267
268 return pos;
269 }
270
271 /*!
272 * \brief Encode the MWIInterrogate result facility ie arguments.
273 *
274 * \param ctrl D channel controller for diagnostic messages or global options.
275 * \param pos Starting position to encode ASN.1 component.
276 * \param end End of ASN.1 encoding data buffer.
277 * \param args Arguments to encode in the buffer.
278 *
279 * \retval Start of the next ASN.1 component to encode on success.
280 * \retval NULL on error.
281 */
rose_enc_qsig_MWIInterrogate_RES(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_result_args * args)282 unsigned char *rose_enc_qsig_MWIInterrogate_RES(struct pri *ctrl, unsigned char *pos,
283 unsigned char *end, const union rose_msg_result_args *args)
284 {
285 unsigned index;
286 unsigned char *seq_len;
287 const struct roseQsigMWIInterrogateRes *mwi_interrogate;
288
289 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
290
291 mwi_interrogate = &args->qsig.MWIInterrogate;
292 for (index = 0; index < mwi_interrogate->num_records; ++index) {
293 ASN1_CALL(pos, rose_enc_qsig_MWIInterrogateResElt(ctrl, pos, end,
294 ASN1_TAG_SEQUENCE, &mwi_interrogate->list[index]));
295 }
296
297 ASN1_CONSTRUCTED_END(seq_len, pos, end);
298
299 return pos;
300 }
301
302 /*!
303 * \internal
304 * \brief Decode the MsgCentreId argument parameters.
305 *
306 * \param ctrl D channel controller for any diagnostic messages.
307 * \param name Field name
308 * \param tag Component tag that identified this production.
309 * \param pos Starting position of the ASN.1 component length.
310 * \param end End of ASN.1 decoding data buffer.
311 * \param msg_centre_id Parameter storage to fill.
312 *
313 * \retval Start of the next ASN.1 component on success.
314 * \retval NULL on error.
315 */
rose_dec_qsig_MsgCentreId(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseQsigMsgCentreId * msg_centre_id)316 static const unsigned char *rose_dec_qsig_MsgCentreId(struct pri *ctrl, const char *name,
317 unsigned tag, const unsigned char *pos, const unsigned char *end,
318 struct roseQsigMsgCentreId *msg_centre_id)
319 {
320 int32_t value;
321 size_t str_len;
322 int length;
323 int explicit_offset;
324 const unsigned char *explicit_end;
325
326 if (ctrl->debug & PRI_DEBUG_APDU) {
327 pri_message(ctrl, " %s MsgCentreId\n", name);
328 }
329 switch (tag) {
330 case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
331 msg_centre_id->type = 0; /* integer */
332 ASN1_CALL(pos, asn1_dec_int(ctrl, "integer", tag, pos, end, &value));
333 msg_centre_id->u.integer = value;
334 break;
335 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
336 msg_centre_id->type = 1; /* partyNumber */
337
338 /* Remove EXPLICIT tag */
339 if (ctrl->debug & PRI_DEBUG_APDU) {
340 pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
341 }
342 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
343 ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, end);
344
345 ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
346 ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "partyNumber", tag, pos, explicit_end,
347 &msg_centre_id->u.number));
348
349 ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, end);
350 break;
351 case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
352 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
353 msg_centre_id->type = 2; /* numericString */
354 ASN1_CALL(pos, asn1_dec_string_max(ctrl, "numericString", tag, pos, end,
355 sizeof(msg_centre_id->u.str), msg_centre_id->u.str, &str_len));
356 break;
357 default:
358 ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
359 return NULL;
360 }
361
362 return pos;
363 }
364
365 /*!
366 * \brief Decode the Q.SIG MWIActivate invoke argument parameters.
367 *
368 * \param ctrl D channel controller for diagnostic messages or global options.
369 * \param tag Component tag that identified this structure.
370 * \param pos Starting position of the ASN.1 component length.
371 * \param end End of ASN.1 decoding data buffer.
372 * \param args Arguments to fill in from the decoded buffer.
373 *
374 * \retval Start of the next ASN.1 component on success.
375 * \retval NULL on error.
376 */
rose_dec_qsig_MWIActivate_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)377 const unsigned char *rose_dec_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned tag,
378 const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
379 {
380 int32_t value;
381 size_t str_len;
382 int length;
383 int seq_offset;
384 int explicit_offset;
385 const unsigned char *explicit_end;
386 const unsigned char *seq_end;
387 const unsigned char *save_pos;
388 struct roseQsigMWIActivateArg *mwi_activate;
389
390 mwi_activate = &args->qsig.MWIActivate;
391
392 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
393 if (ctrl->debug & PRI_DEBUG_APDU) {
394 pri_message(ctrl, " MWIActivateArg %s\n", asn1_tag2str(tag));
395 }
396 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
397 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
398
399 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
400 ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
401 &mwi_activate->served_user_number));
402
403 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
404 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
405 ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
406 mwi_activate->basic_service = value;
407
408 /*
409 * A sequence specifies an ordered list of component types.
410 * However, for simplicity we are not checking the order of
411 * the remaining optional components.
412 */
413 mwi_activate->msg_centre_id_present = 0;
414 mwi_activate->number_of_messages_present = 0;
415 mwi_activate->originating_number.length = 0;
416 mwi_activate->timestamp_present = 0;
417 mwi_activate->priority_present = 0;
418 while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
419 save_pos = pos;
420 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
421 switch (tag & ~ASN1_PC_MASK) {
422 case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
423 case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
424 case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
425 ASN1_CALL(pos, rose_dec_qsig_MsgCentreId(ctrl, "msgCentreId", tag, pos,
426 seq_end, &mwi_activate->msg_centre_id));
427 mwi_activate->msg_centre_id_present = 1;
428 break;
429 case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
430 /* Must not be constructed but we will not check for it for simplicity. */
431 ASN1_CALL(pos, asn1_dec_int(ctrl, "nbOfMessages", tag, pos, seq_end,
432 &value));
433 mwi_activate->number_of_messages = value;
434 mwi_activate->number_of_messages_present = 1;
435 break;
436 case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
437 /* Must be constructed but we will not check for it for simplicity. */
438 /* Remove EXPLICIT tag */
439 if (ctrl->debug & PRI_DEBUG_APDU) {
440 pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
441 }
442 ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
443 ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
444
445 ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
446 ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "originatingNr", tag, pos,
447 explicit_end, &mwi_activate->originating_number));
448
449 ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
450 break;
451 case ASN1_TYPE_GENERALIZED_TIME:
452 ASN1_CALL(pos, asn1_dec_string_max(ctrl, "timestamp", tag, pos, end,
453 sizeof(mwi_activate->timestamp.str), mwi_activate->timestamp.str,
454 &str_len));
455 mwi_activate->timestamp_present = 1;
456 break;
457 case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
458 /* Must not be constructed but we will not check for it for simplicity. */
459 ASN1_CALL(pos, asn1_dec_int(ctrl, "priority", tag, pos, seq_end, &value));
460 mwi_activate->priority = value;
461 mwi_activate->priority_present = 1;
462 break;
463 case ASN1_CLASS_CONTEXT_SPECIFIC | 6:
464 case ASN1_CLASS_CONTEXT_SPECIFIC | 7:
465 if (ctrl->debug & PRI_DEBUG_APDU) {
466 pri_message(ctrl, " argumentExt %s\n", asn1_tag2str(tag));
467 }
468 /* Fixup will skip over the manufacturer extension information */
469 default:
470 pos = save_pos;
471 goto cancel_options;
472 }
473 }
474 cancel_options:;
475
476 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
477
478 return pos;
479 }
480
481 /*!
482 * \brief Decode the Q.SIG MWIDeactivate invoke argument parameters.
483 *
484 * \param ctrl D channel controller for diagnostic messages or global options.
485 * \param tag Component tag that identified this structure.
486 * \param pos Starting position of the ASN.1 component length.
487 * \param end End of ASN.1 decoding data buffer.
488 * \param args Arguments to fill in from the decoded buffer.
489 *
490 * \retval Start of the next ASN.1 component on success.
491 * \retval NULL on error.
492 */
rose_dec_qsig_MWIDeactivate_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)493 const unsigned char *rose_dec_qsig_MWIDeactivate_ARG(struct pri *ctrl, unsigned tag,
494 const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
495 {
496 int32_t value;
497 int length;
498 int seq_offset;
499 const unsigned char *seq_end;
500 const unsigned char *save_pos;
501 struct roseQsigMWIDeactivateArg *mwi_deactivate;
502
503 mwi_deactivate = &args->qsig.MWIDeactivate;
504
505 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
506 if (ctrl->debug & PRI_DEBUG_APDU) {
507 pri_message(ctrl, " MWIDeactivateArg %s\n", asn1_tag2str(tag));
508 }
509 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
510 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
511
512 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
513 ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
514 &mwi_deactivate->served_user_number));
515
516 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
517 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
518 ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
519 mwi_deactivate->basic_service = value;
520
521 /*
522 * A sequence specifies an ordered list of component types.
523 * However, for simplicity we are not checking the order of
524 * the remaining optional components.
525 */
526 mwi_deactivate->msg_centre_id_present = 0;
527 while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
528 save_pos = pos;
529 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
530 switch (tag & ~ASN1_PC_MASK) {
531 case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
532 case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
533 case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
534 ASN1_CALL(pos, rose_dec_qsig_MsgCentreId(ctrl, "msgCentreId", tag, pos,
535 seq_end, &mwi_deactivate->msg_centre_id));
536 mwi_deactivate->msg_centre_id_present = 1;
537 break;
538 case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
539 case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
540 if (ctrl->debug & PRI_DEBUG_APDU) {
541 pri_message(ctrl, " argumentExt %s\n", asn1_tag2str(tag));
542 }
543 /* Fixup will skip over the manufacturer extension information */
544 default:
545 pos = save_pos;
546 goto cancel_options;
547 }
548 }
549 cancel_options:;
550
551 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
552
553 return pos;
554 }
555
556 /*!
557 * \brief Decode the Q.SIG MWIInterrogate invoke argument parameters.
558 *
559 * \param ctrl D channel controller for diagnostic messages or global options.
560 * \param tag Component tag that identified this structure.
561 * \param pos Starting position of the ASN.1 component length.
562 * \param end End of ASN.1 decoding data buffer.
563 * \param args Arguments to fill in from the decoded buffer.
564 *
565 * \retval Start of the next ASN.1 component on success.
566 * \retval NULL on error.
567 */
rose_dec_qsig_MWIInterrogate_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)568 const unsigned char *rose_dec_qsig_MWIInterrogate_ARG(struct pri *ctrl, unsigned tag,
569 const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
570 {
571 int32_t value;
572 int length;
573 int seq_offset;
574 const unsigned char *seq_end;
575 const unsigned char *save_pos;
576 struct roseQsigMWIInterrogateArg *mwi_interrogate;
577
578 mwi_interrogate = &args->qsig.MWIInterrogate;
579
580 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
581 if (ctrl->debug & PRI_DEBUG_APDU) {
582 pri_message(ctrl, " MWIInterrogateArg %s\n", asn1_tag2str(tag));
583 }
584 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
585 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
586
587 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
588 ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
589 &mwi_interrogate->served_user_number));
590
591 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
592 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
593 ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
594 mwi_interrogate->basic_service = value;
595
596 /*
597 * A sequence specifies an ordered list of component types.
598 * However, for simplicity we are not checking the order of
599 * the remaining optional components.
600 */
601 mwi_interrogate->msg_centre_id_present = 0;
602 while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
603 save_pos = pos;
604 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
605 switch (tag & ~ASN1_PC_MASK) {
606 case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
607 case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
608 case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
609 ASN1_CALL(pos, rose_dec_qsig_MsgCentreId(ctrl, "msgCentreId", tag, pos,
610 seq_end, &mwi_interrogate->msg_centre_id));
611 mwi_interrogate->msg_centre_id_present = 1;
612 break;
613 case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
614 case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
615 if (ctrl->debug & PRI_DEBUG_APDU) {
616 pri_message(ctrl, " argumentExt %s\n", asn1_tag2str(tag));
617 }
618 /* Fixup will skip over the manufacturer extension information */
619 default:
620 pos = save_pos;
621 goto cancel_options;
622 }
623 }
624 cancel_options:;
625
626 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
627
628 return pos;
629 }
630
631 /*!
632 * \internal
633 * \brief Decode the MWIInterrogateResElt argument parameters.
634 *
635 * \param ctrl D channel controller for any diagnostic messages.
636 * \param name Field name
637 * \param tag Component tag that identified this production.
638 * \param pos Starting position of the ASN.1 component length.
639 * \param end End of ASN.1 decoding data buffer.
640 * \param record Parameter storage to fill.
641 *
642 * \retval Start of the next ASN.1 component on success.
643 * \retval NULL on error.
644 */
rose_dec_qsig_MWIInterrogateResElt(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseQsigMWIInterrogateResElt * record)645 static const unsigned char *rose_dec_qsig_MWIInterrogateResElt(struct pri *ctrl,
646 const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
647 struct roseQsigMWIInterrogateResElt *record)
648 {
649 int32_t value;
650 size_t str_len;
651 int length;
652 int seq_offset;
653 int explicit_offset;
654 const unsigned char *explicit_end;
655 const unsigned char *seq_end;
656 const unsigned char *save_pos;
657
658 if (ctrl->debug & PRI_DEBUG_APDU) {
659 pri_message(ctrl, " MWIInterrogateResElt %s\n", asn1_tag2str(tag));
660 }
661 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
662 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
663
664 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
665 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
666 ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
667 record->basic_service = value;
668
669 /*
670 * A sequence specifies an ordered list of component types.
671 * However, for simplicity we are not checking the order of
672 * the remaining optional components.
673 */
674 record->msg_centre_id_present = 0;
675 record->number_of_messages_present = 0;
676 record->originating_number.length = 0;
677 record->timestamp_present = 0;
678 record->priority_present = 0;
679 while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
680 save_pos = pos;
681 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
682 switch (tag & ~ASN1_PC_MASK) {
683 case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
684 case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
685 case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
686 ASN1_CALL(pos, rose_dec_qsig_MsgCentreId(ctrl, "msgCentreId", tag, pos,
687 seq_end, &record->msg_centre_id));
688 record->msg_centre_id_present = 1;
689 break;
690 case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
691 /* Must not be constructed but we will not check for it for simplicity. */
692 ASN1_CALL(pos, asn1_dec_int(ctrl, "nbOfMessages", tag, pos, seq_end,
693 &value));
694 record->number_of_messages = value;
695 record->number_of_messages_present = 1;
696 break;
697 case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
698 /* Must be constructed but we will not check for it for simplicity. */
699 /* Remove EXPLICIT tag */
700 if (ctrl->debug & PRI_DEBUG_APDU) {
701 pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
702 }
703 ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
704 ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
705
706 ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
707 ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "originatingNr", tag, pos,
708 explicit_end, &record->originating_number));
709
710 ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
711 break;
712 case ASN1_TYPE_GENERALIZED_TIME:
713 ASN1_CALL(pos, asn1_dec_string_max(ctrl, "timestamp", tag, pos, end,
714 sizeof(record->timestamp.str), record->timestamp.str, &str_len));
715 record->timestamp_present = 1;
716 break;
717 case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
718 /* Must not be constructed but we will not check for it for simplicity. */
719 ASN1_CALL(pos, asn1_dec_int(ctrl, "priority", tag, pos, seq_end, &value));
720 record->priority = value;
721 record->priority_present = 1;
722 break;
723 case ASN1_CLASS_CONTEXT_SPECIFIC | 6:
724 case ASN1_CLASS_CONTEXT_SPECIFIC | 7:
725 if (ctrl->debug & PRI_DEBUG_APDU) {
726 pri_message(ctrl, " argumentExt %s\n", asn1_tag2str(tag));
727 }
728 /* Fixup will skip over the manufacturer extension information */
729 default:
730 pos = save_pos;
731 goto cancel_options;
732 }
733 }
734 cancel_options:;
735
736 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
737
738 return pos;
739 }
740
741 /*!
742 * \brief Decode the Q.SIG MWIInterrogate result argument parameters.
743 *
744 * \param ctrl D channel controller for diagnostic messages or global options.
745 * \param tag Component tag that identified this structure.
746 * \param pos Starting position of the ASN.1 component length.
747 * \param end End of ASN.1 decoding data buffer.
748 * \param args Arguments to fill in from the decoded buffer.
749 *
750 * \retval Start of the next ASN.1 component on success.
751 * \retval NULL on error.
752 */
rose_dec_qsig_MWIInterrogate_RES(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_result_args * args)753 const unsigned char *rose_dec_qsig_MWIInterrogate_RES(struct pri *ctrl, unsigned tag,
754 const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
755 {
756 int length;
757 int seq_offset;
758 const unsigned char *seq_end;
759 struct roseQsigMWIInterrogateRes *mwi_interrogate;
760
761 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
762 if (ctrl->debug & PRI_DEBUG_APDU) {
763 pri_message(ctrl, " MWIInterrogateRes %s\n", asn1_tag2str(tag));
764 }
765 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
766 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
767
768 mwi_interrogate = &args->qsig.MWIInterrogate;
769
770 mwi_interrogate->num_records = 0;
771 while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
772 if (mwi_interrogate->num_records < ARRAY_LEN(mwi_interrogate->list)) {
773 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
774 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
775 ASN1_CALL(pos, rose_dec_qsig_MWIInterrogateResElt(ctrl, "listEntry", tag,
776 pos, seq_end, &mwi_interrogate->list[mwi_interrogate->num_records]));
777 ++mwi_interrogate->num_records;
778 } else {
779 /* Too many records */
780 return NULL;
781 }
782 }
783
784 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
785
786 return pos;
787 }
788
789
790 /* ------------------------------------------------------------------- */
791 /* end rose_qsig_mwi.c */
792