anjana_sreekumar@infosys.com | 991c206 | 2020-01-08 11:42:57 +0530 | [diff] [blame^] | 1 | /* |
| 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 | |
| 35 | extern struct GtpV2Stack* gtpStack_gp; |
| 36 | int s11_CS_resp_handler(MsgBuffer* message, GtpV2MessageHeader* hdr); |
| 37 | int s11_MB_resp_handler(MsgBuffer* message, GtpV2MessageHeader* hdr); |
| 38 | int s11_DS_resp_handler(MsgBuffer* message, GtpV2MessageHeader* hdr); |
| 39 | int s11_RB_resp_handler(MsgBuffer* message, GtpV2MessageHeader* hdr); |
| 40 | int s11_DDN_handler(MsgBuffer* message, GtpV2MessageHeader* hdr); |
| 41 | |
| 42 | /* |
| 43 | Get count of no of IEs in gtpv2c msg |
| 44 | */ |
| 45 | static int |
| 46 | get_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 | |
| 59 | void |
| 60 | network_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 | |
| 71 | int |
| 72 | parse_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 | |
| 111 | int |
| 112 | parse_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 | |
| 173 | void |
| 174 | handle_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 | } |