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