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