[MERGED] libosmo-sccp[master]: Add example program how to use M3UA+SCCP client and server

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Harald Welte gerrit-no-reply at lists.osmocom.org
Mon Apr 10 11:06:09 UTC 2017


Harald Welte has submitted this change and it was merged.

Change subject: Add example program how to use M3UA+SCCP client and server
......................................................................


Add example program how to use M3UA+SCCP client and server

This is an example tool that can be run either as server (SG) or as
client (ASP) with a SCCP+M3UA stacking, and communicate via
connectionless and connection-oriented primitives over it

Change-Id: Id698ce2da5726e304dfa1773b794671dc80d853c
---
M .gitignore
M Makefile.am
M configure.ac
A examples/Makefile.am
A examples/internal.h
A examples/m3ua_example.c
A examples/sccp_test_server.c
A examples/sccp_test_vty.c
8 files changed, 392 insertions(+), 1 deletion(-)

Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/.gitignore b/.gitignore
index 9d1435f..83f1333 100644
--- a/.gitignore
+++ b/.gitignore
@@ -60,6 +60,7 @@
 tests/testsuite
 tests/testsuite.log
 
+examples/m3ua_example
 
 *.pc
 config.*
diff --git a/Makefile.am b/Makefile.am
index b1eff56..dd73ec2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,7 @@
 AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6
 
 AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
-SUBDIRS = include src tests
+SUBDIRS = include src tests examples
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libosmo-sccp.pc libosmo-mtp.pc libosmo-sigtran.pc libosmo-xua.pc
diff --git a/configure.ac b/configure.ac
index 3644d22..6dc0ebd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -27,6 +27,7 @@
 PKG_PROG_PKG_CONFIG([0.20])
 
 PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.3.0)
+PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.3.0)
 PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 0.0.6)
 
 old_LIBS=$LIBS
@@ -68,5 +69,6 @@
     tests/m2ua/Makefile
     tests/xua/Makefile
     tests/ss7/Makefile
+    examples/Makefile
     Makefile)
 
diff --git a/examples/Makefile.am b/examples/Makefile.am
new file mode 100644
index 0000000..6418aca
--- /dev/null
+++ b/examples/Makefile.am
@@ -0,0 +1,11 @@
+AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
+AM_CFLAGS=-Wall -g $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMONETIF_CFLAGS) $(COVERAGE_FLAGS)
+AM_LDFLAGS=$(COVERAGE_LDFLAGS)
+
+noinst_HEADERS = internal.h
+
+noinst_PROGRAMS = m3ua_example
+
+m3ua_example_SOURCES = m3ua_example.c sccp_test_server.c sccp_test_vty.c
+m3ua_example_LDADD = $(top_builddir)/src/libosmo-sigtran.la \
+		   $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS)
diff --git a/examples/internal.h b/examples/internal.h
new file mode 100644
index 0000000..70b9058
--- /dev/null
+++ b/examples/internal.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#define SSN_TEST_UNUSED		200
+#define SSN_TEST_REFUSE		201
+#define SSN_TEST_ECHO		202
+#define SSN_TEST_CALLBACK	203
+
+struct osmo_sccp_user;
+
+int sccp_test_user_vty_install(struct osmo_sccp_instance *inst, int ssn);
+
+int sccp_test_server_init(struct osmo_sccp_instance *sccp);
diff --git a/examples/m3ua_example.c b/examples/m3ua_example.c
new file mode 100644
index 0000000..d7b1fc2
--- /dev/null
+++ b/examples/m3ua_example.c
@@ -0,0 +1,98 @@
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <osmocom/core/select.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/core/application.h>
+#include <osmocom/core/fsm.h>
+#include <osmocom/vty/vty.h>
+#include <osmocom/vty/telnet_interface.h>
+
+#include <osmocom/sigtran/osmo_ss7.h>
+#include <osmocom/sigtran/sccp_sap.h>
+#include <osmocom/sigtran/sccp_helpers.h>
+#include <osmocom/sigtran/protocol/sua.h>
+#include <osmocom/sigtran/protocol/m3ua.h>
+
+#include "internal.h"
+
+static struct osmo_sccp_instance *sua_server_helper(void)
+{
+	struct osmo_sccp_instance *sccp;
+
+	sccp = osmo_sccp_simple_server(NULL, 1, OSMO_SS7_ASP_PROT_M3UA,
+					-1, "127.0.0.2");
+
+	osmo_sccp_simple_server_add_clnt(sccp, OSMO_SS7_ASP_PROT_M3UA,
+					"23", 23, -1, 0, NULL);
+
+	return sccp;
+}
+
+/***********************************************************************
+ * Initialization
+ ***********************************************************************/
+
+static const struct log_info_cat log_info_cat[] = {
+};
+
+static const struct log_info log_info = {
+	.cat = log_info_cat,
+	.num_cat = ARRAY_SIZE(log_info_cat),
+};
+
+static void init_logging(void)
+{
+	const int log_cats[] = { DLSS7, DLSUA, DLM3UA, DLSCCP, DLINP };
+	unsigned int i;
+
+	osmo_init_logging(&log_info);
+
+	for (i = 0; i < ARRAY_SIZE(log_cats); i++)
+		log_set_category_filter(osmo_stderr_target, log_cats[i], 1, LOGL_DEBUG);
+}
+
+static struct vty_app_info vty_info = {
+	.name	= "sccp-test",
+	.version = 0,
+};
+
+int main(int argc, char **argv)
+{
+	struct osmo_sccp_instance *sccp;
+	bool client;
+	int rc;
+
+	init_logging();
+	osmo_ss7_init();
+	osmo_fsm_log_addr(false);
+	vty_init(&vty_info);
+
+	if (argc <= 1)
+		client = true;
+	else
+		client = false;
+
+	rc = telnet_init_dynif(NULL, NULL, vty_get_bind_addr(), 2324+client);
+	if (rc < 0) {
+		perror("Erro binding VTY port\n");
+		exit(1);
+	}
+
+
+	if (client) {
+		sccp = osmo_sccp_simple_client(NULL, "client", 23, OSMO_SS7_ASP_PROT_M3UA, 0, M3UA_PORT, "127.0.0.2");
+		sccp_test_user_vty_install(sccp, OSMO_SCCP_SSN_BSC_BSSAP);
+	} else {
+		sccp = sua_server_helper();
+		sccp_test_server_init(sccp);
+	}
+
+	while (1) {
+		osmo_select_main(0);
+	}
+}
diff --git a/examples/sccp_test_server.c b/examples/sccp_test_server.c
new file mode 100644
index 0000000..c3c658f
--- /dev/null
+++ b/examples/sccp_test_server.c
@@ -0,0 +1,115 @@
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <osmocom/core/utils.h>
+#include <osmocom/core/logging.h>
+
+#include <osmocom/sigtran/sccp_sap.h>
+#include <osmocom/sigtran/sccp_helpers.h>
+
+#include "internal.h"
+
+unsigned int conn_id;
+
+/* a simple SCCP User which refuses all connections and discards all
+ * unitdata */
+static int refuser_prim_cb(struct osmo_prim_hdr *oph, void *_scu)
+{
+	struct osmo_sccp_user *scu = _scu;
+	struct osmo_scu_prim *scu_prim = (struct osmo_scu_prim *) oph;
+
+	switch (OSMO_PRIM_HDR(&scu_prim->oph)) {
+	case OSMO_PRIM(OSMO_SCU_PRIM_N_CONNECT, PRIM_OP_INDICATION):
+		printf("%s: refusing N-CONNECT.ind (local_ref=%u)\n",
+			__func__, scu_prim->u.connect.conn_id);
+		osmo_sccp_tx_disconn(scu, scu_prim->u.connect.conn_id,
+				     &scu_prim->u.connect.called_addr,
+				     23);
+		break;
+	default:
+		printf("%s: Unknown primitive %u:%u\n", __func__,
+			oph->primitive, oph->operation);
+		break;
+	}
+	return 0;
+}
+
+/* a simple SCCP User which accepts all connections and echos back all
+ * DATA + UNITDATA */
+static int echo_prim_cb(struct osmo_prim_hdr *oph, void *_scu)
+{
+	struct osmo_sccp_user *scu = _scu;
+	struct osmo_scu_prim *scu_prim = (struct osmo_scu_prim *) oph;
+	const uint8_t *data = msgb_l2(oph->msg);
+	unsigned int data_len = msgb_l2len(oph->msg);
+
+	switch (OSMO_PRIM_HDR(&scu_prim->oph)) {
+	case OSMO_PRIM(OSMO_SCU_PRIM_N_CONNECT, PRIM_OP_INDICATION):
+		printf("%s: Accepting N-CONNECT.ind (local_ref=%u)\n",
+			__func__, scu_prim->u.connect.conn_id);
+		osmo_sccp_tx_conn_resp(scu, scu_prim->u.connect.conn_id,
+				     &scu_prim->u.connect.called_addr,
+				     data, data_len);
+		break;
+	case OSMO_PRIM(OSMO_SCU_PRIM_N_DATA, PRIM_OP_INDICATION):
+		printf("%s: Echoing N-DATA.ind (local_ref=%u)\n",
+			__func__, scu_prim->u.data.conn_id);
+		osmo_sccp_tx_data(scu, scu_prim->u.data.conn_id,
+				  data, data_len);
+		break;
+	case OSMO_PRIM(OSMO_SCU_PRIM_N_UNITDATA, PRIM_OP_INDICATION):
+		printf("%s: Echoing N-UNITDATA.ind\n", __func__);
+		osmo_sccp_tx_unitdata(scu, &scu_prim->u.unitdata.called_addr,
+				      &scu_prim->u.unitdata.calling_addr,
+				      data, data_len);
+		break;
+	default:
+		printf("%s: Unknown primitive %u:%u\n", __func__,
+			oph->primitive, oph->operation);
+		break;
+	}
+	return 0;
+}
+
+/* a simple SCCP User which receives UNITDATA messages and connects back
+ * to whoever sents UNITDATA and then echo's back all DATA */
+static int callback_prim_cb(struct osmo_prim_hdr *oph, void *_scu)
+{
+	struct osmo_sccp_user *scu = _scu;
+	struct osmo_scu_prim *scu_prim = (struct osmo_scu_prim *) oph;
+	const uint8_t *data = msgb_l2(oph->msg);
+	unsigned int data_len = msgb_l2len(oph->msg);
+
+	switch (OSMO_PRIM_HDR(&scu_prim->oph)) {
+	case OSMO_PRIM(OSMO_SCU_PRIM_N_UNITDATA, PRIM_OP_INDICATION):
+		printf("%s: N-UNITDATA.ind: Connectiong back to sender\n", __func__);
+		osmo_sccp_tx_conn_req(scu, conn_id++,
+				     &scu_prim->u.unitdata.called_addr,
+				     &scu_prim->u.unitdata.calling_addr,
+				     data, data_len);
+		break;
+	case OSMO_PRIM(OSMO_SCU_PRIM_N_DATA, PRIM_OP_INDICATION):
+		printf("%s: Echoing N-DATA.ind (local_ref=%u)\n",
+			__func__, scu_prim->u.data.conn_id);
+		osmo_sccp_tx_data(scu, scu_prim->u.data.conn_id,
+				  data, data_len);
+		break;
+	default:
+		printf("%s: Unknown primitive %u:%u\n", __func__,
+			oph->primitive, oph->operation);
+		break;
+	}
+	return 0;
+}
+
+int sccp_test_server_init(struct osmo_sccp_instance *sccp)
+{
+	osmo_sccp_user_bind(sccp, "refuser", &refuser_prim_cb, SSN_TEST_REFUSE);
+	osmo_sccp_user_bind(sccp, "echo", &echo_prim_cb, SSN_TEST_ECHO);
+	osmo_sccp_user_bind(sccp, "callback", &callback_prim_cb, SSN_TEST_CALLBACK);
+
+	return 0;
+}
diff --git a/examples/sccp_test_vty.c b/examples/sccp_test_vty.c
new file mode 100644
index 0000000..1134d57
--- /dev/null
+++ b/examples/sccp_test_vty.c
@@ -0,0 +1,152 @@
+
+#include <string.h>
+
+#include <osmocom/vty/vty.h>
+#include <osmocom/vty/command.h>
+
+#include <osmocom/sigtran/sccp_sap.h>
+#include <osmocom/sigtran/sccp_helpers.h>
+
+#include "internal.h"
+
+#define SCU_NODE 23
+
+static struct osmo_sccp_user *g_scu;
+
+static struct osmo_sccp_addr g_calling_addr = {
+	.presence = OSMO_SCCP_ADDR_T_SSN | OSMO_SCCP_ADDR_T_PC,
+	.ri = OSMO_SCCP_RI_SSN_PC,
+	.pc = 23,
+};
+
+static struct osmo_sccp_addr g_called_addr = {
+	.presence = OSMO_SCCP_ADDR_T_SSN | OSMO_SCCP_ADDR_T_PC,
+	.ssn = 1,
+	.ri = OSMO_SCCP_RI_SSN_PC,
+	.pc = 1,
+};
+
+DEFUN(scu_called_ssn, scu_called_ssn_cmd,
+	"called-addr-ssn <0-255>",
+	"Set SSN of SCCP CalledAddress\n"
+	"SSN of SCCP CalledAddress\n")
+{
+	g_called_addr.ssn = atoi(argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(scu_conn_req, scu_conn_req_cmd,
+	"connect-req <0-16777216> [DATA]",
+	"N-CONNECT.req\n"
+	"Connection ID\n")
+{
+	struct osmo_sccp_user *scu = vty->index;
+	int conn_id = atoi(argv[0]);
+	const char *data = argv[1];
+
+	osmo_sccp_tx_conn_req(scu, conn_id, &g_calling_addr, &g_called_addr,
+				(const uint8_t *)data, data ? strlen(data)+1 : 0);
+	return CMD_SUCCESS;
+}
+
+DEFUN(scu_conn_resp, scu_conn_resp_cmd,
+	"connect-resp <0-16777216> [DATA]",
+	"N-CONNET.resp\n"
+	"Connection ID\n")
+{
+	struct osmo_sccp_user *scu = vty->index;
+	int conn_id = atoi(argv[0]);
+	const char *data = argv[1];
+
+	osmo_sccp_tx_conn_resp(scu, conn_id, NULL,
+				(const uint8_t *)data, data ? strlen(data)+1 : 0);
+	return CMD_SUCCESS;
+}
+
+DEFUN(scu_data_req, scu_data_req_cmd,
+	"data-req <0-16777216> DATA",
+	"N-DATA.req\n"
+	"Connection ID\n")
+{
+	struct osmo_sccp_user *scu = vty->index;
+	int conn_id = atoi(argv[0]);
+	const char *data = argv[1];
+
+	osmo_sccp_tx_data(scu, conn_id, (const uint8_t *)data, strlen(data)+1);
+	return CMD_SUCCESS;
+}
+
+DEFUN(scu_unitdata_req, scu_unitdata_req_cmd,
+	"unitdata-req DATA",
+	"N-UNITDATA.req\n")
+{
+	struct osmo_sccp_user *scu = vty->index;
+	const char *data = argv[0];
+
+	osmo_sccp_tx_unitdata(scu, &g_calling_addr, &g_called_addr,
+				(const uint8_t *)data, strlen(data)+1);
+	return CMD_SUCCESS;
+}
+
+DEFUN(scu_disc_req, scu_disc_req_cmd,
+	"disconnect-req <0-16777216>",
+	"N-DISCONNT.req\n"
+	"Connection ID\n")
+{
+	struct osmo_sccp_user *scu = vty->index;
+	int conn_id = atoi(argv[0]);
+
+	osmo_sccp_tx_disconn(scu, conn_id, NULL, 42);
+	return CMD_SUCCESS;
+}
+
+static struct cmd_node scu_node = {
+	SCU_NODE,
+	"%s(sccp-user)# ",
+	1,
+};
+
+DEFUN(scu, scu_cmd,
+	"sccp-user",
+	"Enter SCCP User Node\n")
+{
+	vty->node = SCU_NODE;
+	vty->index = g_scu;
+	return CMD_SUCCESS;
+}
+
+static int testclnt_prim_cb(struct osmo_prim_hdr *oph, void *_scu)
+{
+	struct osmo_sccp_user *scu = _scu;
+	struct osmo_scu_prim *scu_prim = (struct osmo_scu_prim *) oph;
+
+	switch (OSMO_PRIM_HDR(&scu_prim->oph)) {
+	case OSMO_PRIM(OSMO_SCU_PRIM_N_CONNECT, PRIM_OP_INDICATION):
+	default:
+		break;
+	}
+	return 0;
+}
+
+
+int sccp_test_user_vty_install(struct osmo_sccp_instance *inst, int ssn)
+{
+	g_scu = osmo_sccp_user_bind(inst, "test_client_vty", testclnt_prim_cb, ssn);
+	if (!g_scu)
+		return -1;
+
+	g_calling_addr.ssn = ssn;
+
+	install_node(&scu_node, NULL);
+	vty_install_default(SCU_NODE);
+	install_element(SCU_NODE, &scu_called_ssn_cmd);
+	install_element(SCU_NODE, &scu_conn_req_cmd);
+	install_element(SCU_NODE, &scu_conn_resp_cmd);
+	install_element(SCU_NODE, &scu_data_req_cmd);
+	install_element(SCU_NODE, &scu_unitdata_req_cmd);
+	install_element(SCU_NODE, &scu_disc_req_cmd);
+
+	install_element(ENABLE_NODE, &scu_cmd);
+
+	return 0;
+}

-- 
To view, visit https://gerrit.osmocom.org/2219
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Id698ce2da5726e304dfa1773b794671dc80d853c
Gerrit-PatchSet: 7
Gerrit-Project: libosmo-sccp
Gerrit-Branch: master
Gerrit-Owner: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder



More information about the gerrit-log mailing list