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 Switch type operations for:  NI2, 4ESS, 5ESS, DMS-100
30  *
31  * \author Richard Mudgett <rmudgett@digium.com>
32  */
33 
34 
35 #include "compat.h"
36 #include "libpri.h"
37 #include "pri_internal.h"
38 #include "rose.h"
39 #include "rose_internal.h"
40 #include "asn1.h"
41 
42 
43 /* ------------------------------------------------------------------- */
44 
45 /*!
46  * \brief Encode the DMS-100 RLT_OperationInd result facility ie arguments.
47  *
48  * \param ctrl D channel controller for diagnostic messages or global options.
49  * \param pos Starting position to encode ASN.1 component.
50  * \param end End of ASN.1 encoding data buffer.
51  * \param args Arguments to encode in the buffer.
52  *
53  * \retval Start of the next ASN.1 component to encode on success.
54  * \retval NULL on error.
55  */
rose_enc_dms100_RLT_OperationInd_RES(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_result_args * args)56 unsigned char *rose_enc_dms100_RLT_OperationInd_RES(struct pri *ctrl, unsigned char *pos,
57 	unsigned char *end, const union rose_msg_result_args *args)
58 {
59 	return asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
60 		args->dms100.RLT_OperationInd.call_id);
61 }
62 
63 /*!
64  * \brief Encode the DMS-100 RLT_ThirdParty invoke facility ie arguments.
65  *
66  * \param ctrl D channel controller for diagnostic messages or global options.
67  * \param pos Starting position to encode ASN.1 component.
68  * \param end End of ASN.1 encoding data buffer.
69  * \param args Arguments to encode in the buffer.
70  *
71  * \retval Start of the next ASN.1 component to encode on success.
72  * \retval NULL on error.
73  */
rose_enc_dms100_RLT_ThirdParty_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)74 unsigned char *rose_enc_dms100_RLT_ThirdParty_ARG(struct pri *ctrl, unsigned char *pos,
75 	unsigned char *end, const union rose_msg_invoke_args *args)
76 {
77 	const struct roseDms100RLTThirdParty_ARG *rlt_thirdparty;
78 	unsigned char *seq_len;
79 
80 	ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
81 
82 	rlt_thirdparty = &args->dms100.RLT_ThirdParty;
83 	ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
84 		rlt_thirdparty->call_id));
85 	ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
86 		rlt_thirdparty->reason));
87 
88 	ASN1_CONSTRUCTED_END(seq_len, pos, end);
89 
90 	return pos;
91 }
92 
93 /*!
94  * \brief Decode the DMS-100 RLT_OperationInd result argument parameters.
95  *
96  * \param ctrl D channel controller for diagnostic messages or global options.
97  * \param tag Component tag that identified this structure.
98  * \param pos Starting position of the ASN.1 component length.
99  * \param end End of ASN.1 decoding data buffer.
100  * \param args Arguments to fill in from the decoded buffer.
101  *
102  * \retval Start of the next ASN.1 component on success.
103  * \retval NULL on error.
104  */
rose_dec_dms100_RLT_OperationInd_RES(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_result_args * args)105 const unsigned char *rose_dec_dms100_RLT_OperationInd_RES(struct pri *ctrl, unsigned tag,
106 	const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
107 {
108 	int32_t value;
109 
110 	ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
111 	ASN1_CALL(pos, asn1_dec_int(ctrl, "callId", tag, pos, end, &value));
112 	args->dms100.RLT_OperationInd.call_id = value;
113 
114 	return pos;
115 }
116 
117 /*!
118  * \brief Decode the DMS-100 RLT_ThirdParty invoke argument parameters.
119  *
120  * \param ctrl D channel controller for diagnostic messages or global options.
121  * \param tag Component tag that identified this structure.
122  * \param pos Starting position of the ASN.1 component length.
123  * \param end End of ASN.1 decoding data buffer.
124  * \param args Arguments to fill in from the decoded buffer.
125  *
126  * \retval Start of the next ASN.1 component on success.
127  * \retval NULL on error.
128  */
rose_dec_dms100_RLT_ThirdParty_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)129 const unsigned char *rose_dec_dms100_RLT_ThirdParty_ARG(struct pri *ctrl, unsigned tag,
130 	const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
131 {
132 	int32_t value;
133 	int length;
134 	int seq_offset;
135 	const unsigned char *seq_end;
136 	struct roseDms100RLTThirdParty_ARG *rlt_third_party;
137 
138 	rlt_third_party = &args->dms100.RLT_ThirdParty;
139 
140 	ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
141 	if (ctrl->debug & PRI_DEBUG_APDU) {
142 		pri_message(ctrl, "  RLT_ThirdParty %s\n", asn1_tag2str(tag));
143 	}
144 	ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
145 	ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
146 
147 	ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
148 	ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
149 	ASN1_CALL(pos, asn1_dec_int(ctrl, "callId", tag, pos, seq_end, &value));
150 	rlt_third_party->call_id = value;
151 
152 	ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
153 	ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
154 	ASN1_CALL(pos, asn1_dec_int(ctrl, "reason", tag, pos, seq_end, &value));
155 	rlt_third_party->reason = value;
156 
157 	/* Fixup will skip over any OPTIONAL information */
158 	ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
159 
160 	return pos;
161 }
162 
163 /*!
164  * \brief Encode the NI2 InformationFollowing invoke facility ie arguments.
165  *
166  * \param ctrl D channel controller for diagnostic messages or global options.
167  * \param pos Starting position to encode ASN.1 component.
168  * \param end End of ASN.1 encoding data buffer.
169  * \param args Arguments to encode in the buffer.
170  *
171  * \retval Start of the next ASN.1 component to encode on success.
172  * \retval NULL on error.
173  */
rose_enc_ni2_InformationFollowing_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)174 unsigned char *rose_enc_ni2_InformationFollowing_ARG(struct pri *ctrl,
175 	unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
176 {
177 	/* Encode the unknown enumeration value. */
178 	return asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
179 		args->ni2.InformationFollowing.value);
180 }
181 
182 /*!
183  * \brief Encode the NI2 InitiateTransfer invoke facility ie arguments.
184  *
185  * \param ctrl D channel controller for diagnostic messages or global options.
186  * \param pos Starting position to encode ASN.1 component.
187  * \param end End of ASN.1 encoding data buffer.
188  * \param args Arguments to encode in the buffer.
189  *
190  * \retval Start of the next ASN.1 component to encode on success.
191  * \retval NULL on error.
192  */
rose_enc_ni2_InitiateTransfer_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)193 unsigned char *rose_enc_ni2_InitiateTransfer_ARG(struct pri *ctrl, unsigned char *pos,
194 	unsigned char *end, const union rose_msg_invoke_args *args)
195 {
196 	const struct roseNi2InitiateTransfer_ARG *initiate_transfer;
197 	unsigned char *seq_len;
198 
199 	ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
200 
201 	initiate_transfer = &args->ni2.InitiateTransfer;
202 	ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
203 		initiate_transfer->call_reference));
204 
205 	ASN1_CONSTRUCTED_END(seq_len, pos, end);
206 
207 	return pos;
208 }
209 
210 /*!
211  * \brief Decode the NI2 InformationFollowing invoke argument parameters.
212  *
213  * \param ctrl D channel controller for diagnostic messages or global options.
214  * \param tag Component tag that identified this structure.
215  * \param pos Starting position of the ASN.1 component length.
216  * \param end End of ASN.1 decoding data buffer.
217  * \param args Arguments to fill in from the decoded buffer.
218  *
219  * \retval Start of the next ASN.1 component on success.
220  * \retval NULL on error.
221  */
rose_dec_ni2_InformationFollowing_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)222 const unsigned char *rose_dec_ni2_InformationFollowing_ARG(struct pri *ctrl,
223 	unsigned tag, const unsigned char *pos, const unsigned char *end,
224 	union rose_msg_invoke_args *args)
225 {
226 	int32_t value;
227 
228 	ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
229 	ASN1_CALL(pos, asn1_dec_int(ctrl, "unknown", tag, pos, end, &value));
230 	args->ni2.InformationFollowing.value = value;
231 
232 	return pos;
233 }
234 
235 /*!
236  * \brief Decode the NI2 InitiateTransfer invoke argument parameters.
237  *
238  * \param ctrl D channel controller for diagnostic messages or global options.
239  * \param tag Component tag that identified this structure.
240  * \param pos Starting position of the ASN.1 component length.
241  * \param end End of ASN.1 decoding data buffer.
242  * \param args Arguments to fill in from the decoded buffer.
243  *
244  * \retval Start of the next ASN.1 component on success.
245  * \retval NULL on error.
246  */
rose_dec_ni2_InitiateTransfer_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)247 const unsigned char *rose_dec_ni2_InitiateTransfer_ARG(struct pri *ctrl, unsigned tag,
248 	const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
249 {
250 	int32_t value;
251 	int length;
252 	int seq_offset;
253 	const unsigned char *seq_end;
254 	struct roseNi2InitiateTransfer_ARG *initiate_transfer;
255 
256 	initiate_transfer = &args->ni2.InitiateTransfer;
257 
258 	ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
259 	if (ctrl->debug & PRI_DEBUG_APDU) {
260 		pri_message(ctrl, "  InitiateTransfer %s\n", asn1_tag2str(tag));
261 	}
262 	ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
263 	ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
264 
265 	ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
266 	ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
267 	ASN1_CALL(pos, asn1_dec_int(ctrl, "callReference", tag, pos, seq_end, &value));
268 	initiate_transfer->call_reference = value;
269 
270 	/* Fixup will skip over any OPTIONAL information */
271 	ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
272 
273 	return pos;
274 }
275 
276 /* ------------------------------------------------------------------- */
277 /* end rose_other.c */
278