Harald Welte | 474fd7d | 2017-12-29 16:01:39 +0100 | [diff] [blame] | 1 | #include "mncc.h" |
| 2 | #include "MNCC_Types.hh" |
| 3 | |
| 4 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) |
| 5 | |
| 6 | namespace MNCC__Types { |
| 7 | |
Pau Espin Pedrol | 563b3d0 | 2020-09-09 20:19:52 +0200 | [diff] [blame] | 8 | static int mncc_sock_version = MNCC_SOCK_VERSION; |
| 9 | |
| 10 | BOOLEAN set__MNCC__version(INTEGER const& version) |
| 11 | { |
| 12 | if (version != 6 && version != 7) |
| 13 | return false; |
| 14 | mncc_sock_version = version; |
| 15 | return true; |
| 16 | } |
| 17 | |
Harald Welte | 474fd7d | 2017-12-29 16:01:39 +0100 | [diff] [blame] | 18 | static void enc_bcap(struct gsm_mncc_bearer_cap *out, const MNCC__bearer__cap& in) |
| 19 | { |
| 20 | out->transfer = in.transfer(); |
| 21 | out->mode = in.mode(); |
| 22 | out->coding = in.coding(); |
| 23 | out->radio = in.radio(); |
| 24 | out->speech_ctm = in.speech__ctm(); |
| 25 | |
| 26 | for (int i = 0; i < in.speech__ver().lengthof(); i++) |
| 27 | out->speech_ver[i] = in.speech__ver()[i]; |
| 28 | |
| 29 | if (in.data().is_value()) { |
| 30 | MNCC__bearer__cap__data data = in.data(); |
| 31 | out->data.rate_adaption = (gsm48_bcap_ra) (int) data.rate__adaptation(); |
| 32 | out->data.sig_access = (gsm48_bcap_sig_access) (int) data.sig__access(); |
| 33 | out->data.async = data.async(); |
| 34 | out->data.nr_stop_bits = data.nr__stop__bits(); |
| 35 | out->data.nr_data_bits = data.nr__data__bits(); |
| 36 | out->data.user_rate = (gsm48_bcap_user_rate) (int) data.user__rate(); |
| 37 | out->data.parity = (gsm48_bcap_parity) (int) data.parity(); |
| 38 | out->data.interm_rate = (gsm48_bcap_interm_rate) (int) data.interm__rate(); |
| 39 | out->data.transp = (gsm48_bcap_transp) (int) data.transp(); |
| 40 | out->data.modem_type = (gsm48_bcap_modem_type) (int) data.modem__type(); |
| 41 | } |
| 42 | |
| 43 | } |
| 44 | |
| 45 | static MNCC__bearer__cap dec_bcap(const struct gsm_mncc_bearer_cap *in) |
| 46 | { |
| 47 | MNCC__bearer__cap__data data; |
| 48 | MNCC__speech__vers vers; |
| 49 | data = MNCC__bearer__cap__data((GSM48__bcap__ra) in->data.rate_adaption, |
| 50 | (GSM48__bcap__sig__access) in->data.sig_access, |
| 51 | in->data.async, |
| 52 | in->data.nr_stop_bits, |
| 53 | in->data.nr_data_bits, |
| 54 | (GSM48__bcap__user__rate) in->data.user_rate, |
| 55 | (GSM48__bcap__parity) in->data.parity, |
| 56 | (GSM48__bcap__interm__rate) in->data.interm_rate, |
| 57 | (GSM48__bcap__transp) in->data.transp, |
| 58 | (GSM48__bcap__modem__type) in->data.modem_type); |
| 59 | |
Harald Welte | 0556600 | 2018-03-26 20:52:45 +0200 | [diff] [blame] | 60 | for (unsigned int i = 0; i < ARRAY_SIZE(in->speech_ver); i++) { |
| 61 | vers[i] = in->speech_ver[i]; |
| 62 | if (vers[i] == -1) |
| 63 | break; |
| 64 | } |
Harald Welte | 474fd7d | 2017-12-29 16:01:39 +0100 | [diff] [blame] | 65 | |
| 66 | return MNCC__bearer__cap(in->transfer, in->mode, in->coding, in->radio, in->speech_ctm, |
| 67 | vers, data); |
| 68 | } |
| 69 | |
| 70 | |
| 71 | static void enc_number(struct gsm_mncc_number *num, const MNCC__number& in) |
| 72 | { |
| 73 | num->type = in.number__type(); |
| 74 | num->plan = in.plan(); |
| 75 | num->present = in.presence(); |
| 76 | num->screen = in.screen(); |
| 77 | strncpy(num->number, in.number(), sizeof(num->number)); |
| 78 | } |
| 79 | |
| 80 | static MNCC__number dec_number(const struct gsm_mncc_number *num) |
| 81 | { |
| 82 | return MNCC__number(num->type, num->plan,num->present, num->screen, num->number); |
| 83 | } |
| 84 | |
| 85 | OCTETSTRING enc__MNCC__PDU(const MNCC__PDU& in) |
| 86 | { |
Harald Welte | 474fd7d | 2017-12-29 16:01:39 +0100 | [diff] [blame] | 87 | struct gsm_mncc mncc; |
| 88 | OCTETSTRING ret_val; |
Pau Espin Pedrol | 563b3d0 | 2020-09-09 20:19:52 +0200 | [diff] [blame] | 89 | TTCN_Buffer ttcn_buffer; |
Harald Welte | 474fd7d | 2017-12-29 16:01:39 +0100 | [diff] [blame] | 90 | |
| 91 | memset(&mncc, 0, sizeof(mncc)); |
| 92 | mncc.msg_type = in.msg__type(); |
| 93 | |
Harald Welte | 1823cb1 | 2018-02-11 11:39:29 +0100 | [diff] [blame] | 94 | switch (in.u().get_selection()) { |
| 95 | case MNCC__MsgUnion::ALT_signal: { |
| 96 | const MNCC__PDU__Signal& in_sig = in.u().signal(); |
Harald Welte | 474fd7d | 2017-12-29 16:01:39 +0100 | [diff] [blame] | 97 | mncc.callref = in_sig.callref(); |
| 98 | if (in_sig.bearer__cap().is_value()) { |
| 99 | enc_bcap(&mncc.bearer_cap, in_sig.bearer__cap()); |
| 100 | mncc.fields |= MNCC_F_BEARER_CAP; |
| 101 | } |
| 102 | if (in_sig.called().is_value()) { |
| 103 | enc_number(&mncc.called, in_sig.called()); |
| 104 | mncc.fields |= MNCC_F_CALLED; |
| 105 | } |
| 106 | if (in_sig.calling().is_value()) { |
| 107 | enc_number(&mncc.calling, in_sig.calling()); |
| 108 | mncc.fields |= MNCC_F_CALLING; |
| 109 | } |
| 110 | if (in_sig.redirecting().is_value()) { |
| 111 | enc_number(&mncc.redirecting, in_sig.redirecting()); |
| 112 | mncc.fields |= MNCC_F_REDIRECTING; |
| 113 | } |
| 114 | if (in_sig.connected().is_value()) { |
| 115 | enc_number(&mncc.connected, in_sig.connected()); |
| 116 | mncc.fields |= MNCC_F_CONNECTED; |
| 117 | } |
| 118 | if (in_sig.cause().is_value()) { |
| 119 | const MNCC__cause &cause = in_sig.cause(); |
| 120 | TTCN_Buffer ttcn_buffer(cause.diag()); |
| 121 | mncc.cause.location = cause.location(); |
| 122 | mncc.cause.coding = cause.coding(); |
| 123 | mncc.cause.rec = cause.rec(); |
| 124 | mncc.cause.rec_val = cause.rec__val(); |
| 125 | mncc.cause.value = cause.val(); |
| 126 | mncc.cause.diag_len = ttcn_buffer.get_len(); |
| 127 | if (mncc.cause.diag_len > (int) sizeof(mncc.cause.diag)) { |
| 128 | TTCN_error("MNCC diagnostics length %u too long", mncc.cause.diag_len); |
| 129 | mncc.cause.diag_len = sizeof(mncc.cause.diag); |
| 130 | } |
| 131 | memcpy(mncc.cause.diag, ttcn_buffer.get_data(), ttcn_buffer.get_len()); |
| 132 | mncc.fields |= MNCC_F_CAUSE; |
| 133 | } |
| 134 | if (in_sig.progress().is_value()) { |
| 135 | const MNCC__progress &progress = in_sig.progress(); |
| 136 | mncc.progress.coding = progress.coding(); |
| 137 | mncc.progress.location = progress.location(); |
| 138 | mncc.progress.descr = progress.descr(); |
| 139 | mncc.fields |= MNCC_F_PROGRESS; |
| 140 | } |
| 141 | if (in_sig.useruser().is_value()) { |
| 142 | const MNCC__useruser &useruser = in_sig.useruser(); |
| 143 | mncc.useruser.proto = useruser.proto(); |
| 144 | strncpy(mncc.useruser.info, useruser.info(), sizeof(mncc.useruser.info)); |
| 145 | mncc.fields |= MNCC_F_USERUSER; |
| 146 | } |
| 147 | if (in_sig.facility().is_value()) { |
| 148 | const CHARSTRING &fac = in_sig.facility(); |
| 149 | strncpy(mncc.facility.info, fac, sizeof(mncc.facility.info)); |
| 150 | mncc.facility.len = strlen(mncc.facility.info); |
| 151 | mncc.fields |= MNCC_F_FACILITY; |
| 152 | } |
| 153 | if (in_sig.cccap().is_value()) { |
| 154 | const MNCC__cccap &cccap = in_sig.cccap(); |
| 155 | mncc.cccap.dtmf = cccap.dtmf(); |
| 156 | mncc.cccap.pcp = cccap.pcp(); |
| 157 | mncc.fields |= MNCC_F_CCCAP; |
| 158 | } |
| 159 | if (in_sig.ssversion().is_value()) { |
| 160 | const CHARSTRING &ssv = in_sig.ssversion(); |
| 161 | strncpy(mncc.ssversion.info, ssv, sizeof(mncc.ssversion.info)); |
| 162 | mncc.ssversion.len = strlen(mncc.ssversion.info); |
| 163 | mncc.fields |= MNCC_F_SSVERSION; |
| 164 | } |
| 165 | mncc.clir.sup = in_sig.clir__sup(); |
| 166 | mncc.clir.inv = in_sig.clir__inv(); |
| 167 | if (in_sig.signal().is_value()) { |
| 168 | const INTEGER &sig = in_sig.signal(); |
| 169 | mncc.signal = sig; |
| 170 | mncc.fields |= MNCC_F_SIGNAL; |
| 171 | } |
| 172 | if (in_sig.keypad().is_value()) { |
Harald Welte | d13700d | 2018-02-02 20:06:52 +0100 | [diff] [blame] | 173 | const CHARSTRING &kpd = in_sig.keypad(); |
| 174 | mncc.signal = (int) kpd[0].get_char(); |
Harald Welte | 474fd7d | 2017-12-29 16:01:39 +0100 | [diff] [blame] | 175 | mncc.fields |= MNCC_F_KEYPAD; |
| 176 | } |
| 177 | mncc.more = in_sig.more(); |
| 178 | mncc.notify = in_sig.notify(); |
| 179 | if (in_sig.emergency().is_value()) { |
| 180 | const INTEGER &emerg = in_sig.emergency(); |
| 181 | mncc.emergency = emerg; |
| 182 | mncc.fields |= MNCC_F_EMERGENCY; |
| 183 | } |
| 184 | strncpy(mncc.imsi, in_sig.imsi(), sizeof(mncc.imsi)); |
| 185 | mncc.lchan_type = in_sig.lchan__type(); |
| 186 | mncc.lchan_mode = in_sig.lchan__mode(); |
| 187 | ret_val = OCTETSTRING(sizeof(mncc), (uint8_t *)&mncc); |
Harald Welte | 1823cb1 | 2018-02-11 11:39:29 +0100 | [diff] [blame] | 188 | } |
| 189 | break; |
| 190 | case MNCC__MsgUnion::ALT_data: |
Harald Welte | 474fd7d | 2017-12-29 16:01:39 +0100 | [diff] [blame] | 191 | struct gsm_data_frame data; |
| 192 | memset(&data, 0, sizeof(data)); |
| 193 | data.msg_type = in.msg__type(); |
| 194 | ret_val = OCTETSTRING(sizeof(data), (uint8_t *)&data); |
| 195 | ret_val = ret_val & in.u().data().data(); |
Harald Welte | 1823cb1 | 2018-02-11 11:39:29 +0100 | [diff] [blame] | 196 | break; |
| 197 | case MNCC__MsgUnion::ALT_rtp: |
Pau Espin Pedrol | 563b3d0 | 2020-09-09 20:19:52 +0200 | [diff] [blame] | 198 | switch (mncc_sock_version) { |
| 199 | case 6: |
| 200 | struct gsm_mncc_rtp_mncc6 rtp_old; |
| 201 | memset(&rtp_old, 0, sizeof(rtp_old)); |
| 202 | rtp_old.msg_type = in.msg__type(); |
| 203 | rtp_old.callref = in.u().rtp().callref(); |
| 204 | ttcn_buffer.put_string(in.u().rtp().ip()); |
| 205 | if (!in.u().rtp().is__ipv6()) { |
| 206 | memcpy(&rtp_old.ip, ttcn_buffer.get_data(), sizeof(struct in_addr)); |
| 207 | rtp_old.ip = ntohl(rtp_old.ip); |
| 208 | } /* else: ipv6 not supported in MNCCv6 */ |
| 209 | rtp_old.port = in.u().rtp().rtp__port(); |
| 210 | rtp_old.payload_type = in.u().rtp().payload__type(); |
| 211 | rtp_old.payload_msg_type = in.u().rtp().payload__msg__type(); |
| 212 | ret_val = OCTETSTRING(sizeof(rtp_old), (uint8_t *) &rtp_old); |
| 213 | break; |
| 214 | case 7: |
| 215 | struct gsm_mncc_rtp rtp; |
| 216 | memset(&rtp, 0, sizeof(rtp)); |
| 217 | rtp.msg_type = in.msg__type(); |
| 218 | rtp.callref = in.u().rtp().callref(); |
| 219 | ttcn_buffer.put_string(in.u().rtp().ip()); |
| 220 | if (in.u().rtp().is__ipv6()) { |
| 221 | // if(in.u().rtp().ip().lengthof() != 16) print error |
| 222 | rtp.addr.ss_family = AF_INET6; |
| 223 | memcpy(&((struct sockaddr_in6*)&rtp.addr)->sin6_addr, ttcn_buffer.get_data(), |
| 224 | sizeof(struct in6_addr)); |
| 225 | ((struct sockaddr_in6*)&rtp.addr)->sin6_port = htons(in.u().rtp().rtp__port()); |
| 226 | } else { |
| 227 | // if(in.u().rtp().ip().lengthof() != 4) print error |
| 228 | rtp.addr.ss_family = AF_INET; |
| 229 | memcpy(&((struct sockaddr_in*)&rtp.addr)->sin_addr, ttcn_buffer.get_data(), |
| 230 | sizeof(struct in_addr)); |
| 231 | ((struct sockaddr_in*)&rtp.addr)->sin_port = htons(in.u().rtp().rtp__port()); |
| 232 | } |
| 233 | rtp.payload_type = in.u().rtp().payload__type(); |
| 234 | rtp.payload_msg_type = in.u().rtp().payload__msg__type(); |
| 235 | ret_val = OCTETSTRING(sizeof(rtp), (uint8_t *) &rtp); |
| 236 | break; |
| 237 | } |
Harald Welte | 1823cb1 | 2018-02-11 11:39:29 +0100 | [diff] [blame] | 238 | break; |
| 239 | case MNCC__MsgUnion::ALT_hello: |
Harald Welte | 474fd7d | 2017-12-29 16:01:39 +0100 | [diff] [blame] | 240 | struct gsm_mncc_hello hello; |
| 241 | memset(&hello, 0, sizeof(hello)); |
| 242 | hello.msg_type = in.msg__type(); |
| 243 | hello.version = in.u().hello().version(); |
| 244 | hello.mncc_size = in.u().hello().mncc__size(); |
| 245 | hello.data_frame_size = in.u().hello().data__frame__size(); |
| 246 | hello.called_offset = in.u().hello().called__offset(); |
| 247 | hello.signal_offset = in.u().hello().signal__offset(); |
| 248 | hello.emergency_offset = in.u().hello().emergency__offset(); |
| 249 | hello.lchan_type_offset = in.u().hello().lchan__type__offset(); |
| 250 | ret_val = OCTETSTRING(sizeof(hello), (uint8_t *) &hello); |
Harald Welte | 1823cb1 | 2018-02-11 11:39:29 +0100 | [diff] [blame] | 251 | break; |
Harald Welte | 474fd7d | 2017-12-29 16:01:39 +0100 | [diff] [blame] | 252 | } |
| 253 | |
| 254 | return ret_val; |
| 255 | } |
| 256 | |
| 257 | MNCC__PDU dec__MNCC__PDU(const OCTETSTRING& in) |
| 258 | { |
| 259 | TTCN_Buffer ttcn_buffer(in); |
| 260 | const struct gsm_mncc *in_mncc; |
| 261 | MNCC__PDU__Signal sign; |
| 262 | const struct gsm_mncc_hello *in_hello; |
| 263 | MNCC__PDU__Hello hello; |
| 264 | const struct gsm_data_frame *in_data; |
| 265 | MNCC__PDU__Data data; |
| 266 | const struct gsm_mncc_rtp *in_rtp; |
Pau Espin Pedrol | 563b3d0 | 2020-09-09 20:19:52 +0200 | [diff] [blame] | 267 | const struct gsm_mncc_rtp_mncc6 *in_rtp_old; |
Harald Welte | 474fd7d | 2017-12-29 16:01:39 +0100 | [diff] [blame] | 268 | MNCC__PDU__Rtp rtp; |
| 269 | MNCC__MsgUnion u; |
Pau Espin Pedrol | 563b3d0 | 2020-09-09 20:19:52 +0200 | [diff] [blame] | 270 | bool is_ipv6; |
| 271 | OCTETSTRING ip; |
| 272 | uint16_t port; |
Harald Welte | 474fd7d | 2017-12-29 16:01:39 +0100 | [diff] [blame] | 273 | |
| 274 | in_mncc = (struct gsm_mncc *) ttcn_buffer.get_read_data(); |
| 275 | |
Harald Welte | 8a10e86 | 2018-01-17 13:58:26 +0100 | [diff] [blame] | 276 | sign.set_implicit_omit(); |
| 277 | hello.set_implicit_omit(); |
| 278 | data.set_implicit_omit(); |
| 279 | rtp.set_implicit_omit(); |
| 280 | |
Harald Welte | 474fd7d | 2017-12-29 16:01:39 +0100 | [diff] [blame] | 281 | switch (in_mncc->msg_type) { |
| 282 | case MNCC_SOCKET_HELLO: |
| 283 | in_hello = (const struct gsm_mncc_hello *) in_mncc; |
| 284 | hello = MNCC__PDU__Hello(in_hello->version, |
| 285 | in_hello->mncc_size, |
| 286 | in_hello->data_frame_size, |
| 287 | in_hello->called_offset, |
| 288 | in_hello->signal_offset, |
| 289 | in_hello->emergency_offset, |
| 290 | in_hello->lchan_type_offset); |
| 291 | u.hello() = hello; |
| 292 | break; |
| 293 | case GSM_TCHF_FRAME: |
| 294 | case GSM_TCHF_FRAME_EFR: |
| 295 | case GSM_TCHH_FRAME: |
| 296 | case GSM_TCH_FRAME_AMR: |
| 297 | case GSM_BAD_FRAME: |
| 298 | in_data = (const struct gsm_data_frame *) in_mncc; |
| 299 | u.data() = MNCC__PDU__Data(in_data->callref, |
| 300 | substr(in, offsetof(struct gsm_data_frame, data), |
| 301 | in.lengthof() - offsetof(struct gsm_data_frame, data))); |
| 302 | break; |
| 303 | case MNCC_RTP_CREATE: |
| 304 | case MNCC_RTP_CONNECT: |
| 305 | case MNCC_RTP_FREE: |
Pau Espin Pedrol | 563b3d0 | 2020-09-09 20:19:52 +0200 | [diff] [blame] | 306 | switch (mncc_sock_version) { |
| 307 | case 6: |
| 308 | struct in_addr inaddr; |
| 309 | in_rtp_old = (const struct gsm_mncc_rtp_mncc6 *) in_mncc; |
| 310 | inaddr.s_addr = htonl(in_rtp_old->ip); |
| 311 | ip = OCTETSTRING(sizeof(struct in_addr), |
| 312 | (const unsigned char*)&inaddr); |
| 313 | rtp = MNCC__PDU__Rtp(in_rtp_old->callref, false, ip, in_rtp_old->port, in_rtp_old->payload_type, |
| 314 | in_rtp_old->payload_msg_type, in_rtp_old->sdp); |
| 315 | u.rtp() = rtp; |
| 316 | break; |
| 317 | case 7: |
| 318 | in_rtp = (const struct gsm_mncc_rtp *) in_mncc; |
| 319 | switch (in_rtp->addr.ss_family) { |
| 320 | case AF_INET6: |
| 321 | is_ipv6 = true; |
| 322 | port = ntohs(((struct sockaddr_in6*)&in_rtp->addr)->sin6_port); |
| 323 | ip = OCTETSTRING(sizeof(struct in6_addr), |
| 324 | (const unsigned char*)&((struct sockaddr_in6*)&in_rtp->addr)->sin6_addr); |
| 325 | |
| 326 | break; |
| 327 | case AF_UNSPEC: //RTP_CREATE and RTP_FREE can contain fully zeroed addr |
| 328 | case AF_INET: |
| 329 | is_ipv6 = false; |
| 330 | port = ntohs(((struct sockaddr_in*)&in_rtp->addr)->sin_port); |
| 331 | ip = OCTETSTRING(sizeof(struct in_addr), |
| 332 | (const unsigned char*)&((struct sockaddr_in*)&in_rtp->addr)->sin_addr); |
| 333 | break; |
| 334 | } |
| 335 | rtp = MNCC__PDU__Rtp(in_rtp->callref, is_ipv6, ip, port, in_rtp->payload_type, |
| 336 | in_rtp->payload_msg_type, in_rtp->sdp); |
| 337 | u.rtp() = rtp; |
| 338 | break; |
| 339 | } |
Harald Welte | 474fd7d | 2017-12-29 16:01:39 +0100 | [diff] [blame] | 340 | break; |
| 341 | default: |
| 342 | sign.callref() = in_mncc->callref; |
| 343 | if (in_mncc->fields & MNCC_F_BEARER_CAP) { |
| 344 | sign.bearer__cap() = dec_bcap(&in_mncc->bearer_cap); |
| 345 | } |
| 346 | if (in_mncc->fields & MNCC_F_CALLED) |
| 347 | sign.called() = dec_number(&in_mncc->called); |
| 348 | if (in_mncc->fields & MNCC_F_CALLING) |
| 349 | sign.calling() = dec_number(&in_mncc->calling); |
| 350 | if (in_mncc->fields & MNCC_F_REDIRECTING) |
| 351 | sign.redirecting() = dec_number(&in_mncc->redirecting); |
| 352 | if (in_mncc->fields & MNCC_F_CONNECTED) |
| 353 | sign.connected() = dec_number(&in_mncc->connected); |
| 354 | if (in_mncc->fields & MNCC_F_CAUSE) { |
| 355 | sign.cause() = MNCC__cause(in_mncc->cause.location, |
| 356 | in_mncc->cause.coding, |
| 357 | in_mncc->cause.rec, |
| 358 | in_mncc->cause.rec_val, |
| 359 | in_mncc->cause.value, |
| 360 | OCTETSTRING(in_mncc->cause.diag_len, |
| 361 | (const uint8_t *)in_mncc->cause.diag)); |
| 362 | } |
| 363 | if (in_mncc->fields & MNCC_F_USERUSER) { |
| 364 | sign.useruser() = MNCC__useruser(in_mncc->useruser.proto, |
| 365 | CHARSTRING(in_mncc->useruser.info)); |
| 366 | } |
| 367 | if (in_mncc->fields & MNCC_F_PROGRESS) { |
| 368 | sign.progress() = MNCC__progress(in_mncc->progress.coding, |
| 369 | in_mncc->progress.location, |
| 370 | in_mncc->progress.descr); |
| 371 | } |
| 372 | if (in_mncc->fields & MNCC_F_EMERGENCY) |
| 373 | sign.emergency() = in_mncc->emergency; |
| 374 | if (in_mncc->fields & MNCC_F_FACILITY) |
| 375 | sign.facility() = CHARSTRING(in_mncc->facility.info); |
| 376 | if (in_mncc->fields & MNCC_F_SSVERSION) |
| 377 | sign.ssversion() = CHARSTRING(in_mncc->ssversion.info); |
| 378 | if (in_mncc->fields & MNCC_F_CCCAP) |
| 379 | sign.cccap() = MNCC__cccap(in_mncc->cccap.dtmf, in_mncc->cccap.pcp); |
Harald Welte | d13700d | 2018-02-02 20:06:52 +0100 | [diff] [blame] | 380 | if (in_mncc->fields & MNCC_F_KEYPAD) { |
| 381 | char kpd[2] = { (char) in_mncc->keypad, 0 }; |
| 382 | sign.keypad() = CHARSTRING(kpd); |
| 383 | } |
Harald Welte | 474fd7d | 2017-12-29 16:01:39 +0100 | [diff] [blame] | 384 | if (in_mncc->fields & MNCC_F_SIGNAL) |
| 385 | sign.signal() = in_mncc->signal; |
| 386 | |
| 387 | sign.clir__sup() = in_mncc->clir.sup; |
| 388 | sign.clir__inv() = in_mncc->clir.inv; |
| 389 | sign.more() = in_mncc->more; |
| 390 | sign.notify() = in_mncc->notify; |
| 391 | sign.imsi() = CHARSTRING(in_mncc->imsi); |
| 392 | sign.lchan__type() = in_mncc->lchan_type; |
| 393 | sign.lchan__mode() = in_mncc->lchan_mode; |
Neels Hofmeyr | 06b859c | 2019-11-12 01:23:04 +0100 | [diff] [blame] | 394 | sign.sdp() = in_mncc->sdp; |
Harald Welte | 474fd7d | 2017-12-29 16:01:39 +0100 | [diff] [blame] | 395 | u.signal() = sign; |
| 396 | break; |
| 397 | } |
| 398 | return MNCC__PDU(in_mncc->msg_type, u); |
| 399 | } |
| 400 | |
| 401 | } |