blob: 8bc361b965aae348cf7e386eb27799ec55210b07 [file] [log] [blame]
anjana_sreekumar@infosys.com991c2062020-01-08 11:42:57 +05301/*
2 * Copyright (c) 2003-2018, Great Software Laboratory Pvt. Ltd.
3 * Copyright (c) 2017 Intel Corporation
4 * Copyright (c) 2019, Infosys Ltd.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <pthread.h>
22#include <string.h>
23#include <unistd.h>
24#include <stdbool.h>
25#include <freeDiameter/freeDiameter-host.h>
26#include <freeDiameter/libfdcore.h>
27#include <freeDiameter/libfdproto.h>
28
29#include "s6a_config.h"
30#include "err_codes.h"
31#include "message_queues.h"
32#include "ipc_api.h"
33#include "sec.h"
34#include "msgType.h"
35//#include "stage1_s6a_msg.h"
36#include "s6a_fd.h"
37#include "s6a.h"
38#include "s6a_config.h"
39#include "hss_message.h"
40
41/************************************************************************
42Current file : Stage - AIR handler of S6A
43ATTACH stages :
44@@@ Stage 1 : IAM-->[stage1 handler]-->AIR, ULR
45 Stage 2 : AIA, ULA -->[stage2 handler]--> Auth req
46 Stage 3 : Auth resp-->[stage1 handler]-->Sec mode cmd
47 Stage 4 : sec mode resp-->[stage1 handler]-->esm infor req
48 Stage 5 : esm infor resp-->[stage1 handler]-->create session
49 Stage 6 : create session resp-->[stage1 handler]-->init ctx setup
50 Stage 7 : attach complete-->[stage1 handler]-->modify bearer
51**************************************************************************/
52
53/****Globals and externs ***/
54extern int g_our_hss_fd;
55extern s6a_config g_s6a_cfg;
56extern struct fd_dict_objects g_fd_dict_objs;
57extern struct fd_dict_data g_fd_dict_data;
58/****Global and externs end***/
59
60
61void ulr_intermediate_cb(void * data, struct msg ** msg)
62{
63 dump_fd_msg(*msg);
64}
65
66/**
67 * @brief Prepare ULR freediameter message, dump and post to HSS
68 * @param[in] aia_msg - AIA info recvd from mme-app
69 * @param[in] imsi - IMSI
70 * @return int Sucess or failure code
71 */
72static int
73send_FD_ULR(struct s6a_Q_msg *aia_msg, char imsi[])
74{
75 struct msg *fd_msg = NULL;
76 int res = SUCCESS;
77 struct s6a_sess_info s6a_sess = {.sess_id="", .sess_id_len = 0};
78 char event = 12;
79 union avp_value val;
80
81 /*Create FD header and message for update location request.*/
82 if(SUCCESS != (res = create_fd_sess_id(&s6a_sess, aia_msg->ue_idx)))
83 return res;
84
85 CHECK_FCT_DO(fd_msg_new(g_fd_dict_objs.ULR, MSGFL_ALLOC_ETEID, &fd_msg),
86 return S6A_FD_ERROR)
87
88 /*AVP: Session-Id*/
89 val.os.data = (unsigned char*)s6a_sess.sess_id;
90 val.os.len = strlen(s6a_sess.sess_id);
91 add_fd_msg(&val, g_fd_dict_objs.sess_id, &fd_msg);
92
93 /*AVP: Auth-Session-State*/
94 val.i32 = 1; /*NO_STATE_MAINTAINED*/
95 val.os.len = 0;
96 add_fd_msg(&val, g_fd_dict_objs.auth_sess_state, &fd_msg);
97
98 /*AVP: Origin-Host/Realm*/
99 CHECK_FCT_DO(fd_msg_add_origin(fd_msg, 0), return S6A_FD_ERROR);
100
101 /*AVP: Destination-Host*/
102 val.os.data = (unsigned char*)g_s6a_cfg.hss_host_name;
103 val.os.len = strlen(g_s6a_cfg.hss_host_name);
104 add_fd_msg(&val, g_fd_dict_objs.dest_host, &fd_msg);
105
106 /*AVP: Destination-Realm*/
107 val.os.data = (unsigned char*)g_s6a_cfg.realm;
108 val.os.len = strlen(g_s6a_cfg.realm);
109 add_fd_msg(&val, g_fd_dict_objs.dest_realm, &fd_msg);
110
111 /*AVP: User-Name*/
112 val.os.data = (unsigned char*)imsi;
113 val.os.len = strlen(imsi);
114 add_fd_msg(&val, g_fd_dict_objs.user_name, &fd_msg);
115
116 /*AVP: RAT-Type*/
117 val.u32 = S6A_RAT_EUTRAN;
118 val.os.len = 0;
119 add_fd_msg(&val, g_fd_dict_objs.RAT_type, &fd_msg);
120
121 /*AVP: ULR-Flags*/
122 val.u32 = ULR_FLAG_S6AS6D_IND | ULR_FLAG_INIT_ATCH_IND ;
123 add_fd_msg(&val, g_fd_dict_objs.ULR_flags, &fd_msg);
124
125 /*AVP: Visited-PLMN-Id*/
126 val.os.data = (unsigned char*)aia_msg->tai.plmn_id.idx;
127 val.os.len = 3;
128 add_fd_msg(&val, g_fd_dict_objs.visited_PLMN_id, &fd_msg);
129
130 dump_fd_msg(fd_msg);
131
132 /*Post ULR to HSS*/
133 CHECK_FCT_DO(fd_msg_send(&fd_msg, ulr_intermediate_cb, (void*)&event),
134 return S6A_FD_ERROR);
135
136 return SUCCESS;
137}
138
139
140/**
141 * @brief dump recvd aia queue msg
142 * @param[in] air_msg - IMSI
143 * @return void
144 */
145void
146dump_s6a_msg(struct s6a_Q_msg *air_msg)
147{
148 log_msg(LOG_INFO, "Received index= %d\n",air_msg->ue_idx);
149 log_msg(LOG_INFO, "Received plmn %x %x %x= %d\n",air_msg->tai.plmn_id.idx[0],
150 air_msg->tai.plmn_id.idx[1], air_msg->tai.plmn_id.idx[2]);
151}
152
153/**
154 * @brief Prepare AIR freediameter message, dump and post to HSS
155 * @param[in] aia_msg - AIA info recvd from mme-app
156 * @param[in] imsi - IMSI
157 * @return int Sucess or failure code
158 */
159static int
160send_FD_AIR(struct s6a_Q_msg *aia_msg, char imsi[])
161{
162 struct avp *avp_ptr = NULL;
163 struct msg *fd_msg = NULL;
164 int res = 0;
165 struct s6a_sess_info s6a_sess = {.sess_id="", .sess_id_len = 0};
166 union avp_value val;
167
168 log_msg(LOG_INFO, "In Send AIR:\n");
169 dump_s6a_msg(aia_msg);
170
171 /*Create FD header and message for authentication info request.*/
172 if(SUCCESS != (res = create_fd_sess_id(&s6a_sess, aia_msg->ue_idx)))
173 return res;
174
175 CHECK_FCT_DO(fd_msg_new(g_fd_dict_objs.AIR, MSGFL_ALLOC_ETEID, &fd_msg),
176 return S6A_FD_ERROR);
177
178 /*AVP: Session-Id*/
179 val.os.data = (unsigned char*)s6a_sess.sess_id;
180 val.os.len = strlen(s6a_sess.sess_id);
181 add_fd_msg(&val, g_fd_dict_objs.sess_id, &fd_msg);
182
183 /*AVP: Auth-Session-State*/
184 val.i32 = 1; /*NO_STATE_MAINTAINED*/
185 val.os.len = 0;
186 add_fd_msg(&val, g_fd_dict_objs.auth_sess_state, &fd_msg);
187
188 /*AVP: Origin-Host/Realm*/
189 CHECK_FCT_DO(fd_msg_add_origin(fd_msg, 0), return S6A_FD_ERROR)
190
191 /*AVP: Destination-Host*/
192 val.os.data = (unsigned char*)g_s6a_cfg.hss_host_name;
193 val.os.len = strlen(g_s6a_cfg.hss_host_name);
194 add_fd_msg(&val, g_fd_dict_objs.dest_host, &fd_msg);
195
196 /*AVP: Destination-Realm*/
197 val.os.data = (unsigned char*)g_s6a_cfg.realm;
198 val.os.len = strlen(g_s6a_cfg.realm);
199 add_fd_msg(&val, g_fd_dict_objs.dest_realm, &fd_msg);
200
201 /*AVP: User-Name*/
202 val.os.data = (unsigned char*)imsi;
203 val.os.len = strlen(imsi);
204 add_fd_msg(&val, g_fd_dict_objs.user_name, &fd_msg);
205
206 /*AVP: Visited-PLMN-Id*/
207 val.os.data = (unsigned char*)aia_msg->tai.plmn_id.idx;
208 val.os.len = 3;
209 add_fd_msg(&val, g_fd_dict_objs.visited_PLMN_id, &fd_msg);
210
211 /*TODO: recheck. Can it be grouped better way*/
212 /*AVP: Requested-EUTRAN-Authentication-Info*/
213 CHECK_FCT_DO(fd_msg_avp_new(
214 g_fd_dict_objs.req_EUTRAN_auth_info, 0, &avp_ptr),
215 return -1);
216 CHECK_FCT_DO(fd_msg_avp_add(fd_msg, MSG_BRW_LAST_CHILD, avp_ptr), return -1);
217
218 /*AVP: Requested-EUTRAN-Authentication-Info
219 *----->AVP: Number-Of-Requested-Vectors(1410)*/
220 val.i32 = 1;
221 val.os.len = 0;
222 add_fd_msg(&val, g_fd_dict_objs.no_of_req_vectors,
223 (struct msg**)&avp_ptr);
224
225 /*AVP: Requested-EUTRAN-Authentication-Info
226 * ------>AVP: Immediate-Response-Preferred*/
227 val.u32 = 0;
228 add_fd_msg(&val, g_fd_dict_objs.immediate_resp_pref,
229 (struct msg**)&avp_ptr);
230
231 dump_fd_msg(fd_msg);
232
233 /*post AIR to hss */
234 CHECK_FCT_DO(fd_msg_send(&fd_msg, NULL, NULL), return S6A_FD_ERROR);
235
236 return SUCCESS;
237}
238
239/**
240API to send AIR oto customer HSS over custome RPC
241*/
242static void
243send_rpc_AIR(struct s6a_Q_msg *air_msg, char imsi[])
244{
245 struct hss_req_msg msg;
246
247 msg.hdr = HSS_AIR_MSG;
248 msg.ue_idx = air_msg->ue_idx;
249
250 strncpy(msg.data.air.imsi, imsi, IMSI_STR_LEN);
251 memcpy(msg.data.air.plmn_id, air_msg->tai.plmn_id.idx, 3);
252
253 if (write(g_our_hss_fd, &msg, HSS_REQ_MSG_SIZE) < 0) {
254 log_msg(LOG_ERROR, "HSS AIR msg send failed.\n");
255 perror("writing on stream socket");
256 }
257 log_msg(LOG_INFO, "AIR msg send to hss for ue_idx %d\n",
258 air_msg->ue_idx);
259}
260
261/**
262API to send ULR oto customer HSS over custome RPC
263*/
264static void
265send_rpc_ULR(struct s6a_Q_msg *ulr_msg, char imsi[])
266{
267 struct hss_req_msg msg;
268
269 msg.hdr = HSS_ULR_MSG;
270 msg.ue_idx = ulr_msg->ue_idx;
271
272 strncpy(msg.data.air.imsi, imsi, IMSI_STR_LEN);
273 memcpy(msg.data.air.plmn_id, ulr_msg->tai.plmn_id.idx, 3);
274
275 if (write(g_our_hss_fd, &msg, HSS_REQ_MSG_SIZE) < 0) {
276 log_msg(LOG_ERROR, "HSS ULR msg send failed.\n");
277 perror("writing on stream socket");
278 }
279 log_msg(LOG_INFO, "ULR msg send to hss\n");
280}
281
282
283/**
284 * @brief convert binary imsi to string imsi
285 * Binary imsi is stored in 8 bytes, each nibble representing each imsi char.
286 * char imsi stroes each char in 1 byte.
287 * @param[in] b_imsi : Binary imsi
288 * @param[out] s_imsi : Converted string imsi
289 * @return void
290 */
291void
292imsi_bin_to_str(unsigned char *b_imsi, char *s_imsi)
293{
294 if(NULL == b_imsi || NULL == s_imsi) return;
295
296 memset(s_imsi, 0, STR_IMSI_LEN);
297
298 /* Byte 'AB' in b_imsi, is converted to two bytes 'A', 'B' in s_imsi*/
299 s_imsi[0] = '0' + ((b_imsi[0]>>4) & 0x0F);
300
301 for(int i=1; i < BINARY_IMSI_LEN; ++i) {
302 s_imsi[(i*2)-1] = '0' + (b_imsi[i] & 0x0F);
303 s_imsi[(i*2)] = '0' + ((b_imsi[i]>>4) & 0x0F);
304 }
305 s_imsi[(BINARY_IMSI_LEN*2)-1] = '\0';
306}
307
308/**
309 * @brief Post AIR and ULR messsages simultaneously to HSS.
310 * @return int Sucess or failure code
311 */
312static int
313AIR_processing(struct s6a_Q_msg * air_msg)
314{
315 log_msg(LOG_INFO, "IMSI recvd - %s\n %d \n", air_msg->imsi, air_msg->msg_type);
316
317 if(HSS_FD == g_s6a_cfg.hss_type) {
318 if(air_msg->msg_type == auth_info_request)
319 /*post to next processing*/
320 send_FD_AIR(air_msg, air_msg->imsi);
321 else if(air_msg->msg_type == update_loc_request)
322 send_FD_ULR(air_msg, air_msg->imsi);
323
324 } else {
325 log_msg(LOG_INFO, "Sending over IPC\n");
326 send_rpc_AIR(air_msg, air_msg->imsi);
327 send_rpc_ULR(air_msg, air_msg->imsi);
328 }
329
330 return SUCCESS;
331}
332
333/*
334* Thread function for stage.
335*/
336void*
337S6Req_handler(void *data)
338{
339 log_msg(LOG_INFO, "AIR Q handler ready.\n");
340
341 char *msg = ((char *) data) + ((sizeof(uint32_t)) * 2);
342
343 AIR_processing((struct s6a_Q_msg *)msg);
344
345 return NULL;
346}