as_message.c 12.5 KB
Newer Older
gauthier's avatar
 
gauthier committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 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 84 85 86 87 88 89 90 91 92 93
/*******************************************************************************
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom

    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.


    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
   see <http://www.gnu.org/licenses/>.

  Contact Information
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr

  Address      : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.

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

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;
  Byte_t** data = NULL;

  /* Get the message type */
94 95
  msg->msgID = *(uint16_t*)(buffer);
  bytes = sizeof(uint16_t);
gauthier's avatar
 
gauthier committed
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 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 174 175 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 210 211 212 213 214 215 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 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 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 362 363 364 365 366 367 368 369 370 371 372 373 374

  switch (msg->msgID) {
  case AS_NAS_ESTABLISH_REQ:
    /* NAS signalling connection establish request */
    bytes += sizeof(nas_establish_req_t) - sizeof(Byte_t*);
    data = &msg->msg.nas_establish_req.initialNasMsg.data;
    break;

  case AS_NAS_ESTABLISH_IND:
    /* NAS signalling connection establishment indication */
    bytes += sizeof(nas_establish_ind_t) - sizeof(Byte_t*);
    data = &msg->msg.nas_establish_ind.initialNasMsg.data;
    break;

  case AS_NAS_ESTABLISH_RSP:
    /* NAS signalling connection establishment response */
    bytes += sizeof(nas_establish_rsp_t) - sizeof(Byte_t*);
    data = &msg->msg.nas_establish_rsp.nasMsg.data;
    break;

  case AS_NAS_ESTABLISH_CNF:
    /* NAS signalling connection establishment confirm */
    bytes += sizeof(nas_establish_cnf_t) - sizeof(Byte_t*);
    data = &msg->msg.nas_establish_cnf.nasMsg.data;
    break;

  case AS_UL_INFO_TRANSFER_REQ:
    /* Uplink L3 data transfer request */
    bytes += sizeof(ul_info_transfer_req_t) - sizeof(Byte_t*);
    data = &msg->msg.ul_info_transfer_req.nasMsg.data;
    break;

  case AS_UL_INFO_TRANSFER_IND:
    /* Uplink L3 data transfer indication */
    bytes += sizeof(ul_info_transfer_ind_t) - sizeof(Byte_t*);
    data = &msg->msg.ul_info_transfer_ind.nasMsg.data;
    break;

  case AS_DL_INFO_TRANSFER_REQ:
    /* Downlink L3 data transfer request */
    bytes += sizeof(dl_info_transfer_req_t) - sizeof(Byte_t*);
    data = &msg->msg.dl_info_transfer_req.nasMsg.data;
    break;

  case AS_DL_INFO_TRANSFER_IND:
    /* Downlink L3 data transfer indication */
    bytes += sizeof(dl_info_transfer_ind_t) - sizeof(Byte_t*);
    data = &msg->msg.dl_info_transfer_ind.nasMsg.data;
    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 */
      *data = (Byte_t*)(buffer + bytes);
    }

    /* 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);
  as_nas_info_t* nas_msg = NULL;

  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*);
    nas_msg = &msg->msg.nas_establish_req.initialNasMsg;
    break;

  case AS_NAS_ESTABLISH_IND:
    /* NAS signalling connection establish indication */
    bytes += sizeof(nas_establish_ind_t) - sizeof(Byte_t*);
    nas_msg = &msg->msg.nas_establish_ind.initialNasMsg;
    break;

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

  case AS_NAS_ESTABLISH_CNF:
    /* NAS signalling connection establish confirm */
    bytes += sizeof(nas_establish_cnf_t) - sizeof(Byte_t*);
    nas_msg = &msg->msg.nas_establish_cnf.nasMsg;
    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*);
    nas_msg = &msg->msg.ul_info_transfer_req.nasMsg;
    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*);
    nas_msg = &msg->msg.ul_info_transfer_ind.nasMsg;
    break;

  case AS_DL_INFO_TRANSFER_REQ:
    /* Downlink L3 data transfer */
    bytes += sizeof(dl_info_transfer_req_t) - sizeof(Byte_t*);
    nas_msg = &msg->msg.dl_info_transfer_req.nasMsg;
    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*);
    nas_msg = &msg->msg.dl_info_transfer_ind.nasMsg;
    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);

    if ( nas_msg && (nas_msg->length > 0) ) {
      /* Copy the NAS message */
      memcpy(buffer + bytes, nas_msg->data, nas_msg->length);
      bytes += nas_msg->length;
      /* Release NAS message memory */
      free(nas_msg->data);
      nas_msg->length = 0;
      nas_msg->data = NULL;
    }

    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  *********************/
/****************************************************************************/