TOP

NAS/C API Advanced Topics

Applies to: NAS/C LTE/EPC r15.5.0 v7.1.2

OSS NAS/C API Internal Variables and Data Structures

OssBuf

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.

OssNASGlobal

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:

mallocp
All memory allocation performed by the OSS NAS/C API functions described above are done via a call to (*mallocp)(). By default, mallocp points to the malloc() function. You can set it to point to your own low-level memory allocator so long as its function prototype is identical to that of malloc().
freep
All memory freeing performed by the OSS NAS/C API functions described above are done via a call to (*freep)(). By default, freep points to the free() function. You can set it to point to your own low-level memory deallocator so long as its function prototype is identical to that of free().
reallocp
All memory reallocation performed by the OSS NAS/C API functions described above are done via a call to (*realloc)(). By default, reallocp points to the function realloc(). You can set it to point to your own low-level memory reallocator so long as its function prototype is identical to that of realloc().
asn1chop
This field is not used by the present version of the OSS NAS API.
ossblock
This field is not used by the present version of the OSS NAS API.
ossprefx
This field is not used by the present version of the OSS NAS API.
asn1out
This pointer is passed to the (*asn1prnt)() function as the first parameter to determine the output stream to which trace and other requested data is to be written. By default, asn1out is set to stdout. You can change it to reference an output file or another type of output stream.
asn1prnt
Is called by the ossNASPrint() and ossNASPrintPDU() functions. By default, asn1prnt points to fprintf(). You can set it to point to your own print function, as long as it has the same interface as fprintf(). You should set asn1out whenever you set asn1prnt. Failing to do so might cause an application crash if the OSS NAS runtime and your application use different versions of the C runtime, for instance, when you use Visual Studio 2005 along with an OSS NAS runtime built with Visual Studio 6.
userVar
This field is not used by the present version of the OSS NAS API. Warning: Aside from the fields documented in this section, you should not explicitly modify any other fields in OssNASGlobal. Doing so may produce unpredictable results.

OSS NAS/C API Function Library Files

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.

Dynamic link libraries

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. Each dynamic library supports one particular version of 3GPP NAS. On Windows, these libraries are, for example, ossCEFEDXNAS1160.dll, ossCEFEDXNAS1280.dll, and ossCEFEDXNAS1550.dll. On Linux, they are libossCEFEDXNAS1160.so, libossCEFEDXNAS1280.so, and libossCEFEDXNAS1550.so.

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 file (libossNAS.so) is included in the LD_LIBRARY_PATH environment variable. Otherwise, your application will be unable to load the library at runtime. All plug-ins must also be located in this.

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.

Static link libraries

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 libossNAS1550.a static library, which is located in the lib directory of your product installation.

For Windows, link your NAS application code to a single ossNAS1550.lib static library, which is located in the lib directory of your product installation.

Example

/* Header file containing C structures for the NAS specification */
#include "NAS1550.h"	

/* OSS NAS/C API header file */
#include "ossNAS.h"	

static int CreateOutgoingUEMessage();

enum 
{ 
	bufferSize = 100000
};

static unsigned char encodedDataBuffer[bufferSize];
static unsigned char unencodedDataBuffer[bufferSize];
static unsigned char decodedDataBuffer[bufferSize];
static unsigned char outTextBuffer[bufferSize];
static int lenEncodedData;

/* Helper macro that facilitates the construction of an unencoded message */
#define NEW(T) (freeAddrTemp = freeAddr, freeAddr += sizeof(T), (T *)freeAddrTemp)

int main(int argc, char *argv[])
{
	int exitcode;

	exitcode = CreateOutgoingUEMessage();

	if(exitcode)
		return exitcode;

	return 0;
}

static int CreateOutgoingUEMessage()
{
	/* User-application variable that will hold the state of the OSS NAS/C API */
	OssNASGlobal w, *nasworld = &w;

	OssBuf encodedData;
	OssBuf outData;
	int pdu_num;
	int retcode;
	NAS1550_NASMessage *nasmessage;
	unsigned char *freeAddr, *freeAddrTemp;
	NAS1550_AttachRequest *attachRequest;
	NAS1550_EPSMobileIdentity_imsi_or_imei *imsi;

	/* We initialize the OSS NAS/C API */	
	/* The state of the API will be stored in the variable pointed to by nasworld */
	/* The NAS version number must be specified as an US-ASCII character string, "1550" */
    retcode = ossNASinit(nasworld, "NAS1550");

    if(retcode != 0)
	{
		ossNASPrint(NULL, "ossNASinit error: %s\n", 
				ossNASDescribeReturnCode(nasworld, retcode));
		return 1;
	}

	/* We set the originator of NAS messages to "UE" */	
	ossNASSetOriginator(nasworld, OSSNAS_ORIG_UE);

	/* We set the encoding/decoding flags (no flags) */	
	ossNASSetFlags(nasworld, 0);

	pdu_num = OSSNAS_PDUNUM;
	freeAddr = unencodedDataBuffer;
	nasmessage = NEW(NAS1550_NASMessage);

	/* We start to construct an unencoded NAS message */
	/* This is a plain EMM message of type NAS1550_AttachRequest */
	nasmessage->choice = NAS1550_emmMessage_chosen;
	nasmessage->u.emmMessage = NEW(NAS1550_EMMMessage);
	nasmessage->u.emmMessage->choice = NAS1550_plain_chosen;
	nasmessage->u.emmMessage->u.plain = NEW(NAS1550_PlainEMMMessage);
	nasmessage->u.emmMessage->u.plain->body.choice = NAS1550_attachRequest_chosen ;
	nasmessage->u.emmMessage->u.plain->body.u.attachRequest = 
			attachRequest = NEW(NAS1550_AttachRequest);

   memset(attachRequest, 0, sizeof(NAS1550_AttachRequest));

	/* We populate the NAS1550_AttachRequest message with user-application data */
	attachRequest->epsAttachType.epsAttachType = NAS1550_epsAttachType_combinedEPSIMSI ;

	attachRequest->nasKeySetIdentifier.typeOfSecurityContext = 
			NAS1550_NASKeySetIdentifier_typeOfSecurityContext_mappedSecurityContext;
	attachRequest->nasKeySetIdentifier.nasKeySetIdentifier = 4;

	attachRequest->oldGUTIOrIMSI.choice = NAS1550_imsi_chosen;
	attachRequest->oldGUTIOrIMSI.u.imsi = imsi = NEW(NAS1550_EPSMobileIdentity_imsi_or_imei );
    imsi->typeOfIdentity = NAS1550_EPSMobileIdentity_imsi_or_imei_typeOfIdentity_imsi;
	imsi->identityDigits.length = 7;
	imsi->identityDigits.value = "1234567";

	attachRequest->ueNetworkCapability.
            epsEncryptionAlgorithmsSupported.epsEncryptionAlgorithm128EEA3 =1;
	attachRequest->ueNetworkCapability.
			epsEncryptionAlgorithmsSupported.epsEncryptionAlgorithmEEA4 = 0;
	attachRequest->ueNetworkCapability.
			epsEncryptionAlgorithmsSupported.epsEncryptionAlgorithmEEA6 = 1;
	
   attachRequest->ueNetworkCapability.
           epsIdentityProtectionAlgorithmsSupported.epsIntegrityAlgorithm128EIA3 =1;
	attachRequest->ueNetworkCapability.
			epsIdentityProtectionAlgorithmsSupported.epsIntegrityAlgorithmEIA5 = 1;

	attachRequest->ueNetworkCapability.bit_mask = 
			NAS1550_UENetworkCapability_umtsAlgorithms_present;
	attachRequest->ueNetworkCapability.umtsAlgorithms.bit_mask = 0;
	attachRequest->ueNetworkCapability.umtsAlgorithms.ucs2Support = 
			NAS1550_MSNetworkCapability_ucs2Support_ueHasNoPreference;
	attachRequest->ueNetworkCapability.
			umtsAlgorithms.umtsEncryptionAlgorithmsSupported.
			umtsEncryptionAlgorithmUEA3 = 1;
	attachRequest->ueNetworkCapability.
			umtsAlgorithms.umtsIdentityProtectionAlgorithmsSupported.
			umtsIntegrityAlgorithmUIA5 = 1;

	attachRequest->esmMessageContainer.length = 5;
	attachRequest->esmMessageContainer.value = (unsigned char *)"\x13\x15\x17\x25\x98";

	/* We encode the message */
	encodedData.value = encodedDataBuffer;
	encodedData.length = freeAddr - (unsigned char *)nasmessage;  
			/* encodedData.length = bufferSize;  would also be acceptable */
	retcode = ossNASEncode(nasworld, pdu_num, nasmessage, &encodedData);

	if(retcode != 0) 
	{
		ossNASPrint(nasworld, "ossNASEncode error: %s\n", ossNASGetErrMsg(nasworld));
		return 2;
	}

	/* This is the length of the encoded message produced by the ossNASEncode function */			lenEncodedData = encodedData.length;

	/* We decode the encoded message produced by the ossNASEncode function */
	encodedData.value = encodedDataBuffer;
	encodedData.length = lenEncodedData;
	nasmessage = (NAS1550_NASMessage *)&decodedDataBuffer;
	ossNASSetDecodingLength(nasworld, bufferSize);  
			/* Size of the output buffer for the decoded message */
	retcode = ossNASDecode(nasworld, &pdu_num, &encodedData, (void **)&nasmessage);
			
	if(retcode != 0) 
	{
		ossNASPrint(nasworld, "ossNASDecode error: %s\n", ossNASGetErrMsg(nasworld));
		return 3;
	}			

	/* We compare the decoded message produced by the ossNASDecode function 
		with the unencoded message. They are expected to be equal */
	retcode = ossNASCmpValue(nasworld, OSSNAS_PDUNUM, unencodedDataBuffer, decodedDataBuffer);

	if(retcode != 0)
	{
		ossNASPrint(nasworld, "ossNASCmpValue error: %s\n", 
				ossNASDescribeReturnCode(nasworld, retcode));
		return 4;
	}

	/* We convert the encoded message to XML using the ossNASBinary2XML function */
	encodedData.value = encodedDataBuffer;
	encodedData.length = lenEncodedData;
	outData.value = outTextBuffer;
	outData.length = bufferSize;
	retcode = ossNASBinary2XML(nasworld, pdu_num, OSSNAS_ENCRULE, &encodedData, &outData);

	if(retcode != 0) 
	{
		ossNASPrint(nasworld, "ossNASBinary2XML error: %s\n", 
				ossNASDescribeReturnCode(nasworld, retcode));
		return 5;
	}			

	/* We print the resulting XML text to the console */
	outTextBuffer[outData.length] = 0;
	ossNASPrint(nasworld, "%s\n\n", 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);


	/* We print the decoded message (as XML text) to the console */
	/* The output is expected to match the output of the ossNASBinary2XML function */
	nasmessage = (NAS1550_NASMessage *)&decodedDataBuffer;
	retcode = ossNASPrintPDU(nasworld, OSSNAS_PDUNUM, nasmessage);

	if(retcode != 0) 
	{
		ossNASPrint(nasworld, "ossNASPrintPDU error: %s\n", 
				ossNASDescribeReturnCode(nasworld, retcode));
		return 6;
	}			

	ossNASPrint(nasworld, "\n"); 
    ossNASterm(nasworld);
	return 0;
}

This documentation applies to the NAS/C Encoder Decoder Library for LTE/EPC v7.1.2 for 3GPP Release 15.5.0.

Copyright © 2020 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 NAS/C Encoder Decoder Library for LTE/EPC is associated with a specific license and related unique license number. That license determines, among other things, what functions of the NAS/C Encoder Decoder Library for LTE/EPC are available to you.