as_message.c 13 KB
Newer Older
1 2 3 4 5
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

gauthier's avatar
 
gauthier committed
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
/*****************************************************************************

Source    as_message.c

Version   0.1

Date    2012/11/06

Product   NAS stack

Subsystem Application Programming Interface

Author    Frederic Maurel

Description Defines the messages supported by the Access Stratum sublayer
    protocol (usually RRC and S1AP for E-UTRAN) and functions used
    to encode and decode

*****************************************************************************/

#include "as_message.h"
#include "commonDef.h"
#include "nas_log.h"

#include <string.h> // memcpy
#include <stdlib.h> // free

/****************************************************************************/
/****************  E X T E R N A L    D E F I N I T I O N S  ****************/
/****************************************************************************/

/****************************************************************************/
/*******************  L O C A L    D E F I N I T I O N S  *******************/
/****************************************************************************/

/****************************************************************************/
/******************  E X P O R T E D    F U N C T I O N S  ******************/
/****************************************************************************/

/****************************************************************************
 **                                                                        **
 ** Name:  as_message_decode()                                       **
 **                                                                        **
 ** Description: Decode AS message and accordingly fills data structure    **
 **                                                                        **
 ** Inputs:  buffer:  Pointer to the buffer containing the       **
 **       message                                    **
 **      length:  Number of bytes that should be decoded     **
 **    Others:  None                                       **
 **                                                                        **
 ** Outputs:   msg:   AS message structure to be filled          **
 **      Return:  The AS message identifier when the buffer  **
 **       has been successfully decoded;             **
 **       RETURNerror otherwise.                     **
 **    Others:  None                                       **
 **                                                                        **
 ***************************************************************************/
int as_message_decode(const char* buffer, as_message_t* msg, int length)
{
  LOG_FUNC_IN;

  int bytes;
84 85 86 87 88 89
  /* pointers to msg fields possibly not aligned because msg  points to a packed structure
 * Using these possibly unaligned pointers in a function call may trigger alignment errors at run time and
 * gcc, from v9,  now warns about it. fix these warnings by removing the indirection on data
 * (in fact i don't understand this code data seems to be useless...)
 */
  Byte_t *data = NULL;
gauthier's avatar
 
gauthier committed
90 91

  /* Get the message type */
92 93
  msg->msgID = *(uint16_t*)(buffer);
  bytes = sizeof(uint16_t);
gauthier's avatar
 
gauthier committed
94 95 96 97 98

  switch (msg->msgID) {
  case AS_NAS_ESTABLISH_REQ:
    /* NAS signalling connection establish request */
    bytes += sizeof(nas_establish_req_t) - sizeof(Byte_t*);
99
    data = msg->msg.nas_establish_req.initialNasMsg.data;
gauthier's avatar
 
gauthier committed
100 101 102 103 104
    break;

  case AS_NAS_ESTABLISH_IND:
    /* NAS signalling connection establishment indication */
    bytes += sizeof(nas_establish_ind_t) - sizeof(Byte_t*);
105
    data = msg->msg.nas_establish_ind.initialNasMsg.data;
gauthier's avatar
 
gauthier committed
106 107 108 109 110
    break;

  case AS_NAS_ESTABLISH_RSP:
    /* NAS signalling connection establishment response */
    bytes += sizeof(nas_establish_rsp_t) - sizeof(Byte_t*);
111
    data = msg->msg.nas_establish_rsp.nasMsg.data;
gauthier's avatar
 
gauthier committed
112 113 114 115 116
    break;

  case AS_NAS_ESTABLISH_CNF:
    /* NAS signalling connection establishment confirm */
    bytes += sizeof(nas_establish_cnf_t) - sizeof(Byte_t*);
117
    data = msg->msg.nas_establish_cnf.nasMsg.data;
gauthier's avatar
 
gauthier committed
118 119 120 121 122
    break;

  case AS_UL_INFO_TRANSFER_REQ:
    /* Uplink L3 data transfer request */
    bytes += sizeof(ul_info_transfer_req_t) - sizeof(Byte_t*);
123
    data = msg->msg.ul_info_transfer_req.nasMsg.data;
gauthier's avatar
 
gauthier committed
124 125 126 127 128
    break;

  case AS_UL_INFO_TRANSFER_IND:
    /* Uplink L3 data transfer indication */
    bytes += sizeof(ul_info_transfer_ind_t) - sizeof(Byte_t*);
129
    data = msg->msg.ul_info_transfer_ind.nasMsg.data;
gauthier's avatar
 
gauthier committed
130 131 132 133 134
    break;

  case AS_DL_INFO_TRANSFER_REQ:
    /* Downlink L3 data transfer request */
    bytes += sizeof(dl_info_transfer_req_t) - sizeof(Byte_t*);
135
    data = msg->msg.dl_info_transfer_req.nasMsg.data;
gauthier's avatar
 
gauthier committed
136 137 138 139 140
    break;

  case AS_DL_INFO_TRANSFER_IND:
    /* Downlink L3 data transfer indication */
    bytes += sizeof(dl_info_transfer_ind_t) - sizeof(Byte_t*);
141
    data = msg->msg.dl_info_transfer_ind.nasMsg.data;
gauthier's avatar
 
gauthier committed
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
    break;

  case AS_BROADCAST_INFO_IND:
  case AS_CELL_INFO_REQ:
  case AS_CELL_INFO_CNF:
  case AS_CELL_INFO_IND:
  case AS_PAGING_REQ:
  case AS_PAGING_IND:
  case AS_NAS_RELEASE_REQ:
  case AS_UL_INFO_TRANSFER_CNF:
  case AS_DL_INFO_TRANSFER_CNF:
  case AS_NAS_RELEASE_IND:
  case AS_RAB_ESTABLISH_REQ:
  case AS_RAB_ESTABLISH_IND:
  case AS_RAB_ESTABLISH_RSP:
  case AS_RAB_ESTABLISH_CNF:
  case AS_RAB_RELEASE_REQ:
  case AS_RAB_RELEASE_IND:
    /* Messages without dedicated NAS information */
    bytes = length;
    break;

  default:
    bytes = 0;
    LOG_TRACE(WARNING, "NET-API   - AS message 0x%x is not valid",
              msg->msgID);
    break;
  }

  if (bytes > 0) {
    if (data) {
      /* Set the pointer to dedicated NAS information */
174 175
      /* wasn't data already computed above for specific cases here we override ?? */
      data = (Byte_t *)buffer + bytes;
gauthier's avatar
 
gauthier committed
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
    }

    /* Decode the message */
    memcpy(msg, (as_message_t*)buffer, bytes);
    LOG_FUNC_RETURN (msg->msgID);
  }

  LOG_TRACE(WARNING, "NET-API   - Failed to decode AS message 0x%x",
            msg->msgID);
  LOG_FUNC_RETURN (RETURNerror);
}

/****************************************************************************
 **                                                                        **
 ** Name:  as_message_encode()                                       **
 **                                                                        **
 ** Description: Encode AS message                                         **
 **                                                                        **
 ** Inputs:  msg:   AS message structure to encode             **
 **      length:  Maximal capacity of the output buffer      **
 **    Others:  None                                       **
 **                                                                        **
 ** Outputs:   buffer:  Pointer to the encoded data buffer         **
 **      Return:  The number of characters in the buffer     **
 **       when data have been successfully encoded;  **
 **       RETURNerror otherwise.                     **
 **    Others:  None                                       **
 **                                                                        **
 ***************************************************************************/
int as_message_encode(char* buffer, as_message_t* msg, int length)
{
  LOG_FUNC_IN;

  int bytes = sizeof(msg->msgID);
210 211 212
  as_nas_info_t nas_msg;
  Byte_t *dataptr=NULL;
  uint32_t len=0;
213 214 215

  memset(&nas_msg, 0, sizeof(as_nas_info_t));

gauthier's avatar
 
gauthier committed
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
  switch (msg->msgID) {
  case AS_BROADCAST_INFO_IND:
    /* Broadcast information */
    bytes += sizeof(broadcast_info_ind_t);
    break;

  case AS_CELL_INFO_REQ:
    /* Cell information request */
    bytes += sizeof(cell_info_req_t);
    break;

  case AS_CELL_INFO_CNF:
    /* Cell information response */
    bytes += sizeof(cell_info_cnf_t);
    break;

  case AS_CELL_INFO_IND:
    /* Cell information indication */
    bytes += sizeof(cell_info_ind_t);
    break;

  case AS_PAGING_REQ:
    /* Paging information request */
    bytes += sizeof(paging_req_t);
    break;

  case AS_PAGING_IND:
    /* Paging information indication */
    bytes += sizeof(paging_ind_t);
    break;

  case AS_NAS_ESTABLISH_REQ:
    /* NAS signalling connection establish request */
    bytes += sizeof(nas_establish_req_t) - sizeof(Byte_t*);
250
    nas_msg = msg->msg.nas_establish_req.initialNasMsg;
gauthier's avatar
 
gauthier committed
251 252 253 254 255
    break;

  case AS_NAS_ESTABLISH_IND:
    /* NAS signalling connection establish indication */
    bytes += sizeof(nas_establish_ind_t) - sizeof(Byte_t*);
256 257 258
    nas_msg = msg->msg.nas_establish_ind.initialNasMsg;
    dataptr=(Byte_t *)&(msg->msg.nas_establish_ind.initialNasMsg.data);
    len=msg->msg.nas_establish_ind.initialNasMsg.length;
gauthier's avatar
 
gauthier committed
259 260 261 262 263
    break;

  case AS_NAS_ESTABLISH_RSP:
    /* NAS signalling connection establish response */
    bytes += sizeof(nas_establish_rsp_t) - sizeof(Byte_t*);
264 265
    nas_msg = msg->msg.nas_establish_rsp.nasMsg;

gauthier's avatar
 
gauthier committed
266 267 268 269 270
    break;

  case AS_NAS_ESTABLISH_CNF:
    /* NAS signalling connection establish confirm */
    bytes += sizeof(nas_establish_cnf_t) - sizeof(Byte_t*);
271 272 273
    nas_msg = msg->msg.nas_establish_cnf.nasMsg;
    dataptr=(Byte_t *)&(msg->msg.nas_establish_cnf.nasMsg.data);
    len=msg->msg.nas_establish_ind.initialNasMsg.length;
gauthier's avatar
 
gauthier committed
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
    break;

  case AS_NAS_RELEASE_REQ:
    /* NAS signalling connection release request */
    bytes += sizeof(nas_release_req_t);
    break;

  case AS_NAS_RELEASE_IND:
    /* NAS signalling connection release indication */
    bytes += sizeof(nas_release_ind_t);
    break;

  case AS_UL_INFO_TRANSFER_REQ:
    /* Uplink L3 data transfer request */
    bytes += sizeof(ul_info_transfer_req_t) - sizeof(Byte_t*);
289
    nas_msg = msg->msg.ul_info_transfer_req.nasMsg;
gauthier's avatar
 
gauthier committed
290 291 292 293 294 295 296 297 298 299
    break;

  case AS_UL_INFO_TRANSFER_CNF:
    /* Uplink L3 data transfer confirm */
    bytes += sizeof(ul_info_transfer_cnf_t);
    break;

  case AS_UL_INFO_TRANSFER_IND:
    /* Uplink L3 data transfer indication */
    bytes += sizeof(ul_info_transfer_ind_t) - sizeof(Byte_t*);
300
    nas_msg = msg->msg.ul_info_transfer_ind.nasMsg;
gauthier's avatar
 
gauthier committed
301 302 303 304 305
    break;

  case AS_DL_INFO_TRANSFER_REQ:
    /* Downlink L3 data transfer */
    bytes += sizeof(dl_info_transfer_req_t) - sizeof(Byte_t*);
306
    nas_msg = msg->msg.dl_info_transfer_req.nasMsg;
gauthier's avatar
 
gauthier committed
307 308 309 310 311 312 313 314 315 316
    break;

  case AS_DL_INFO_TRANSFER_CNF:
    /* Downlink L3 data transfer confirm */
    bytes += sizeof(dl_info_transfer_cnf_t);
    break;

  case AS_DL_INFO_TRANSFER_IND:
    /* Downlink L3 data transfer indication */
    bytes += sizeof(dl_info_transfer_ind_t) - sizeof(Byte_t*);
317 318
    nas_msg = msg->msg.dl_info_transfer_ind.nasMsg;
 
gauthier's avatar
 
gauthier committed
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
    break;

  case AS_RAB_ESTABLISH_REQ:
    /* Radio Access Bearer establishment request */
    bytes += sizeof(rab_establish_req_t);
    break;

  case AS_RAB_ESTABLISH_IND:
    /* Radio Access Bearer establishment indication */
    bytes += sizeof(rab_establish_ind_t);
    break;

  case AS_RAB_ESTABLISH_RSP:
    /* Radio Access Bearer establishment response */
    bytes += sizeof(rab_establish_rsp_t);
    break;

  case AS_RAB_ESTABLISH_CNF:
    /* Radio Access Bearer establishment confirm */
    bytes += sizeof(rab_establish_cnf_t);
    break;

  case AS_RAB_RELEASE_REQ:
    /* Radio Access Bearer release request */
    bytes += sizeof(rab_release_req_t);
    break;

  case AS_RAB_RELEASE_IND:
    /* Radio Access Bearer release indication */
    bytes += sizeof(rab_release_ind_t);
    break;

  default:
    LOG_TRACE(WARNING, "NET-API   - AS message 0x%x is not valid",
              msg->msgID);
    bytes = length;
    break;
  }

  if (length > bytes) {
    /* Encode the AS message */
    memcpy(buffer, (unsigned char*)msg, bytes);

362
    if ( (dataptr!=NULL) && (len > 0) ) {
gauthier's avatar
 
gauthier committed
363
      /* Copy the NAS message */
364 365
      memcpy(buffer + bytes, nas_msg.data, nas_msg.length);
      bytes += len;
gauthier's avatar
 
gauthier committed
366
      /* Release NAS message memory */
367 368 369
      free(nas_msg.data);
      len=0;
      dataptr = NULL;
gauthier's avatar
 
gauthier committed
370 371 372 373 374 375 376 377 378 379 380 381 382 383
    }

    LOG_FUNC_RETURN (bytes);
  }

  LOG_TRACE(WARNING, "NET-API   - Failed to encode AS message 0x%x",
            msg->msgID);
  LOG_FUNC_RETURN (RETURNerror);
}

/****************************************************************************/
/*********************  L O C A L    F U N C T I O N S  *********************/
/****************************************************************************/