The encoder uses the OssBuf structure to store its output while the decoder reads its input from this structure.
The OssBuf structure has the following header-file definition:
typedef struct { long length; unsigned char *value; } OssBuf;
The value field is designed to reference a memory buffer of contiguous octets of encoded data. The length field stores the total count of octets occupied by the encoding referenced by value.
The OssNASGlobal structure is the global environment variable that is passed to almost all of the OSS NAS/C API functions.
You can manually set the following fields in this structure:
The OSS NAS/C API functions are located in various library files. Two types of libraries are provided: dynamic and static. The libraries described in this section are for the MS Windows and Linux platforms.
The OSS NAS/C API functions are located in a dynamic library file (ossNAS.dll for Windows and libossNAS.so for Linux) that is supplemented by one or more version-specific "plug-in" dynamic libraries. A version-specific library supports one specific version of 3GPP NAS. and is named according to that version number. For example, ossCEFEDXNAS5GS1680.dll on Windows and ossCEFEDXNAS5GS1680.so on Linux are named for 5G NAS version 16.8.0.
To use the OSS NAS dynamic libraries on Windows, specify the ossNAS.lib import library on your linker command-line. Your application program will automatically try to load the ossNAS.dll library as needed during runtime. On Linux, just link with the libossNAS.so shared library. The first time your application calls the ossNASinit function with a specific 3GPP NAS version number, the ossNAS.dll or libossNAS.so library will automatically search for and load the plug-in that supports that 3GPP NAS version.
For Windows, make sure the directory that contains the OSS NAS dynamic library file (ossNAS.dll) is included in the operating system's environment path. Otherwise, your application will be unable to load the library at runtime. All plug-ins must also be located in this directory.
For Linux, make sure the directory that contains the OSS NAS shared library files is included the LD_LIBRARY_PATH environment variable. Otherwise, your application will be unable to load the libraries at runtime.
For Windows, the ossNAS.dll and plug-in DLLs are in the bin directory of the product installation. The ossNAS.lib import library is in the lib directory of the product installation. For Linux, all libraries are in the lib directory of the product installation.
To use the NAS/C API functions, explicitly specify the appropriate static library on your linker command-line, as follows:
For Linux, link your NAS application code to a single libossNAS5GS1680.a static library, which is located in the lib directory of your product installation.
For Windows, link your NAS application code to a single ossNAS5GS1680.lib static library, which is located in the lib directory of your product installation.
The following sample C program illustrates how to use the OSS NAS Tools for C for 5G for 3GPP release 16.8.0 . Please pay attention to the memory management methods for using NAS/C APIs.
/* Header file containing C structures for the NAS specification */ #include "NAS5GS1680.h" /* OSS NAS/C API header file */ #include "ossNAS.h" static int CreateOutgoingUEMessage(OssNASGlobal *nasworld, struct Env *env); enum { bufferSize = 100000 }; static unsigned char encodedDataBuffer[bufferSize]; static unsigned char unencodedDataBuffer[bufferSize]; static unsigned char decodedDataBuffer[bufferSize]; static unsigned char outTextoutTextBuffer[bufferSize]; static int lenEncodedData; /* Helper macro that facilitates the construction of an unencoded message */ #define align_adr8(a) (unsigned char *)(((size_t)(a) + 7) & ~7) #define NEW(T) (freeAddrTemp = align_adr8(freeAddr), freeAddr =freeAddrTemp + sizeof(T), (T *)freeAddrTemp) /* Helper macro to set ossOctetString to the value of a string literal */ #define SET_OSTRING_BY_LITERAL(s, literal) {(s).value = (freeAddr = align_adr8(freeAddr));\ memcpy(freeAddr, literal, sizeof(literal)-1); freeAddr += sizeof(literal)-1;\ (s).length = sizeof(literal)-1;} struct Env { unsigned char *encodedDataBuffer; unsigned char *unencodedDataBuffer; unsigned char *decodedDataBuffer; unsigned char *outTextoutTextBuffer; int lenEncodedData; }; int main(int argc, char *argv[]) { OssNASGlobal w, *nasworld = &w; /* Stores the state of the OSS NAS API */ int exitcode; struct Env env; /* Make sure the buffer addresses passed to the API are properly aligned */ env.encodedDataBuffer = align_adr8 (encodedDataBuffer); env.unencodedDataBuffer = align_adr8 (unencodedDataBuffer); env.decodedDataBuffer = align_adr8 (decodedDataBuffer); env.outTextoutTextBuffer = align_adr8 (outTextoutTextBuffer); /* Initialize the OSS NAS API */ exitcode = ossNASinit(nasworld, "NAS5GS1680"); if (exitcode != 0) { ossNASPrint(NULL, "ossNASInit error: %d\n", exitcode); return 1; } ossNASSetFlags(nasworld, 0); exitcode = CreateOutgoingUEMessage(nasworld, &env); ossNASterm(nasworld); return exitcode; } static int CreateOutgoingUEMessage(OssNASGlobal *nasworld, struct Env *env) { OssBuf encodedData; OssBuf outData; int pdu_num = OSSNAS_PDUNUM; int retcode; NAS5GS1680_NASMessage *nasmessage; unsigned char *freeAddr, *freeAddrTemp; NAS5GS1680_RegistrationRequest *registrationRequest; /* Set the originator of NAS messages to "UE" */ ossNASSetOriginator(nasworld, OSSNAS_ORIG_UE); /* Set the encoding/decoding flags (no flags) */ ossNASSetFlags(nasworld, 0); freeAddr = env->unencodedDataBuffer; nasmessage = NEW(NAS5GS1680_NASMessage); /* Construct an unencoded NAS message */ /* This is a plain 5GSMM message of type NAS5GS1680_RegistrationRequest */ nasmessage = NEW(NAS5GS1680_NASMessage); nasmessage->choice = NAS5GS1680_nas5GMMMessage_chosen; nasmessage->u.nas5GMMMessage = NEW(NAS5GS1680_NAS5GMMMessage); nasmessage->u.nas5GMMMessage->choice = NAS5GS1680_plain_chosen; nasmessage->u.nas5GMMMessage->u.plain = NEW(NAS5GS1680_Plain5GSNASMessage); nasmessage->u.nas5GMMMessage->u.plain->extendedProtocolDiscriminator = 126; nasmessage->u.nas5GMMMessage->u.plain->securityHeaderType = NAS5GS1680_plain5GSNASMessage; nasmessage->u.nas5GMMMessage->u.plain->messageType = NAS5GS1680_NAS5GMMMessageType_registrationRequest; nasmessage->u.nas5GMMMessage->u.plain->messageBody.choice = NAS5GS1680_registrationRequest_chosen; nasmessage->u.nas5GMMMessage->u.plain->messageBody.u.registrationRequest = registrationRequest = NEW(NAS5GS1680_RegistrationRequest); registrationRequest->nas5GSRegistrationType.nas5GSRegistrationTypeValue = NAS5GS1680_initialRegistration; registrationRequest->nas5GSRegistrationType.NAS5GSRegistrationType_for = NAS5GS1680_followOnRequestPending; registrationRequest->ngKSI.tsc = NAS5GS1680_NASKeySetIdentifier_tsc_nativeSecurityContext; registrationRequest->ngKSI.nasKeySetIdentifier = 4; registrationRequest->nas5GSMobileIdentity.choice = NAS5GS1680_nas5GSTMSI_chosen; registrationRequest->nas5GSMobileIdentity.u.nas5GSTMSI = NEW(NAS5GS1680_MobileIdentity5GSTMSI); registrationRequest->nas5GSMobileIdentity.u.nas5GSTMSI->amfPointer = 2; registrationRequest->nas5GSMobileIdentity.u.nas5GSTMSI->dummy = 15; registrationRequest->nas5GSMobileIdentity.u.nas5GSTMSI->amfSetID = 0; registrationRequest->nas5GSMobileIdentity.u.nas5GSTMSI->oddEvenIndicator = 0; registrationRequest->nas5GSMobileIdentity.u.nas5GSTMSI->typeOfIdentity = 4; SET_OSTRING_BY_LITERAL(registrationRequest->nas5GSMobileIdentity.u.nas5GSTMSI->nas5GTMSI, "\x02\x04\x17\x25"); registrationRequest->bit_mask = NAS5GS1680_nas5GMMCapability_present | NAS5GS1680_RegistrationRequest_networkSlicingIndication_present; registrationRequest->nas5GMMCapability.spare = 0; registrationRequest->nas5GMMCapability.hoAttach = NAS5GS1680_supported; registrationRequest->nas5GMMCapability.lpp = NAS5GS1680_lppInN1ModeSupported; registrationRequest->nas5GMMCapability.s1Mode = NAS5GS1680_s1ModeSupported; registrationRequest->networkSlicingIndication.spare = 0; registrationRequest->networkSlicingIndication.dcni = NAS5GS1680_requestedNSSAICreated; registrationRequest->networkSlicingIndication.nssci = NAS5GS1680_networkSlicingSubscriptionNotChanged; ossNASPrint(NULL, "OK.\n"); /* Encode the message */ encodedData.value = env->encodedDataBuffer; encodedData.length = (long)(freeAddr - (unsigned char *)nasmessage); ossNASPrint(NULL, "Encoding..."); retcode = ossNASEncode(nasworld, pdu_num, nasmessage, &encodedData); if (retcode != 0) { ossNASPrint(nasworld, "ossNASEncode error: %s\n", ossNASGetErrMsg(nasworld)); return 2; } ossNASPrint(NULL, "OK.\n"); ossNASPrint(nasworld, "Encoding (%ld octets):\n", encodedData.length); printHex(nasworld, encodedData.value, encodedData.length); ossNASPrint(nasworld, "\n"); /* This is the length of the encoded message produced by the ossNASEncode function */ env->lenEncodedData = encodedData.length; /* Decode the encoded message produced by the ossNASEncode function */ encodedData.value = env->encodedDataBuffer; encodedData.length = env->lenEncodedData; nasmessage = (NAS5GS1680_NASMessage *)env->decodedDataBuffer; ossNASSetDecodingLength(nasworld, bufferSize); /* Size of the output buffer for the decoded message */ ossNASPrint(NULL, "Decoding back..."); retcode = ossNASDecode(nasworld, &pdu_num, &encodedData, (void **)&nasmessage); if (retcode != 0) { ossNASPrint(nasworld, "ossNASDecode error: %s\n", ossNASGetErrMsg(nasworld)); return 3; } ossNASPrint(NULL, "OK.\n"); ossNASPrint(NULL, "Comparing original and decoded messages..."); /* Compare the decoded message produced by the ossNASDecode function * with the unencoded message. They are expected to be equal */ retcode = ossNASCmpValue(nasworld, OSSNAS_PDUNUM, env->unencodedDataBuffer, env->decodedDataBuffer); /* Convert the encoded message to XML using the ossNASBinary2XML function */ encodedData.value = env->encodedDataBuffer; encodedData.length = env->lenEncodedData; outData.value = env->outTextBuffer; outData.length = bufferSize; ossNASPrint(NULL, "Converting encoded message to XML..."); retcode = ossNASBinary2XML(nasworld, OSSNAS_PDUNUM, (ossEncodingRules)0, &encodedData, &outData); if (retcode != 0) { ossNASPrint(nasworld, "ossNASBinary2XML error: %s\n", ossNASDescribeReturnCode(nasworld, retcode)); return 5; } ossNASPrint(NULL, "OK.\n"); /* Print the resulting XML text to the console */ env->outTextBuffer[outData.length] = 0; ossNASPrint(NULL, "Printing the resulting XML as string...\n"); ossNASPrint(nasworld, "%s\n\n", env->outTextBuffer); /* We convert the encoded message to JSON using the ossNASBinary2JSON function */ encodedData.value = encodedDataBuffer; encodedData.length = lenEncodedData; outData.value = outTextBuffer; outData.length = bufferSize; retcode = ossNASBinary2JSON(nasworld, pdu_num, OSSNAS_ENCRULE, &encodedData, &outData); if(retcode != 0) { ossNASPrint(nasworld, "ossNASBinary2JSON error: %s\n", ossNASDescribeReturnCode(nasworld, retcode)); return 5; } /* We print the resulting JSON text to the console */ outTextBuffer[outData.length] = 0; ossNASPrint(nasworld, "%s\n\n", outTextBuffer); /* Print the decoded message (as XML text) to the console */ /* The output is expected to match the output of the ossNASBinary2XML function */ nasmessage = (NAS5GS1680_NASMessage *)env->decodedDataBuffer; ossNASPrint(NULL, "Printing decoded message using ossNASPrintPDU()...\n"); retcode = ossNASPrintPDU(nasworld, OSSNAS_PDUNUM, nasmessage); return 0; }
This documentation applies to the OSS NAS Tools for C for 5G v8.3.1-8.3.5 for 3GPP Release 16.8.0 .
Copyright © 2024 OSS Nokalva, Inc. All rights reserved.
No part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form or by any means electronic, mechanical, photocopying, recording or otherwise, without the prior permission of OSS Nokalva, Inc.
Every distributed copy of the OSS NAS Tools for C for 5G is associated with a specific license and related unique license number. That license determines, among other things, what functions of the OSS NAS Tools for C for 5G are available to you.