blob: fbb0d7b8c56c2310050aec56c8d02f980948c59b [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 <arpa/inet.h>
22#include <unistd.h>
23#include <string.h>
24#include <pthread.h>
25
26#include "err_codes.h"
27#include "options.h"
28#include "ipc_api.h"
29#include "message_queues.h"
30#include "s11.h"
31#include "s11_config.h"
32#include "s11_structs.h"
33#include "../../gtpV2Codec/gtpV2StackWrappers.h"
34
35extern struct GtpV2Stack* gtpStack_gp;
36int s11_CS_resp_handler(MsgBuffer* message, GtpV2MessageHeader* hdr);
37int s11_MB_resp_handler(MsgBuffer* message, GtpV2MessageHeader* hdr);
38int s11_DS_resp_handler(MsgBuffer* message, GtpV2MessageHeader* hdr);
39int s11_RB_resp_handler(MsgBuffer* message, GtpV2MessageHeader* hdr);
40int s11_DDN_handler(MsgBuffer* message, GtpV2MessageHeader* hdr);
41
42/*
43 Get count of no of IEs in gtpv2c msg
44*/
45static int
46get_IE_cnt(char *msg, int len)
47{
48 int cnt = 0;
49 char *tmp = msg+11;
50 struct s11_IE_header *header = (struct s11_IE_header *)tmp;
51
52 for(; (char *)tmp <= msg + len; ++cnt) {
53 tmp += sizeof(struct s11_IE_header) + ntohs(header->ie_len);
54 header = (struct s11_IE_header*)tmp;
55 }
56 return cnt;
57}
58
59void
60network_cp_fteid(struct fteid *teid, char *data)
61{
62 unsigned int *tmp;
63
64 memcpy(teid, data, sizeof(struct fteid));
65 teid->header.teid_gre = ntohl(teid->header.teid_gre);
66 tmp = (unsigned int*)(data+5);
67 *tmp = ntohl(*tmp);
68 memcpy(&(teid->ip.ipv4), tmp, sizeof(struct in_addr));
69}
70
71int
72parse_bearer_ctx(struct bearer_ctx *bearer, char* data, short len)
73{
74 char no_of_ies = 4;
75 //TODO: count no of IEs
76
77 for(int i=0; i < no_of_ies; ++i) {
78 struct s11_IE_header *header = (struct s11_IE_header*)data;
79 char *value = data + sizeof(struct s11_IE_header);
80
81 switch(header->ie_type){
82 case S11_IE_CAUSE:
83 memcpy(&(bearer->cause), value, sizeof(struct gtp_cause));
84 break;
85
86 case S11_IE_FTEID_C:{
87 #define S1U_SGW_FTEID 1 /*binary 0001*/
88 if((0x0F & (unsigned char)(*value))
89 == S1U_SGW_FTEID) {
90 network_cp_fteid(&bearer->s1u_sgw_teid, value);
91 }
92 else { /*s5s8 pgw_U ftied*/
93 network_cp_fteid(&bearer->s5s8_pgw_u_teid, value);
94 }
95 break;
96 }
97
98 case S11_IE_EPS_BEARER_ID:
99 bearer->eps_bearer_id = (unsigned char)(*value);
100 break;
101
102 default:
103 log_msg(LOG_ERROR, "Unhandled S11 bearer IE: %d\n", header->ie_type);
104 }
105
106 data += ntohs(header->ie_len) + sizeof(struct s11_IE_header); /*goto next IE*/
107 }
108 return SUCCESS;
109}
110
111int
112parse_gtpv2c_IEs(char *msg, int len, struct s11_proto_IE *proto_ies)
113{
114 proto_ies->no_of_ies = get_IE_cnt(msg, len);
115
116 if(0 == proto_ies->no_of_ies) {
117 log_msg(LOG_INFO, "No IEs recvd in message\n");
118 return SUCCESS;
119 }
120 log_msg(LOG_INFO, "No of IEs - %d\n", proto_ies->no_of_ies);
121
122 /*allocated IEs for message*/
123 proto_ies->s11_ies = (struct s11_IE*)calloc(sizeof(struct s11_IE),
124 proto_ies->no_of_ies);
125 msg +=11;
126
127 for(int i=0; i < proto_ies->no_of_ies; ++i) {
128 struct s11_IE *ie = &(proto_ies->s11_ies[i]);
129 char *data = msg + sizeof(struct s11_IE_header);
130
131 memcpy(&(ie->header), msg, sizeof(struct s11_IE_header));
132
133 switch(ie->header.ie_type){
134 case S11_IE_CAUSE:
135 memcpy(&(ie->data.cause), data, sizeof(struct gtp_cause));
136 break;
137
138 case S11_IE_FTEID_C:{
139 #define S11_SGW_C_FTEID 11 /*binary 1011*/
140 if((0x0F & (unsigned char)(*data))
141 == S11_SGW_C_FTEID) {
142 network_cp_fteid(&(ie->data.s11_sgw_fteid), data);
143 }
144 else { /*s5s8 pgw_c ftied*/
145 network_cp_fteid(&(ie->data.s5s8_pgw_c_fteid), data);
146 }
147 break;
148 }
149
150 case S11_IE_PAA: {
151 memcpy(&(ie->data.pdn_addr.pdn_type), data,
152 sizeof(ie->data.pdn_addr.pdn_type));
153 memcpy(&(ie->data.pdn_addr.ip_type.ipv4), data+1, sizeof(int));
154 break;
155 }
156
157 case S11_IE_APN_RESTRICTION:
158 break;
159
160 case S11_IE_BEARER_CTX:
161 parse_bearer_ctx(&(ie->data.bearer), data, ntohs(ie->header.ie_len));
162 break;
163
164 default:
165 log_msg(LOG_ERROR, "Unhandled S11 IE: %d\n", ie->header.ie_type);
166 }
167
168 msg += (ntohs(((struct s11_IE_header*)msg)->ie_len) + sizeof(struct s11_IE_header)) ; /*goto next IE*/
169 }
170 return SUCCESS;
171}
172
173void
174handle_s11_message(void *message)
175{
176 log_msg(LOG_INFO, "S11 recv msg handler.\n");
177
178 MsgBuffer* msgBuf_p = (MsgBuffer*)(message);
179
180 GtpV2MessageHeader msgHeader;
181
182 bool rc = GtpV2Stack_decodeMessageHeader(gtpStack_gp, &msgHeader, msgBuf_p);
183
184 switch(msgHeader.msgType){
185 case S11_GTP_CREATE_SESSION_RESP:
186 s11_CS_resp_handler(msgBuf_p, &msgHeader);
187 break;
188
189 case S11_GTP_MODIFY_BEARER_RESP:
190 s11_MB_resp_handler(msgBuf_p, &msgHeader);
191 break;
192
193 case S11_GTP_DELETE_SESSION_RESP:
194 s11_DS_resp_handler(msgBuf_p, &msgHeader);
195 break;
196
197 case S11_GTP_RELEASE_BEARER_RESP:
198 s11_RB_resp_handler(msgBuf_p, &msgHeader);
199 break;
200
201 case S11_GTP_DDN:
202 s11_DDN_handler(msgBuf_p, &msgHeader);
203 break;
204
205 }
206 return;
207}