5G NGAP C++ Sample Code Using OSS ASN.1 Tools


This sample is provided as part of the OSS ASN.1 Tools trial and commercial shipments. The source code and related files are listed below for reference.

The sample demonstrates how to use the OSS ASN.1 Tools to process messages for the 3GPP 5G NGAP standard (TS 38.413 version 19.0.0).

It runs on Linux on x86-64 as an example and illustrates how to decode, inspect, and create PER-encoded 5G NGAP messages using the OSS ASN.1 Tools API.

The sample reads NGAP messages from .per files, decodes and prints them, and creates and encodes a response message.

A makefile is included for building and running the test program using the OSS ASN.1/C++ runtime.

To explore more samples (LTE RRC, 5G RRC, S1AP, X2AP, NGAP), visit the main Sample Code page.

Overview

This sample shows how to:

  • Initialize the OSS ASN.1/C++ runtime for the 5G NGAP schema.
  • Read .per files that contain valid PER-encoded 5G NGAP messages.
  • Decode and print 5G NGAP messages.
  • Create and encode a response message.
  • Build and run the sample test program with a makefile on Linux.

Files in This Sample

The files listed below are included in the OSS ASN.1 Tools trial and commercial shipments and are used by this sample program:

File Description
README.TXT Instructions and sample overview.
*.asn ASN.1 source files that describe the 3GPP 5G NGAP protocol (TS 38.413) used with this program example.
NGAP-PDU_HandoverRequest.per Valid PER-encoded NGAP message. It should pass testing.
tngap.cpp Simple C++ program that shows how to work with 5G NGAP protocol data. It reads input messages from files, decodes and prints them, and creates and encodes a response message.
makefile Makefile that builds and runs the sample test.
makefile.rtoed Makefile that builds and runs the sample test using RTOED.
gui/ ASN.1 Studio project for viewing/compiling schema and generating sample data.

Build and Run Instructions

(Installation instructions for the OSS ASN.1 Tools are included in all trial and commercial shipments.)

To build and run this sample, install a trial or licensed version of the OSS ASN.1 Tools for C++.

1. Generate C source and header files (runtime-only shipments)

If your shipment is runtime-only, generate the .cpp and .h files by running:

make cross

This creates a samples/cross directory with:

  • the required .asn files
  • scripts to run the OSS ASN.1/C++ compiler (asn1cpl.sh or asn1cpl.bat)
2. Build and run the sample
make

This command compiles the sample C++ source, links it with the OSS ASN.1 static library, and executes the test. To use another type of library in the shipment (such as a shared library), set the A makefile variable, for example:

make A=so
3. Clean up generated files
make clean
4. Other Platforms

Note: The C++ source code in this sample is platform-independent. Linux commands are shown as an example, but equivalent samples and build instructions are available for Windows, macOS, and other platforms. For help with platform-specific instructions, please contact OSS Support.

Code Listing: tngap.cpp

The following listing shows the main C++ source file for this sample test program, tngap.c. It demonstrates how to read PER-encoded 5G NGAP messages from files, decode and print them, and create and encode a response message using the OSS ASN.1 Tools API.

Show tngap.cpp source code
/****************************************************************************/
/*  Copyright (C) 2025 OSS Nokalva, Inc.  All rights reserved.               */
/*****************************************************************************/
/* THIS FILE IS PROPRIETARY MATERIAL OF OSS NOKALVA, INC.                    */
/* AND MAY BE USED ONLY BY DIRECT LICENSEES OF OSS NOKALVA, INC.             */
/* THIS FILE MAY NOT BE DISTRIBUTED.                                         */
/* THIS COPYRIGHT STATEMENT MAY NOT BE REMOVED.                              */
/* THIS SAMPLE PROGRAM IS PROVIDED AS IS. THE SAMPLE PROGRAM AND ANY RESULTS */
/* OBTAINED FROM IT ARE PROVIDED WITHOUT ANY WARRANTIES OR REPRESENTATIONS,  */
/* EXPRESS, IMPLIED OR STATUTORY.                                            */
/*****************************************************************************/
/*
 * $Id: 5G-ngap-cpp.html 3363 2026-02-16 09:51:05Z macra $
 */

/*
 *Demonstrates work with data for NGAP protocol
 */

#include <errno.h>
#include <string.h>
#include "ngap_r19.h"

/* Names of Criticality values */
static const char *Criticalities[] = { "reject", "ignore", "notify" };

/* Names of HandoverType values */
static const char *HandoverType[] = {
	"intra5gs", "fivegs-to-eps", "eps-to-5gs", "unknown"
};

/* The directory where input files reside. It is set to the command line parameter
 * if any and to the directory where the sample is started, otherwise.
 */
char *filesDir;

/*
 * FUNCTION     Helper function to open file in the specified directory.
 *
 * PARAMETERS
 *     directoryName    directory where fileName resides
 *     fileName         file to open
 *
 * RETURNS      pointer to file on success, NULL on failure
 */
FILE * openInputFile(char *directoryName, const char *fileName)
{
    char *path;
    FILE *fv;
    const char kPathSeparator =
#ifdef _WIN32
				'\\';
#else
				'/';
#endif

    if (directoryName) {
	size_t dLength = strlen(directoryName);

	if (NULL == (path = (char*)asn1Malloc(dLength + strlen(fileName) + 2))) {
	    return NULL;
	}

	memcpy(path, directoryName, dLength);
	if (path[dLength - 1] != kPathSeparator)
	    path[dLength++] = kPathSeparator;
	strcpy(path+dLength, fileName);
    } else {
	path = (char *) fileName;
    }

    if (!(fv = fopen(path, "rb"))) {
	printf("Failed to open the '%s' file. Restart the sample program using the file "
		"location as the input parameter.\n", path);
    }

    if (path != fileName)
	asn1Free(path);

    return fv;
}

/*
 * FUNCTION     readEncodingFromFile() reads serialized message from specified
 *              file
 *
 * PARAMETERS
 *    filename  name of file containing serialized message
 *    buf       read message
 *
 * RETURNS      0 on success, error code on failure
 */
static int readEncodingFromFile(const char *filename, EncodedBuffer &buf)
{
    FILE        *in = openInputFile(filesDir, filename);
    long        length;
    char *data;

    if (!in) {
        printf("fopen() failed to open %s: %s\n", filename, strerror(errno));
        exit(-1);
    }

    if (fseek(in, 0, SEEK_END)) {
        printf("fseek() failed: %s\n", strerror(errno));
        exit(-1);
    }

    length = ftell(in);
    if (length < 0) {
        printf("ftell() failed: %s\n", strerror(errno));
        exit(-1);
    }

    /* Allocate memory to store completely read message in it */
    data = (char*)asn1Malloc(length);

    rewind(in);

    if ((size_t)length != fread(data, sizeof(char), (size_t)length, in)) {
        printf("fread() failed\n");
    }
    fclose(in);
    /* Store read message in output argument */
    buf.grab_buffer(length, data);
    return 0;
}

/*****************************************************************************
 * Printing functions below are intended to demonstrate how to access NGAP
 * PDU components and to analyze their contents.
 *****************************************************************************/

/*
 * FUNCTION     printHexString() prints data (octet string) as a sequence of
 *              hexadecimal digits 'XXXX...'H
 *
 * PARAMETERS
 *    length    length of input data
 *    value     pointer to input data
 *    indent    indentation
 *
 */
static void printHexString(unsigned int length, unsigned char *value, int indent)
{
    unsigned int i, j,
		max_pos = 74 - indent;

    printf("'");
    for (i = 0, j = 1; i < length; i++, j += 2) {
	/* skip to next line when the current one is filled */
	if (j >= max_pos) {
	    printf("'\n%*s'", indent, "");
	    j = 1;
	}
	printf("%02X", value[i]);
    }
    printf("'H");
}

/* Prints a BIT STRING as a sequence of hexadecimal digits */
#define printHexBitString(length, value, indent)\
	    printHexString((length + 7)/8, value, indent)

/*
 * FUNCTION     printProtocolExtensions() prints ProtocolExtensionContainer
 *              data.
 *
 * PARAMETERS
 *    ctl       OSS environment variable
 *    ie_ext    pointer to ProtocolExtensionContainer data to print
 *    indent    indentation
 *
 * RETURNS      0 on success, error code on failure
 */
static int printProtocolExtensions(OssControl &ctl, OSS_NGAP_UEAggregateMaximumBitRate::iE_Extensions *ie_ext,
				int indent)
{
    if (!ie_ext)
        return 0;
    printf("%*s%s includes the following IEs:\n", indent++, "",
				"iE-Extensions");
    int cnt = 0;
    /* Print each IE in the list */
    for (OssIndex i = ie_ext->first(); i != OSS_NOINDEX; i = ie_ext->next(i)) {

        OSS_NGAP_PrivateMessageIEs_Value &extval = ie_ext->at(i)->get_extensionValue();

	printf("%*s#%d: id = %2u, criticality = %s\n", indent, "",
		cnt++, ie_ext->at(i)->get_id(), Criticalities[ie_ext->at(i)->get_criticality()]);

	if (extval.has_decoded()) {
            OSS_NGAP_PDU_PDU pdu;
            extval.get_decoded(pdu);
	    pdu.print(ctl);
        } else {
            printf("PDU is not decoded\n");
        }
    }
    return 0;
}


/*
 * FUNCTION     printProtocolExtensionsGGNB_ID() prints ProtocolExtensionContainer
 *              data.
 *
 * PARAMETERS
 *    ctl       OSS environment variable
 *    ie_ext    pointer to ProtocolExtensionContainer data to print
 *    indent    indentation
 *
 * RETURNS      0 on success, error code on failure
 */
static int printProtocolExtensionsGGNB_ID(OssControl &ctl, OSS_NGAP_GlobalGNB_ID::iE_Extensions *ie_ext,
				int indent)
{
    if (!ie_ext)
        return 0;
    printf("%*s%s includes the following IEs:\n", indent++, "",
				"iE-Extensions");
    int cnt = 0;
    /* Print each IE in the list */
    for (OssIndex i = ie_ext->first(); i != OSS_NOINDEX; i = ie_ext->next(i)) {

        OSS_NGAP_PrivateMessageIEs_Value &extval = ie_ext->at(i)->get_extensionValue();

	printf("%*s#%d: id = %2u, criticality = %s\n", indent, "",
		cnt++, ie_ext->at(i)->get_id(), Criticalities[ie_ext->at(i)->get_criticality()]);

	if (extval.has_decoded()) {
            OSS_NGAP_PDU_PDU pdu;
            extval.get_decoded(pdu);
	    pdu.print(ctl);
        } else {
            printf("PDU is not decoded\n");
        }
    }
    return 0;
}

/*
 * FUNCTION     printProtocolExtensionsTRN_ID() prints ProtocolExtensionContainer
 *              data.
 *
 * PARAMETERS
 *    ctl       OSS environment variable
 *    ie_ext    pointer to ProtocolExtensionContainer data to print
 *    indent    indentation
 *
 * RETURNS      0 on success, error code on failure
 */
static int printProtocolExtensionsTRN_ID(OssControl &ctl, OSS_NGAP_TargetRANNodeID::iE_Extensions *ie_ext,
				int indent)
{
    if (!ie_ext)
        return 0;
    printf("%*s%s includes the following IEs:\n", indent++, "",
				"iE-Extensions");
    int cnt = 0;
    /* Print each IE in the list */
    for (OssIndex i = ie_ext->first(); i != OSS_NOINDEX; i = ie_ext->next(i)) {

        OSS_NGAP_TargetRANNodeID_ExtIEs_Extension &extval = ie_ext->at(i)->get_extensionValue();

        printf("%*s#%d: id = %2u, criticality = %s\n", indent, "",
		cnt++, ie_ext->at(i)->get_id(), Criticalities[ie_ext->at(i)->get_criticality()]);

	if (extval.has_decoded()) {
            OSS_NGAP_PDU_PDU pdu;
            extval.get_decoded(pdu);
	    pdu.print(ctl);
        } else {
            printf("PDU is not decoded\n");
        }
    }
    return 0;
}

/*
 * FUNCTION     printProtocolIEs() prints ProtocolIE_Container data.
 *              ossPrintPDU() is called to print IEs that are not
 *              handled by this function.
 *
 * PARAMETERS
 *    ctl       OssControl object
 *    ies       pointer to ProtocolIE-Container data to print
 *    indent    indentation
 *
 * RETURNS      0 on success, error code on failure
 */
static int printProtocolIEs(OssControl &ctl, OSS_NGAP_HRequiredIEs &ies, int indent)
{
    int err = 0;

    printf("%*s%s includes the following IEs:\n", indent++, "",
					"protocolIEs");
    /* Print each IE */
    int i = 1;
    for (OssIndex idx = ies.first(); idx != OSS_NOINDEX; idx = ies.next(idx), i++) {

	OSS_NGAP_HRequiredIE *field = ies.at(idx);
	OSS_NGAP_HandoverRequiredIEs_Value   value = field->get_value();

	printf("\n%*s#%d: id = %2u, criticality = %s\n", indent, "",
		    i, field->get_id(), Criticalities[field->get_criticality()]);
	++indent;

        if (field->get_id() == OSS_NGAP_id_AMF_UE_NGAP_ID) {
	    printf("%*svalue %s: %llu\n", indent, "", "AMF-UE-NGAP-ID",
					*value.get_OSS_NGAP_AMF_UE_NGAP_ID());
	} else if (field->get_id() == OSS_NGAP_id_RAN_UE_NGAP_ID) {
	    printf("%*svalue %s: %u\n", indent, "", "RAN-UE-NGAP-ID",
                                        *value.get_OSS_NGAP_RAN_UE_NGAP_ID());

	} else 	if (field->get_id() == OSS_NGAP_id_HandoverType) {
	    printf("%*svalue %s: %s\n", indent, "", "HandoverType",
		HandoverType[
			((*value.get_OSS_NGAP_HandoverType()) <= OSS_NGAP_eps_to_5gs)
			    ? *value.get_OSS_NGAP_HandoverType() : OSS_NGAP_eps_to_5gs + 1]);

	} else if (field->get_id() == OSS_NGAP_id_Cause) {
	    OSS_NGAP_Cause  *pcause = value.get_OSS_NGAP_Cause();

	    /*
	     * Named values can be printed below instead of numbers for all
	     * Cause components
	     */
	    printf("%*svalue %s: ", indent, "", "Cause");
            if (OSS_NGAP_CauseRadioNetwork *radioNetwork = pcause->get_radioNetwork()) {
                printf("%s : %d", "radioNetwork", *radioNetwork);
            } else if (OSS_NGAP_CauseTransport *transport = pcause->get_transport()) {
                printf("%s : %d", "transport", *transport);
	    } else if (OSS_NGAP_CauseNas *nas = pcause->get_nas()) {
                printf("%s : %d", "nas", *nas);
            } else if (OSS_NGAP_CauseProtocol *protocol = pcause->get_protocol()) {
		printf("%s : %d", "protocol", *protocol);
            } else if (OSS_NGAP_CauseMisc *misc = pcause->get_misc()) {
                printf("%s : %d", "misc", *misc);
	    } else if (OSS_NGAP_Cause::choice_Extensions *extensions = pcause->get_choice_Extensions()) {
		extensions = NULL;
                printf("%s: ", "choice-Extensions --<Not implemented>--");
            }
	    printf("\n");
	/* TargetID IE */
	} else if (field->get_id() == OSS_NGAP_id_TargetID) {
	    OSS_NGAP_TargetID *ptarget = value.get_OSS_NGAP_TargetID();

	    printf("%*svalue %s : ", indent, "", "TargetID");
	    indent++;
	    if (OSS_NGAP_TargetRANNodeID *targetRN_ID = ptarget->get_targetRANNodeID()) {
		printf("%s :\n", "globalRANNodeID");
		indent++;
		OSS_NGAP_GlobalRANNodeID &globalRN_ID = targetRN_ID->get_globalRANNodeID();
		if (OSS_NGAP_GlobalGNB_ID *glob_id = globalRN_ID.get_globalGNB_ID()){
		    printf("%*s%s:\n", indent, "", "globalGNB-ID");
		    indent++;
		    printf("%*s%s: ", indent, "", "pLMNIdentity");
		    OssString &pLMNId = glob_id->get_pLMNIdentity();
		    printHexString(pLMNId.length(), (unsigned char*)pLMNId.get_buffer(), indent);
		    printf("\n%*s%s : ", indent, "", "gNB-ID");

		    OSS_NGAP_GNB_ID &gnb_id = glob_id->get_gNB_ID();
	            if (gnb_id.get_gNB_ID()) {
                        printf("%s: ", "gNB-ID");
			printHexBitString(gnb_id.get_gNB_ID()->length(), gnb_id.get_gNB_ID()->get_buffer(), indent);
		    } else if (gnb_id.get_choice_Extensions()) {
                        printf("%s: ", "choice-Extensions --<Not implemented>--");
		    }
		    printf("\n");
		    if (OSS_NGAP_GlobalGNB_ID::iE_Extensions *ie_ext = glob_id->get_iE_Extensions()) {
                printProtocolExtensionsGGNB_ID(ctl, ie_ext, indent);
                printf("\n");
		    }
		    indent--;
		} else if (globalRN_ID.get_globalNgENB_ID()) {
		    printf("%s :\n", "globalNgENB-ID --<Not implemented>--\n");
		} else if (globalRN_ID.get_globalN3IWF_ID()) {
		    printf("%s :\n", "globalN3IWF-ID --<Not implemented>--\n");
		} else if (globalRN_ID.get_choice_Extensions()) {
		    printf("%s: ", "choice-Extensions --<Not implemented>--\n");
		}
		printf("%*s%s:\n", indent, "", "selectedTAI");
		indent++;
		printf("%*s%s: ", indent, "", "pLMNIdentity");
                printHexString(targetRN_ID->get_selectedTAI().get_pLMNIdentity().length(),
				(unsigned char*)targetRN_ID->get_selectedTAI().get_pLMNIdentity().get_buffer(),
				indent);
		printf("\n%*s%s: ", indent, "", "tAC");
		printHexString(targetRN_ID->get_selectedTAI().get_tAC().length(),
				    (unsigned char*)targetRN_ID->get_selectedTAI().get_tAC().get_buffer(), indent);
                if (targetRN_ID->get_iE_Extensions()) {
		    printf("\n");
		    printProtocolExtensionsTRN_ID(ctl, targetRN_ID->get_iE_Extensions(), indent);
                }
		indent -= 2;
            } else if (OSS_NGAP_TargeteNB_ID *targeteNB_ID = ptarget->get_targeteNB_ID()) {
		printf("\n%*s%s: ", indent, "", "globalENB-ID");
		printf("\n%*s%s: ", indent, "", "selected-EPS-TAI");
		if (targeteNB_ID->get_iE_Extensions()) {
		    printf("\n");
		    printProtocolExtensions(ctl, targeteNB_ID->get_iE_Extensions(), indent);
		}
            } else if (ptarget->get_choice_Extensions()) {
		printf("%s: ", "choice-Extensions --<Not implemented>--");
	    }
	    indent--;
	    printf("\n");

	} else if (field->get_id() == OSS_NGAP_id_DirectForwardingPathAvailability) {
	    OSS_NGAP_DirectForwardingPathAvailability *ptarget =
                                value.get_OSS_NGAP_DirectForwardingPathAvailability();

	    printf("%*svalue %s : ", indent, "", "DirectForwardingPathAvailability");
	    if (*ptarget)
		printf("%u\n", *ptarget);
	    else
		printf("direct-path-available\n");
	} else if (field->get_id() == OSS_NGAP_id_PDUSessionResourceListHORqd) {
	    OSS_NGAP_PDUSessionResourceListHORqd *ptarget =
				value.get_OSS_NGAP_PDUSessionResourceListHORqd();
	    ptarget = NULL;
	    printf("%*svalue %s : ", indent, "", "PDUSessionResourceListHORqd");
	    printf("%*s%s : ", indent + 1, "", "--<Not implemented>--\n");
	} else if (field->get_id() == OSS_NGAP_id_SourceToTarget_TransparentContainer) {
	    OSS_NGAP_SourceToTarget_TransparentContainer *ptarget =
			    value.get_OSS_NGAP_SourceToTarget_TransparentContainer();

	    printf("%*svalue %s : ", indent, "", "SourceToTarget-TransparentContainer");
	    printHexString(ptarget->length(), (unsigned char*)ptarget->get_buffer(), indent);
	    printf("\n");
	} else
	    printf("%*svalue %s (%d)\n", indent, "", "UNKNOWN", field->get_id());
	indent--;
    }
    return err;
}

/*
 * FUNCTION     printHandoverRequiredMsg() prints NGAP pdu which contains
 *              HandoverRequired message.  The function is not intended to
 *              handle other types of messages.
 *
 * PARAMETERS
 *    ctl       OssControl object
 *    pdu       input NGAP PDU which data should be printed
 *
 * RETURNS      0 on success, error code on failure
 */
static int printHandoverRequiredMsg(OssControl &ctl, OSS_NGAP_PDU *pdu)
{

    OSS_NGAP_InitiatingMessage *imsg = pdu->get_initiatingMessage();
    /* Get identifier of message stored in PDU */
    if (!imsg) {
	printf("Unexpected type of message");
	return -1;
    }
    OSS_NGAP_NGAP_ELEMENTARY_PROCEDURES_InitiatingMessage  &msg_value = imsg->get_value();
    OSS_NGAP_HandoverRequired *hr_value = msg_value.get_OSS_NGAP_HandoverRequired();

    if (!hr_value) {
	printf("Unexpected message.\n");
	return -1;
    }

    printf("HandoverRequired message.\n\n");

    return printProtocolIEs(ctl, hr_value->get_protocolIEs(), 0);
}

/*
 * FUNCTION     createSuccessResponse() creates NGAP successful outcome
 *              message for given HandoverRequired request.
 *
 * PARAMETERS
 *    ctl       OssControl object
 *    req       input message (request)
 *    resp      pointer to the successful outcome message (response)
 *              created by the function
 *
 * RETURNS      0 on success, error code on failure
 */
static int createSuccessResponse(OssControl &ctl, OSS_NGAP_PDU *req,
							    OSS_NGAP_PDU &resp)
{
    OSS_NGAP_InitiatingMessage *imsg = req->get_initiatingMessage();
    if (!imsg) {
	printf("Unexpected type of message\n");
	return -1;
    }

    OSS_NGAP_HandoverRequired *hr_value = req->get_initiatingMessage()->get_value().get_OSS_NGAP_HandoverRequired();

    if (NULL == hr_value) {
	printf("No IEs in HandoverRequired request");
	return -1;
    }

    OSS_NGAP_HRequiredIEs &reqies = hr_value->get_protocolIEs();

    /*
     * Create successful outcome message from initiating message. Copy
     * some IEs from input to output.
     */

    OSS_NGAP_SuccessfulOutcome successfulOutcome;
    successfulOutcome.set_procedureCode(req->get_initiatingMessage()->get_procedureCode());
    successfulOutcome.set_criticality(OSS_NGAP_reject);
    OSS_NGAP_NGAP_ELEMENTARY_PROCEDURES_SuccessfulOutcome ot_val;
    OSS_NGAP_HandoverCommand *hoc = new OSS_NGAP_HandoverCommand;
    OSS_NGAP_HCommandIEs respies;

    OssIndex resp_idx = respies.first();

    ossBoolean	element_was_found = FALSE;
    for (OssIndex idx = reqies.first(); idx; idx = reqies.next(idx)) {
	if (reqies.at(idx)->get_id() == OSS_NGAP_id_AMF_UE_NGAP_ID
	    || reqies.at(idx)->get_id() == OSS_NGAP_id_RAN_UE_NGAP_ID
	    || reqies.at(idx)->get_id() == OSS_NGAP_id_HandoverType
	    || reqies.at(idx)->get_id() == OSS_NGAP_id_SourceToTarget_TransparentContainer) {

	    if (reqies.at(idx)->get_id() == OSS_NGAP_id_AMF_UE_NGAP_ID) {
	        OSS_NGAP_HCommandIE hcie;
	        OSS_NGAP_HandoverCommandIEs_Value hciesv;
		OSS_NGAP_AMF_UE_NGAP_ID data = *reqies.at(idx)->get_value().get_OSS_NGAP_AMF_UE_NGAP_ID();
	       	hciesv.set_OSS_NGAP_AMF_UE_NGAP_ID(data);
	        hcie.set_value(hciesv);
 		hcie.set_id(OSS_NGAP_id_AMF_UE_NGAP_ID);
	        resp_idx = respies.insert_after(resp_idx, hcie);
	    } else if (reqies.at(idx)->get_id() == OSS_NGAP_id_RAN_UE_NGAP_ID) {
	        OSS_NGAP_HCommandIE hcie;
                OSS_NGAP_HandoverCommandIEs_Value hciesv;
                OSS_NGAP_RAN_UE_NGAP_ID data = *reqies.at(idx)->get_value().get_OSS_NGAP_RAN_UE_NGAP_ID();
		hciesv.set_OSS_NGAP_RAN_UE_NGAP_ID(data);
	        hcie.set_value(hciesv);
 		hcie.set_id(OSS_NGAP_id_RAN_UE_NGAP_ID);
	        resp_idx = respies.insert_after(resp_idx, hcie);
	    } else if (reqies.at(idx)->get_id() == OSS_NGAP_id_HandoverType) {
	        OSS_NGAP_HCommandIE hcie;
                OSS_NGAP_HandoverCommandIEs_Value hciesv;
		OSS_NGAP_HandoverType data = *reqies.at(idx)->get_value().get_OSS_NGAP_HandoverType();
                hciesv.set_OSS_NGAP_HandoverType(data);
	        hcie.set_value(hciesv);
 		hcie.set_id(OSS_NGAP_id_HandoverType);
	        resp_idx = respies.insert_after(resp_idx, hcie);
	    } else {
		/*
		 * Create TargetToSource_TransparentContainer.
		 * Now copy SourceToTarget_TransparentContainer to Target.
		 */
		OSS_NGAP_TargetToSource_TransparentContainer t2s_container;

		OSS_NGAP_SourceToTarget_TransparentContainer *s2t_container =
				reqies.at(idx)->get_value().get_OSS_NGAP_SourceToTarget_TransparentContainer();

		t2s_container = *s2t_container;

		OSS_NGAP_HandoverCommandIEs_Value hciesv;
		hciesv.set_OSS_NGAP_TargetToSource_TransparentContainer(t2s_container);
		OSS_NGAP_HCommandIE hcie;
		hcie.set_value(hciesv);
		hcie.set_id(OSS_NGAP_id_TargetToSource_TransparentContainer);
	        resp_idx = respies.insert_after(resp_idx, hcie);
	    }
	    element_was_found = TRUE;
	}

    }
    hoc->set_protocolIEs(respies);
    ot_val.set_OSS_NGAP_HandoverCommand(hoc);
    successfulOutcome.set_value(ot_val);
    resp.set_successfulOutcome(successfulOutcome);

    return 0;
}

/*
 * FUNCTION     testNGAP() is used to test NGAP message, the input serialized
 *              pdu is deserialized and printed, then an outcome message
 *              is created, printed and encoded.
 *
 * PARAMETERS
 *    ctl	OssControl object
 *    filename  name of file containing serialized message
 *
 */
static int testNGAP(OssControl &ctl, const char *filename)
{
    EncodedBuffer encoded_data;
    int		  err;

    printf("======================================================"
		"======================\n");
    printf("### Reading serialized request message from file: \"%s\"... ", filename);
    /* Read serialized message from file */
    err = readEncodingFromFile(filename, encoded_data);
    if (!err) {
	printf("OK.\n\n");

	OSS_NGAP_PDU_PDU pdu;
	printf("### Deserializing the message...\n");
	/* Deserialize input message */
	pdu.decode(ctl, encoded_data);
        printf("\n");
	printf("### Printing the deserialized message:\n");
	/* Print deserialized message */
	pdu.print(ctl);
	printf("\n");
        OSS_NGAP_PDU *decoded = pdu.get_data();
	printf("### Printing the deserialized message by a handwritten code"
		    " demonstrating how to access data:\n");
	if (0 == (err = printHandoverRequiredMsg(ctl, decoded))) {
            OSS_NGAP_PDU  resp;


            printf("\n### Creating Success Response message... ");
            /* Create successful outcome message */
            err = createSuccessResponse(ctl, pdu.get_data(), resp);
            if (!err) {

		printf("OK.\n\n### Printing the created response message:\n");
	        OSS_NGAP_PDU_PDU resp_pdu;
		resp_pdu.set_data(resp);
		resp_pdu.print(ctl);
		printf("\n\n### Serializing the response message... \n");

		/* Serialize outcome message */
	        EncodedBuffer msg;
	        resp_pdu.encode(ctl, msg);

		printf("\n");
                printf("Serialized response (%lu bytes):\n",
				    msg.get_data_size());

                printHexString(msg.get_data_size(), (unsigned char*)msg.get_data(), 0);
                printf("\n\n");
            }
        }
	pdu.free_data(ctl);
    }
    return err;
}

/*
 * Deserializes and prints input messages, creates and prints successful
 * outcome messages
 */
int main(int argc, char *argv[])
{
    int err = 0;

    try {
        _oss_ngap_control_table_Control ctl;

        /* Set flags */
        ctl.setEncodingFlags(AUTOMATIC_ENCDEC);
        ctl.setDecodingFlags(AUTOMATIC_ENCDEC);
        /* Set debug mode */
	ctl.setDebugFlags(PRINT_ERROR_MESSAGES | PRINT_DECODING_DETAILS |
		PRINT_ENCODING_DETAILS);
        filesDir = argc > 1 ? argv[1] : (char*)".";

        testNGAP(ctl, "NGAP-PDU_HandoverRequest.per");
	printf("Testing successful.\n");

    } catch (ASN1RuntimeException &exc) {
        err = exc.get_code();
	printf("An error occurred: code = %d.\n", err);
    } catch (...) {
	printf("An unexpected exception occurred.\n");
	err =  -1;
    }

    return err;
}

Expected Output (Excerpt)

This is the expected output when running the sample:

Decoded NGAP message:
  ...
Encoding response message...
Encoding successful.

ASN.1 Schema Excerpt (ngap.asn)

Show excerpt from ngap.asn
-- Excerpt from ngap.asn 3GPP TS 38.413 V19.0.0 (2025-09) 

-- **************************************************************
--
-- Elementary Procedure definitions
--
-- **************************************************************

NGAP-PDU-Descriptions  { 
itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) 
ngran-Access (22) modules (3) ngap (1) version1 (1) ngap-PDU-Descriptions (0)}

DEFINITIONS AUTOMATIC TAGS ::= 

BEGIN

-- **************************************************************
--
-- IE parameter types from other modules.
--
-- **************************************************************

IMPORTS

	Criticality,
	ProcedureCode
FROM NGAP-CommonDataTypes

	AMFConfigurationUpdate,
	AMFConfigurationUpdateAcknowledge,
	AMFConfigurationUpdateFailure,
	AMFCPRelocationIndication,
	AMFStatusIndication,
	BroadcastSessionModificationFailure,
	BroadcastSessionModificationRequest,
	BroadcastSessionModificationResponse,
	BroadcastSessionReleaseRequest,
	BroadcastSessionReleaseRequired,
	BroadcastSessionReleaseResponse,
	BroadcastSessionSetupFailure,
	BroadcastSessionSetupRequest,
	BroadcastSessionSetupResponse,
	BroadcastSessionTransportFailure,
	BroadcastSessionTransportRequest,
	BroadcastSessionTransportResponse,
	CellTrafficTrace,
	ConnectionEstablishmentIndication,
	DeactivateTrace,
	DistributionReleaseRequest,
	DistributionReleaseResponse,
	DistributionSetupFailure,
	DistributionSetupRequest,
	DistributionSetupResponse,
	DownlinkNASTransport,
	DownlinkNonUEAssociatedNRPPaTransport,
	DownlinkRANConfigurationTransfer,
	DownlinkRANEarlyStatusTransfer,
	DownlinkRANStatusTransfer,
	DownlinkUEAssociatedNRPPaTransport,
	ErrorIndication,
	HandoverCancel,
	HandoverCancelAcknowledge,
	HandoverCommand,
	HandoverFailure,
	HandoverNotify,
	HandoverPreparationFailure,
	HandoverRequest,
	HandoverRequestAcknowledge,
	HandoverRequired,
	HandoverSuccess,
	InitialContextSetupFailure,
	InitialContextSetupRequest,
	InitialContextSetupResponse,
	InitialUEMessage,
	LocationReport,
	LocationReportingControl,
	LocationReportingFailureIndication,
	MTCommunicationHandlingRequest,
	MTCommunicationHandlingResponse,
	MTCommunicationHandlingFailure,
	MulticastSessionActivationFailure,
	MulticastSessionActivationRequest,
	MulticastSessionActivationResponse,
	MulticastSessionDeactivationRequest,
	MulticastSessionDeactivationResponse,
	MulticastSessionUpdateFailure,
	MulticastSessionUpdateRequest,
	MulticastSessionUpdateResponse,
	MulticastGroupPaging,
	NASNonDeliveryIndication,
	NGReset,
	NGResetAcknowledge,
	NGRemovalFailure,
	NGRemovalRequest,
	NGRemovalResponse,
	NGSetupFailure,
	NGSetupRequest,
	NGSetupResponse,
	OverloadStart,
	OverloadStop,
	Paging,
	PathSwitchRequest,
	PathSwitchRequestAcknowledge,
	PathSwitchRequestFailure,	
	PDUSessionResourceModifyConfirm,
	PDUSessionResourceModifyIndication,
	PDUSessionResourceModifyRequest,
	PDUSessionResourceModifyResponse,
	PDUSessionResourceNotify,
	PDUSessionResourceReleaseCommand,
	PDUSessionResourceReleaseResponse,
	PDUSessionResourceSetupRequest,
	PDUSessionResourceSetupResponse,
	PrivateMessage,
	PWSCancelRequest,
	PWSCancelResponse,
	PWSFailureIndication,
	PWSRestartIndication,
	RANConfigurationUpdate,
	RANConfigurationUpdateAcknowledge,
	RANConfigurationUpdateFailure,
	RANCPRelocationIndication,
	RANPagingRequest,
	RerouteNASRequest,
	RetrieveUEInformation,
	RRCInactiveTransitionReport,
	SecondaryRATDataUsageReport,
	TimingSynchronisationStatusRequest,
	TimingSynchronisationStatusResponse,
	TimingSynchronisationStatusFailure,
	TimingSynchronisationStatusReport,
	TraceFailureIndication,
	TraceStart,
	UEContextModificationFailure,
	UEContextModificationRequest,
	UEContextModificationResponse,
	UEContextReleaseCommand,
	UEContextReleaseComplete,
	UEContextReleaseRequest,
	UEContextResumeRequest,
	UEContextResumeResponse,
	UEContextResumeFailure,
	UEContextSuspendRequest,
	UEContextSuspendResponse,
	UEContextSuspendFailure,
	UEInformationTransfer,
	UERadioCapabilityCheckRequest,
	UERadioCapabilityCheckResponse,
	UERadioCapabilityIDMappingRequest,
	UERadioCapabilityIDMappingResponse,
	UERadioCapabilityInfoIndication,
	UETNLABindingReleaseRequest,
	UplinkNASTransport,
	UplinkNonUEAssociatedNRPPaTransport,
	UplinkRANConfigurationTransfer,
	UplinkRANEarlyStatusTransfer,
	UplinkRANStatusTransfer,
	UplinkUEAssociatedNRPPaTransport,
	WriteReplaceWarningRequest,
	WriteReplaceWarningResponse,
	UplinkRIMInformationTransfer,
	DownlinkRIMInformationTransfer,
	InventoryRequest,
	InventoryResponse,
	InventoryFailure,
	InventoryReport,
	CommandRequest,
	CommandResponse,
	CommandFailure,
	AIOTSessionReleaseCommand,
	AIOTSessionReleaseComplete,
	AIOTSessionReleaseRequest


FROM NGAP-PDU-Contents

	id-AMFConfigurationUpdate,
	id-AMFCPRelocationIndication,
	id-AMFStatusIndication,
	id-BroadcastSessionModification,
	id-BroadcastSessionRelease,
	id-BroadcastSessionReleaseRequired,
	id-BroadcastSessionSetup,
	id-BroadcastSessionTransport,
	id-CellTrafficTrace,
	id-ConnectionEstablishmentIndication,
	id-DeactivateTrace,
	id-DistributionRelease,
	id-DistributionSetup,
	id-DownlinkNASTransport,
	id-DownlinkNonUEAssociatedNRPPaTransport,
	id-DownlinkRANConfigurationTransfer,
	id-DownlinkRANEarlyStatusTransfer,
	id-DownlinkRANStatusTransfer,
	id-DownlinkRIMInformationTransfer,
	id-DownlinkUEAssociatedNRPPaTransport,
	id-ErrorIndication,
	id-HandoverCancel,
	id-HandoverNotification,
	id-HandoverPreparation,
	id-HandoverResourceAllocation,
	id-HandoverSuccess,
	id-InitialContextSetup,
	id-InitialUEMessage,
	id-LocationReport,
	id-LocationReportingControl,
	id-LocationReportingFailureIndication,
	id-MTCommunicationHandling,
	id-MulticastGroupPaging,
	id-MulticastSessionActivation,
	id-MulticastSessionDeactivation,
	id-MulticastSessionUpdate,
	id-NASNonDeliveryIndication,
	id-NGReset,
	id-NGRemoval,
	id-NGSetup,
	id-OverloadStart,
	id-OverloadStop,
	id-Paging,
	id-PathSwitchRequest,
	id-PDUSessionResourceModify,
	id-PDUSessionResourceModifyIndication,
	id-PDUSessionResourceNotify,
	id-PDUSessionResourceRelease,
	id-PDUSessionResourceSetup,
	id-PrivateMessage,
	id-PWSCancel,
	id-PWSFailureIndication,
	id-PWSRestartIndication,
	id-RANConfigurationUpdate,
	id-RANCPRelocationIndication,
	id-RANPagingRequest,
	id-RerouteNASRequest,
	id-RetrieveUEInformation,
	id-RRCInactiveTransitionReport,
	id-SecondaryRATDataUsageReport,
	id-TimingSynchronisationStatus,
	id-TimingSynchronisationStatusReport,
	id-TraceFailureIndication,
	id-TraceStart,
	id-UEContextModification,
	id-UEContextRelease,
	id-UEContextReleaseRequest,
	id-UEContextResume,
	id-UEContextSuspend,
	id-UEInformationTransfer,
	id-UERadioCapabilityCheck,
	id-UERadioCapabilityIDMapping,
	id-UERadioCapabilityInfoIndication,
	id-UETNLABindingRelease,
	id-UplinkNASTransport,
	id-UplinkNonUEAssociatedNRPPaTransport,
	id-UplinkRANConfigurationTransfer,
	id-UplinkRANEarlyStatusTransfer,
	id-UplinkRANStatusTransfer,
	id-UplinkRIMInformationTransfer,
	id-UplinkUEAssociatedNRPPaTransport,
	id-WriteReplaceWarning,
	id-InventoryRequest,
	id-InventoryReport,
	id-CommandRequest,
	id-AIOTSessionRelease,
	id-AIOTSessionReleaseRequest


FROM NGAP-Constants;

-- **************************************************************
--
-- Interface Elementary Procedure Class
--
-- **************************************************************

NGAP-ELEMENTARY-PROCEDURE ::= CLASS {
	&InitiatingMessage				,
	&SuccessfulOutcome							OPTIONAL,
	&UnsuccessfulOutcome						OPTIONAL,
	&procedureCode				ProcedureCode	UNIQUE,
	&criticality				Criticality	DEFAULT ignore
}

WITH SYNTAX {
	INITIATING MESSAGE			&InitiatingMessage
	[SUCCESSFUL OUTCOME			&SuccessfulOutcome]
	[UNSUCCESSFUL OUTCOME		&UnsuccessfulOutcome]
	PROCEDURE CODE				&procedureCode
	[CRITICALITY				&criticality]
}

Using ASN.1 Studio (Optional)

The gui/ subdirectory contains an ASN.1 Studio project for this sample. With ASN.1 Studio you can:

  • Open the 5G NGAP ASN.1 modules.
  • Generate code from the ASN.1 schema.
  • Create and edit sample encoded 5G NGAP messages.
  • Export projects to gmake makefiles.

Related Samples

Disclaimer

This sample is provided solely for illustration purposes, for example to demonstrate usage of the OSS ASN.1 Tools API with 3GPP 5G NGAP messages. It does not represent a complete application. To build and run this sample, you must use a trial or licensed version of the appropriate OSS ASN.1 Tools. The copyright and license statements included in each source file remain fully applicable.

Need Help?

If you have questions about using this sample, contact OSS Nokalva Support.

See Also