comparison sip-out/call_setup.c @ 154:e54b0a9e322f

beginning of themwi-sip-out
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 11 Oct 2022 23:04:01 -0800
parents sip-in/call_setup.c@1bbe57df74f6
children e89619893c1e
comparison
equal deleted inserted replaced
153:99fd4ae573ae 154:e54b0a9e322f
1 /*
2 * In this module we implement our initial handling of MNCC_SETUP_IND.
3 */
4
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <sys/time.h>
8 #include <netinet/in.h>
9 #include <stdio.h>
10 #include <stdint.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <strings.h>
14 #include <syslog.h>
15 #include "../include/mncc.h"
16 #include "../include/gsm48_const.h"
17 #include "../include/out_routes.h"
18 #include "call.h"
19
20 extern struct call *find_call_by_mncc_callref();
21
22 extern int block_1900_numbers;
23 extern struct call *call_list;
24
25 static void
26 reject_mo_call(mncc, callref, cause_loc, cause_val)
27 struct mncc_conn *mncc;
28 uint32_t callref;
29 {
30 struct gsm_mncc msg;
31
32 bzero(&msg, sizeof(struct gsm_mncc));
33 msg.msg_type = MNCC_REJ_REQ;
34 msg.callref = callref;
35 mncc_set_cause(&msg, cause_loc, cause_val);
36 send_mncc_to_sock(mncc, &msg, sizeof(struct gsm_mncc));
37 }
38
39 static void
40 send_call_proceeding(call)
41 struct call *call;
42 {
43 struct gsm_mncc msg;
44
45 bzero(&msg, sizeof(struct gsm_mncc));
46 msg.msg_type = MNCC_CALL_PROC_REQ;
47 msg.callref = call->mncc_callref;
48 send_mncc_to_sock(call->mncc, &msg, sizeof(struct gsm_mncc));
49 }
50
51 void
52 handle_setup_ind(mncc, msg, msglen)
53 struct mncc_conn *mncc;
54 struct gsm_mncc *msg;
55 unsigned msglen;
56 {
57 struct call *call;
58 struct sip_out_dest *dest;
59 struct special_num_route *special_rt;
60 char to_sip_user[MAX_SIP_USER_PART+1];
61 int rc;
62
63 if (msglen != sizeof(struct gsm_mncc)) {
64 syslog(LOG_CRIT,
65 "FATAL: Rx MNCC_SETUP_IND has wrong length");
66 exit(1);
67 }
68 /* check for duplicates */
69 call = find_call_by_mncc_callref(mncc, msg->callref);
70 if (call) {
71 syslog(LOG_ERR, "duplicate MNCC_SETUP_IND for callref 0x%x",
72 msg->callref);
73 /* drop it like OsmoMSC's mncc_builtin does */
74 return;
75 }
76 if (!(msg->fields & MNCC_F_CALLED) ||
77 !(msg->fields & MNCC_F_BEARER_CAP)) {
78 syslog(LOG_ERR, "rejecting MO call 0x%x: missing mandatory IE",
79 msg->callref);
80 reject_mo_call(mncc, msg->callref, GSM48_CAUSE_LOC_PRN_S_LU,
81 GSM48_CC_CAUSE_INVAL_MAND_INF);
82 return;
83 }
84 /* route based on destination address */
85 refresh_out_routes_db();
86 if (msg->called.type == GSM48_TON_INTERNATIONAL) {
87 rc = grok_number_string(msg->called.number, 0);
88 if (rc < 2 || rc > MAX_E164_NUMBER) {
89 inv_nr_format: reject_mo_call(mncc, msg->callref,
90 GSM48_CAUSE_LOC_PRN_S_LU,
91 GSM48_CC_CAUSE_INV_NR_FORMAT);
92 return;
93 }
94 if (msg->called.number[0] == '0')
95 goto inv_nr_format;
96 if (msg->called.number[0] == '1') {
97 if (rc != 11)
98 goto inv_nr_format;
99 if (!is_nanp_valid_prefix(msg->called.number+1))
100 goto inv_nr_format;
101 if (msg->called.number[1] == '9' &&
102 msg->called.number[2] == '0' &&
103 msg->called.number[3] == '0' &&
104 block_1900_numbers) {
105 call_barred: reject_mo_call(mncc, msg->callref,
106 GSM48_CAUSE_LOC_PRN_S_LU,
107 GSM48_CC_CAUSE_OP_DET_BARRING);
108 return;
109 }
110 }
111 rc = route_e164_number(msg->called.number, &dest);
112 if (!rc) {
113 no_route_to_dest: reject_mo_call(mncc, msg->callref,
114 GSM48_CAUSE_LOC_PRN_S_LU,
115 GSM48_CC_CAUSE_NO_ROUTE);
116 return;
117 }
118 to_sip_user[0] = '+';
119 strcpy(to_sip_user+1, msg->called.number);
120 } else {
121 rc = route_special_number(msg->called.number, &dest,
122 &special_rt);
123 if (!rc)
124 goto no_route_to_dest;
125 strcpy(to_sip_user, special_rt->sip_user);
126 }
127 /* validate From number */
128 if (!(msg->fields & MNCC_F_CALLING))
129 goto call_barred;
130 if (msg->calling.type != GSM48_TON_INTERNATIONAL)
131 goto call_barred;
132 if (grok_number_string(msg->calling.number, 0) != 11 ||
133 msg->calling.number[0] != '1')
134 goto call_barred;
135 /* speech-only restriction */
136 if (msg->bearer_cap.transfer != GSM48_BCAP_ITCAP_SPEECH ||
137 msg->bearer_cap.mode != GSM48_BCAP_TMOD_CIRCUIT) {
138 syslog(LOG_ERR, "rejecting MO call 0x%x: bad bearer cap",
139 msg->callref);
140 reject_mo_call(mncc, msg->callref, GSM48_CAUSE_LOC_PRN_S_LU,
141 GSM48_CC_CAUSE_BEARER_CA_UNAVAIL);
142 return;
143 }
144 /* TMGW must be up and running */
145 rc = connect_tmgw_socket();
146 if (rc < 0) {
147 reject_mo_call(mncc, msg->callref, GSM48_CAUSE_LOC_PRN_S_LU,
148 GSM48_CC_CAUSE_NETWORK_OOO);
149 return;
150 }
151 /* allocate struct call and being stateful processing */
152 call = malloc(sizeof(struct call));
153 if (!call) {
154 syslog(LOG_CRIT, "failed malloc for outbound call!");
155 reject_mo_call(mncc, msg->callref, GSM48_CAUSE_LOC_PRN_S_LU,
156 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
157 return;
158 }
159 bzero(call, sizeof(struct call));
160 call->mncc = mncc;
161 call->mncc_callref = msg->callref;
162 call->from_user[0] = '+';
163 strcpy(call->from_user+1, msg->calling.number);
164 sprintf(call->to_uri, "sip:%s@%s", to_sip_user, dest->domain);
165 bcopy(&dest->sin, &call->udp_sin, sizeof(struct sockaddr_in));
166 call->next = call_list;
167 call_list = call;
168 send_call_proceeding(call);
169 call->overall_state = OVERALL_STATE_GSM_RTP;
170 call->mncc_state = MNCC_STATE_MO_PROC;
171 }