1 /*
2 * libpri: An implementation of Primary Rate ISDN
3 *
4 * Copyright (C) 2010 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 ROSE Message Waiting Indication (MWI) operations
30 *
31 * Message Waiting Indication (MWI) supplementary service EN 300 745-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 MessageID 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_id
55 *
56 * \retval Start of the next ASN.1 component to encode on success.
57 * \retval NULL on error.
58 */
rose_enc_etsi_message_id(struct pri * ctrl,unsigned char * pos,unsigned char * end,const struct roseEtsiMessageID * msg_id)59 static unsigned char *rose_enc_etsi_message_id(struct pri *ctrl, unsigned char *pos,
60 unsigned char *end, const struct roseEtsiMessageID *msg_id)
61 {
62 unsigned char *seq_len;
63
64 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
65
66 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, msg_id->reference_number));
67 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED, msg_id->status));
68
69 ASN1_CONSTRUCTED_END(seq_len, pos, end);
70
71 return pos;
72 }
73
74 /*!
75 * \brief Encode the MWIActivate invoke facility ie arguments.
76 *
77 * \param ctrl D channel controller for diagnostic messages or global options.
78 * \param pos Starting position to encode ASN.1 component.
79 * \param end End of ASN.1 encoding data buffer.
80 * \param args Arguments to encode in the buffer.
81 *
82 * \retval Start of the next ASN.1 component to encode on success.
83 * \retval NULL on error.
84 */
rose_enc_etsi_MWIActivate_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)85 unsigned char *rose_enc_etsi_MWIActivate_ARG(struct pri *ctrl, unsigned char *pos,
86 unsigned char *end, const union rose_msg_invoke_args *args)
87 {
88 const struct roseEtsiMWIActivate_ARG *mwi_activate;
89 unsigned char *seq_len;
90 unsigned char *explicit_len;
91
92 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
93
94 mwi_activate = &args->etsi.MWIActivate;
95 ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
96 &mwi_activate->receiving_user_number));
97 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
98 mwi_activate->basic_service));
99 if (mwi_activate->controlling_user_number.length) {
100 /* EXPLICIT tag */
101 ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
102 ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
103 &mwi_activate->controlling_user_number));
104 ASN1_CONSTRUCTED_END(explicit_len, pos, end);
105 }
106 if (mwi_activate->number_of_messages_present) {
107 /* EXPLICIT tag */
108 ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
109 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
110 mwi_activate->number_of_messages));
111 ASN1_CONSTRUCTED_END(explicit_len, pos, end);
112 }
113 if (mwi_activate->controlling_user_provided_number.length) {
114 /* EXPLICIT tag */
115 ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
116 ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
117 &mwi_activate->controlling_user_provided_number));
118 ASN1_CONSTRUCTED_END(explicit_len, pos, end);
119 }
120 if (mwi_activate->time_present) {
121 /* EXPLICIT tag */
122 ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4);
123 ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_GENERALIZED_TIME,
124 mwi_activate->time.str, sizeof(mwi_activate->time.str) - 1));
125 ASN1_CONSTRUCTED_END(explicit_len, pos, end);
126 }
127 if (mwi_activate->message_id_present) {
128 /* EXPLICIT tag */
129 ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5);
130 ASN1_CALL(pos, rose_enc_etsi_message_id(ctrl, pos, end,
131 &mwi_activate->message_id));
132 ASN1_CONSTRUCTED_END(explicit_len, pos, end);
133 }
134 if (mwi_activate->mode_present) {
135 /* EXPLICIT tag */
136 ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 6);
137 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
138 mwi_activate->mode));
139 ASN1_CONSTRUCTED_END(explicit_len, pos, end);
140 }
141
142 ASN1_CONSTRUCTED_END(seq_len, pos, end);
143
144 return pos;
145 }
146
147 /*!
148 * \brief Encode the MWIDeactivate invoke facility ie arguments.
149 *
150 * \param ctrl D channel controller for diagnostic messages or global options.
151 * \param pos Starting position to encode ASN.1 component.
152 * \param end End of ASN.1 encoding data buffer.
153 * \param args Arguments to encode in the buffer.
154 *
155 * \retval Start of the next ASN.1 component to encode on success.
156 * \retval NULL on error.
157 */
rose_enc_etsi_MWIDeactivate_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)158 unsigned char *rose_enc_etsi_MWIDeactivate_ARG(struct pri *ctrl, unsigned char *pos,
159 unsigned char *end, const union rose_msg_invoke_args *args)
160 {
161 const struct roseEtsiMWIDeactivate_ARG *mwi_deactivate;
162 unsigned char *seq_len;
163
164 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
165
166 mwi_deactivate = &args->etsi.MWIDeactivate;
167 ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
168 &mwi_deactivate->receiving_user_number));
169 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
170 mwi_deactivate->basic_service));
171 if (mwi_deactivate->controlling_user_number.length) {
172 ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
173 &mwi_deactivate->controlling_user_number));
174 }
175 if (mwi_deactivate->mode_present) {
176 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
177 mwi_deactivate->mode));
178 }
179
180 ASN1_CONSTRUCTED_END(seq_len, pos, end);
181
182 return pos;
183 }
184
185 /*!
186 * \brief Encode the MWIIndicate invoke facility ie arguments.
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 args Arguments to encode in the buffer.
192 *
193 * \retval Start of the next ASN.1 component to encode on success.
194 * \retval NULL on error.
195 */
rose_enc_etsi_MWIIndicate_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)196 unsigned char *rose_enc_etsi_MWIIndicate_ARG(struct pri *ctrl, unsigned char *pos,
197 unsigned char *end, const union rose_msg_invoke_args *args)
198 {
199 const struct roseEtsiMWIIndicate_ARG *mwi_indicate;
200 unsigned char *seq_len;
201 unsigned char *explicit_len;
202
203 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
204
205 mwi_indicate = &args->etsi.MWIIndicate;
206 if (mwi_indicate->controlling_user_number.length) {
207 /* EXPLICIT tag */
208 ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
209 ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
210 &mwi_indicate->controlling_user_number));
211 ASN1_CONSTRUCTED_END(explicit_len, pos, end);
212 }
213 if (mwi_indicate->basic_service_present) {
214 /* EXPLICIT tag */
215 ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
216 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
217 mwi_indicate->basic_service));
218 ASN1_CONSTRUCTED_END(explicit_len, pos, end);
219 }
220 if (mwi_indicate->number_of_messages_present) {
221 /* EXPLICIT tag */
222 ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
223 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
224 mwi_indicate->number_of_messages));
225 ASN1_CONSTRUCTED_END(explicit_len, pos, end);
226 }
227 if (mwi_indicate->controlling_user_provided_number.length) {
228 /* EXPLICIT tag */
229 ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4);
230 ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
231 &mwi_indicate->controlling_user_provided_number));
232 ASN1_CONSTRUCTED_END(explicit_len, pos, end);
233 }
234 if (mwi_indicate->time_present) {
235 /* EXPLICIT tag */
236 ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5);
237 ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_GENERALIZED_TIME,
238 mwi_indicate->time.str, sizeof(mwi_indicate->time.str) - 1));
239 ASN1_CONSTRUCTED_END(explicit_len, pos, end);
240 }
241 if (mwi_indicate->message_id_present) {
242 /* EXPLICIT tag */
243 ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 6);
244 ASN1_CALL(pos, rose_enc_etsi_message_id(ctrl, pos, end,
245 &mwi_indicate->message_id));
246 ASN1_CONSTRUCTED_END(explicit_len, pos, end);
247 }
248
249 ASN1_CONSTRUCTED_END(seq_len, pos, end);
250
251 return pos;
252 }
253
254 /*!
255 * \internal
256 * \brief Decode the MessageID argument parameters.
257 *
258 * \param ctrl D channel controller for any diagnostic messages.
259 * \param name Field name
260 * \param tag Component tag that identified this production.
261 * \param pos Starting position of the ASN.1 component length.
262 * \param end End of ASN.1 decoding data buffer.
263 * \param msg_id Parameter storage to fill.
264 *
265 * \retval Start of the next ASN.1 component on success.
266 * \retval NULL on error.
267 */
rose_dec_etsi_message_id(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseEtsiMessageID * msg_id)268 static const unsigned char *rose_dec_etsi_message_id(struct pri *ctrl, const char *name,
269 unsigned tag, const unsigned char *pos, const unsigned char *end,
270 struct roseEtsiMessageID *msg_id)
271 {
272 int32_t value;
273 int length;
274 int seq_offset;
275 const unsigned char *seq_end;
276
277 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
278 if (ctrl->debug & PRI_DEBUG_APDU) {
279 pri_message(ctrl, " %s MessageID %s\n", name, asn1_tag2str(tag));
280 }
281 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
282 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
283
284 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
285 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
286 ASN1_CALL(pos, asn1_dec_int(ctrl, "messageRef", tag, pos, seq_end, &value));
287 msg_id->reference_number = value;
288
289 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
290 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
291 ASN1_CALL(pos, asn1_dec_int(ctrl, "status", tag, pos, seq_end, &value));
292 msg_id->status = value;
293
294 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
295
296 return pos;
297 }
298
299 /*!
300 * \brief Decode the MWIActivate invoke argument parameters.
301 *
302 * \param ctrl D channel controller for diagnostic messages or global options.
303 * \param tag Component tag that identified this structure.
304 * \param pos Starting position of the ASN.1 component length.
305 * \param end End of ASN.1 decoding data buffer.
306 * \param args Arguments to fill in from the decoded buffer.
307 *
308 * \retval Start of the next ASN.1 component on success.
309 * \retval NULL on error.
310 */
rose_dec_etsi_MWIActivate_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)311 const unsigned char *rose_dec_etsi_MWIActivate_ARG(struct pri *ctrl, unsigned tag,
312 const unsigned char *pos, const unsigned char *end,
313 union rose_msg_invoke_args *args)
314 {
315 int32_t value;
316 size_t str_len;
317 int length;
318 int seq_offset;
319 int explicit_offset;
320 const unsigned char *explicit_end;
321 const unsigned char *seq_end;
322 const unsigned char *save_pos;
323 struct roseEtsiMWIActivate_ARG *mwi_activate;
324
325 mwi_activate = &args->etsi.MWIActivate;
326
327 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
328 if (ctrl->debug & PRI_DEBUG_APDU) {
329 pri_message(ctrl, " MWIActivate %s\n", asn1_tag2str(tag));
330 }
331 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
332 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
333
334 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
335 ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "receivingUserNr", tag, pos, seq_end,
336 &mwi_activate->receiving_user_number));
337
338 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
339 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
340 ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
341 mwi_activate->basic_service = value;
342
343 /*
344 * A sequence specifies an ordered list of component types.
345 * However, for simplicity we are not checking the order of
346 * the remaining optional components.
347 */
348 mwi_activate->controlling_user_number.length = 0;
349 mwi_activate->number_of_messages_present = 0;
350 mwi_activate->controlling_user_provided_number.length = 0;
351 mwi_activate->time_present = 0;
352 mwi_activate->message_id_present = 0;
353 mwi_activate->mode_present = 0;
354 while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
355 save_pos = pos;
356 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
357 switch (tag) {
358 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
359 /* Remove EXPLICIT tag */
360 if (ctrl->debug & PRI_DEBUG_APDU) {
361 pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
362 }
363 ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
364 ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
365
366 ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
367 ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "controllingUserNr", tag, pos,
368 explicit_end, &mwi_activate->controlling_user_number));
369
370 ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
371 break;
372 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
373 /* Remove EXPLICIT tag */
374 if (ctrl->debug & PRI_DEBUG_APDU) {
375 pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
376 }
377 ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
378 ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
379
380 ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
381 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
382 ASN1_CALL(pos, asn1_dec_int(ctrl, "numberOfMessages", tag, pos, explicit_end,
383 &value));
384 mwi_activate->number_of_messages = value;
385 mwi_activate->number_of_messages_present = 1;
386
387 ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
388 break;
389 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
390 /* Remove EXPLICIT tag */
391 if (ctrl->debug & PRI_DEBUG_APDU) {
392 pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
393 }
394 ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
395 ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
396
397 ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
398 ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "controllingUserProvidedNr", tag,
399 pos, explicit_end, &mwi_activate->controlling_user_provided_number));
400
401 ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
402 break;
403 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 4:
404 /* Remove EXPLICIT tag */
405 if (ctrl->debug & PRI_DEBUG_APDU) {
406 pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
407 }
408 ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
409 ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
410
411 ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
412 ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_TYPE_GENERALIZED_TIME);
413 ASN1_CALL(pos, asn1_dec_string_max(ctrl, "time", tag, pos, explicit_end,
414 sizeof(mwi_activate->time.str), mwi_activate->time.str, &str_len));
415 mwi_activate->time_present = 1;
416
417 ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
418 break;
419 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 5:
420 /* Remove EXPLICIT tag */
421 if (ctrl->debug & PRI_DEBUG_APDU) {
422 pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
423 }
424 ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
425 ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
426
427 ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
428 ASN1_CALL(pos, rose_dec_etsi_message_id(ctrl, "messageId", tag, pos,
429 explicit_end, &mwi_activate->message_id));
430 mwi_activate->message_id_present = 1;
431
432 ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
433 break;
434 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 6:
435 /* Remove EXPLICIT tag */
436 if (ctrl->debug & PRI_DEBUG_APDU) {
437 pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
438 }
439 ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
440 ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
441
442 ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
443 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
444 ASN1_CALL(pos, asn1_dec_int(ctrl, "mode", tag, pos, explicit_end, &value));
445 mwi_activate->mode = value;
446 mwi_activate->mode_present = 1;
447
448 ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
449 break;
450 default:
451 pos = save_pos;
452 goto cancel_options;
453 }
454 }
455 cancel_options:;
456
457 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
458
459 return pos;
460 }
461
462 /*!
463 * \brief Decode the MWIDeactivate invoke argument parameters.
464 *
465 * \param ctrl D channel controller for diagnostic messages or global options.
466 * \param tag Component tag that identified this structure.
467 * \param pos Starting position of the ASN.1 component length.
468 * \param end End of ASN.1 decoding data buffer.
469 * \param args Arguments to fill in from the decoded buffer.
470 *
471 * \retval Start of the next ASN.1 component on success.
472 * \retval NULL on error.
473 */
rose_dec_etsi_MWIDeactivate_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)474 const unsigned char *rose_dec_etsi_MWIDeactivate_ARG(struct pri *ctrl, unsigned tag,
475 const unsigned char *pos, const unsigned char *end,
476 union rose_msg_invoke_args *args)
477 {
478 int32_t value;
479 int length;
480 int seq_offset;
481 const unsigned char *seq_end;
482 struct roseEtsiMWIDeactivate_ARG *mwi_deactivate;
483
484 mwi_deactivate = &args->etsi.MWIDeactivate;
485
486 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
487 if (ctrl->debug & PRI_DEBUG_APDU) {
488 pri_message(ctrl, " MWIDeactivate %s\n", asn1_tag2str(tag));
489 }
490 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
491 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
492
493 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
494 ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "receivingUserNr", tag, pos, seq_end,
495 &mwi_deactivate->receiving_user_number));
496
497 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
498 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
499 ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
500 mwi_deactivate->basic_service = value;
501
502 /*
503 * A sequence specifies an ordered list of component types.
504 * However, for simplicity we are not checking the order of
505 * the remaining optional components.
506 */
507 mwi_deactivate->controlling_user_number.length = 0;
508 mwi_deactivate->mode_present = 0;
509 while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
510 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
511 switch (tag) {
512 default:
513 ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "controllingUserNr", tag, pos,
514 seq_end, &mwi_deactivate->controlling_user_number));
515 break;
516 case ASN1_TYPE_ENUMERATED:
517 ASN1_CALL(pos, asn1_dec_int(ctrl, "mode", tag, pos, seq_end, &value));
518 mwi_deactivate->mode = value;
519 mwi_deactivate->mode_present = 1;
520 break;
521 }
522 }
523
524 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
525
526 return pos;
527 }
528
529 /*!
530 * \brief Decode the MWIIndicate invoke argument parameters.
531 *
532 * \param ctrl D channel controller for diagnostic messages or global options.
533 * \param tag Component tag that identified this structure.
534 * \param pos Starting position of the ASN.1 component length.
535 * \param end End of ASN.1 decoding data buffer.
536 * \param args Arguments to fill in from the decoded buffer.
537 *
538 * \retval Start of the next ASN.1 component on success.
539 * \retval NULL on error.
540 */
rose_dec_etsi_MWIIndicate_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)541 const unsigned char *rose_dec_etsi_MWIIndicate_ARG(struct pri *ctrl, unsigned tag,
542 const unsigned char *pos, const unsigned char *end,
543 union rose_msg_invoke_args *args)
544 {
545 int32_t value;
546 size_t str_len;
547 int length;
548 int seq_offset;
549 int explicit_offset;
550 const unsigned char *explicit_end;
551 const unsigned char *seq_end;
552 const unsigned char *save_pos;
553 struct roseEtsiMWIIndicate_ARG *mwi_indicate;
554
555 mwi_indicate = &args->etsi.MWIIndicate;
556
557 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
558 if (ctrl->debug & PRI_DEBUG_APDU) {
559 pri_message(ctrl, " MWIIndicate %s\n", asn1_tag2str(tag));
560 }
561 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
562 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
563
564 /*
565 * A sequence specifies an ordered list of component types.
566 * However, for simplicity we are not checking the order of
567 * the remaining optional components.
568 */
569 mwi_indicate->controlling_user_number.length = 0;
570 mwi_indicate->basic_service_present = 0;
571 mwi_indicate->number_of_messages_present = 0;
572 mwi_indicate->controlling_user_provided_number.length = 0;
573 mwi_indicate->time_present = 0;
574 mwi_indicate->message_id_present = 0;
575 while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
576 save_pos = pos;
577 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
578 switch (tag) {
579 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
580 /* Remove EXPLICIT tag */
581 if (ctrl->debug & PRI_DEBUG_APDU) {
582 pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
583 }
584 ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
585 ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
586
587 ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
588 ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "controllingUserNr", tag, pos,
589 explicit_end, &mwi_indicate->controlling_user_number));
590
591 ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
592 break;
593 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
594 /* Remove EXPLICIT tag */
595 if (ctrl->debug & PRI_DEBUG_APDU) {
596 pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
597 }
598 ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
599 ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
600
601 ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
602 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
603 ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, explicit_end,
604 &value));
605 mwi_indicate->basic_service = value;
606 mwi_indicate->basic_service_present = 1;
607
608 ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
609 break;
610 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
611 /* Remove EXPLICIT tag */
612 if (ctrl->debug & PRI_DEBUG_APDU) {
613 pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
614 }
615 ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
616 ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
617
618 ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
619 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
620 ASN1_CALL(pos, asn1_dec_int(ctrl, "numberOfMessages", tag, pos, explicit_end,
621 &value));
622 mwi_indicate->number_of_messages = value;
623 mwi_indicate->number_of_messages_present = 1;
624
625 ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
626 break;
627 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 4:
628 /* Remove EXPLICIT tag */
629 if (ctrl->debug & PRI_DEBUG_APDU) {
630 pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
631 }
632 ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
633 ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
634
635 ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
636 ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "controllingUserProvidedNr", tag,
637 pos, explicit_end, &mwi_indicate->controlling_user_provided_number));
638
639 ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
640 break;
641 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 5:
642 /* Remove EXPLICIT tag */
643 if (ctrl->debug & PRI_DEBUG_APDU) {
644 pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
645 }
646 ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
647 ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
648
649 ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
650 ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_TYPE_GENERALIZED_TIME);
651 ASN1_CALL(pos, asn1_dec_string_max(ctrl, "time", tag, pos, explicit_end,
652 sizeof(mwi_indicate->time.str), mwi_indicate->time.str, &str_len));
653 mwi_indicate->time_present = 1;
654
655 ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
656 break;
657 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 6:
658 /* Remove EXPLICIT tag */
659 if (ctrl->debug & PRI_DEBUG_APDU) {
660 pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
661 }
662 ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
663 ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
664
665 ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
666 ASN1_CALL(pos, rose_dec_etsi_message_id(ctrl, "messageId", tag, pos,
667 explicit_end, &mwi_indicate->message_id));
668 mwi_indicate->message_id_present = 1;
669
670 ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
671 break;
672 default:
673 pos = save_pos;
674 goto cancel_options;
675 }
676 }
677 cancel_options:;
678
679 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
680
681 return pos;
682 }
683
684
685 /* ------------------------------------------------------------------- */
686 /* end rose_etsi_mwi.c */
687