Introduce libsmpputil

As part of preparation for libosmo-netif migration let's move common SMPP code
into separate build-time library and use it for both smpp_mirror and OsmoMSC
renaming the files if necessary.

While at it we also fix id/password legth limits in smpp_mirror and drop unused
fields from ESME struct.

Related: OS#5568
Change-Id: I61910651bc7c188dc2fb67d96189a66a47e7e8fb
diff --git a/src/Makefile.am b/src/Makefile.am
index 4e7cea1..e23ab10 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,8 +25,16 @@
 	libmsc \
 	$(NULL)
 
+if BUILD_SMPP
+
+SUBDIRS += \
+	libsmpputil \
+	utils \
+	$(NULL)
+
+endif
+
 # Programs
 SUBDIRS += \
 	osmo-msc \
-	utils \
 	$(NULL)
diff --git a/src/libmsc/Makefile.am b/src/libmsc/Makefile.am
index d3b6035..de02a17 100644
--- a/src/libmsc/Makefile.am
+++ b/src/libmsc/Makefile.am
@@ -20,9 +20,6 @@
 	$(LIBOSMONETIF_CFLAGS) \
 	$(NULL)
 
-noinst_HEADERS = \
-	$(NULL)
-
 noinst_LIBRARIES = \
 	libmsc.a \
 	$(NULL)
@@ -81,16 +78,3 @@
 	ran_msg_iu.c \
 	$(NULL)
 endif
-
-if BUILD_SMPP
-noinst_HEADERS += \
-	smpp_smsc.h \
-	$(NULL)
-
-libmsc_a_SOURCES += \
-	smpp_smsc.c \
-	smpp_openbsc.c \
-	smpp_vty.c \
-	smpp_utils.c \
-	$(NULL)
-endif
diff --git a/src/libmsc/gsm_04_11.c b/src/libmsc/gsm_04_11.c
index 743e272..adc9d88 100644
--- a/src/libmsc/gsm_04_11.c
+++ b/src/libmsc/gsm_04_11.c
@@ -58,7 +58,7 @@
 #include <osmocom/msc/paging.h>
 
 #ifdef BUILD_SMPP
-#include "smpp_smsc.h"
+#include <osmocom/smpp/smpp_smsc.h>
 #endif
 
 void *tall_gsms_ctx;
@@ -1389,4 +1389,3 @@
 		trans_free(trans);
 	}
 }
-
diff --git a/src/libmsc/smpp_smsc.h b/src/libmsc/smpp_smsc.h
deleted file mode 100644
index 76772a3..0000000
--- a/src/libmsc/smpp_smsc.h
+++ /dev/null
@@ -1,167 +0,0 @@
-#ifndef _SMPP_SMSC_H
-#define _SMPP_SMSC_H
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-#include <osmocom/core/utils.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/write_queue.h>
-#include <osmocom/core/timer.h>
-
-#include <smpp34.h>
-#include <smpp34_structs.h>
-#include <smpp34_params.h>
-
-#define SMPP_SYS_ID_LEN	15
-#define SMPP_PASSWD_LEN	8
-
-#define MODE_7BIT	7
-#define MODE_8BIT	8
-
-struct msc_a;
-
-enum esme_read_state {
-	READ_ST_IN_LEN = 0,
-	READ_ST_IN_MSG = 1,
-};
-
-struct osmo_smpp_acl;
-
-struct osmo_smpp_addr {
-	uint8_t ton;
-	uint8_t npi;
-	char addr[21+1];
-};
-
-struct osmo_esme {
-	struct llist_head list;
-	struct smsc *smsc;
-	struct osmo_smpp_acl *acl;
-	int use;
-
-	struct llist_head smpp_cmd_list;
-
-	uint32_t own_seq_nr;
-
-	struct osmo_wqueue wqueue;
-
-	enum esme_read_state read_state;
-	uint32_t read_len;
-	uint32_t read_idx;
-	struct msgb *read_msg;
-
-	uint8_t smpp_version;
-	char system_id[SMPP_SYS_ID_LEN+1];
-
-	uint8_t bind_flags;
-};
-
-struct osmo_smpp_acl {
-	struct llist_head list;
-	struct smsc *smsc;
-	struct osmo_esme *esme;
-	char *description;
-	char system_id[SMPP_SYS_ID_LEN+1];
-	char passwd[SMPP_PASSWD_LEN+1];
-	int default_route;
-	int deliver_src_imsi;
-	int osmocom_ext;
-	int dcs_transparent;
-	int alert_notifications;
-	struct llist_head route_list;
-};
-
-enum osmo_smpp_rtype {
-	SMPP_ROUTE_NONE,
-	SMPP_ROUTE_PREFIX,
-};
-
-struct osmo_smpp_route {
-	struct llist_head list;	/*!< in acl.route_list */
-	struct llist_head global_list; /*!< in smsc->route_list */
-	struct osmo_smpp_acl *acl;
-	enum osmo_smpp_rtype type;
-	union {
-		struct osmo_smpp_addr prefix;
-	} u;
-};
-
-struct osmo_smpp_cmd {
-	struct llist_head	list;
-	struct vlr_subscr	*vsub;
-	uint32_t		sequence_nr;
-	uint32_t		gsm411_msg_ref;
-	uint8_t			gsm411_trans_id;
-	bool			is_report;
-	struct osmo_timer_list	response_timer;
-};
-
-struct osmo_smpp_cmd *smpp_cmd_find_by_seqnum(struct osmo_esme *esme,
-					      uint32_t sequence_number);
-void smpp_cmd_ack(struct osmo_smpp_cmd *cmd);
-void smpp_cmd_err(struct osmo_smpp_cmd *cmd, uint32_t status);
-void smpp_cmd_flush_pending(struct osmo_esme *esme);
-
-struct smsc {
-	struct osmo_fd listen_ofd;
-	struct llist_head esme_list;
-	struct llist_head acl_list;
-	struct llist_head route_list;
-	char *bind_addr;
-	uint16_t listen_port;
-	char system_id[SMPP_SYS_ID_LEN+1];
-	int accept_all;
-	int smpp_first;
-	struct osmo_smpp_acl *def_route;
-	void *priv;
-};
-
-int smpp_addr_eq(const struct osmo_smpp_addr *a,
-		 const struct osmo_smpp_addr *b);
-
-struct smsc *smpp_smsc_alloc_init(void *ctx);
-int smpp_smsc_conf(struct smsc *smsc, const char *bind_addr, uint16_t port);
-int smpp_smsc_start(struct smsc *smsc, const char *bind_addr, uint16_t port);
-int smpp_smsc_restart(struct smsc *smsc, const char *bind_addr, uint16_t port);
-void smpp_smsc_stop(struct smsc *smsc);
-
-void smpp_esme_get(struct osmo_esme *esme);
-void smpp_esme_put(struct osmo_esme *esme);
-
-int smpp_route(const struct smsc *smsc, const struct osmo_smpp_addr *dest, struct osmo_esme **emse);
-
-struct osmo_smpp_acl *smpp_acl_alloc(struct smsc *smsc, const char *sys_id);
-struct osmo_smpp_acl *smpp_acl_by_system_id(struct smsc *smsc,
-					    const char *sys_id);
-void smpp_acl_delete(struct osmo_smpp_acl *acl);
-
-int smpp_tx_submit_r(struct osmo_esme *esme, uint32_t sequence_nr,
-		     uint32_t command_status, char *msg_id);
-
-int smpp_tx_alert(struct osmo_esme *esme, uint8_t ton, uint8_t npi,
-		  const char *addr, uint8_t avail_status);
-
-int smpp_tx_deliver(struct osmo_esme *esme, struct deliver_sm_t *deliver);
-
-int handle_smpp_submit(struct osmo_esme *esme, struct submit_sm_t *submit,
-			struct submit_sm_resp_t *submit_r);
-
-int smpp_route_pfx_add(struct osmo_smpp_acl *acl,
-		       const struct osmo_smpp_addr *pfx);
-int smpp_route_pfx_del(struct osmo_smpp_acl *acl,
-		       const struct osmo_smpp_addr *pfx);
-
-int smpp_vty_init(void);
-
-int smpp_determine_scheme(uint8_t dcs, uint8_t *data_coding, int *mode);
-
-time_t smpp_parse_time_format(const char *vp, time_t *t_now);
-
-
-struct gsm_sms;
-struct ran_conn;
-
-bool smpp_route_smpp_first();
-int smpp_try_deliver(struct gsm_sms *sms, struct msc_a *msc_a);
-#endif
diff --git a/src/libsmpputil/Makefile.am b/src/libsmpputil/Makefile.am
new file mode 100644
index 0000000..b180ddf
--- /dev/null
+++ b/src/libsmpputil/Makefile.am
@@ -0,0 +1,25 @@
+AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
+AM_CFLAGS= \
+	-Wall \
+	$(LIBOSMOCORE_CFLAGS) \
+	$(LIBOSMOVTY_CFLAGS) \
+	$(LIBOSMOSCCP_CFLAGS) \
+	$(LIBOSMOGSM_CFLAGS) \
+	$(LIBOSMONETIF_CFLAGS) \
+	$(LIBOSMOMGCPCLIENT_CFLAGS) \
+	$(LIBOSMOGSUPCLIENT_CFLAGS) \
+	$(LIBSMPP34_CFLAGS) \
+	$(COVERAGE_CFLAGS) \
+	$(NULL)
+
+noinst_HEADERS = \
+	$(NULL)
+
+noinst_LIBRARIES = libsmpputil.a
+
+libsmpputil_a_SOURCES = \
+	smpp_utils.c \
+	smpp_vty.c \
+	smpp_msc.c \
+	smpp_smsc.c \
+	$(NULL)
diff --git a/src/libmsc/smpp_openbsc.c b/src/libsmpputil/smpp_msc.c
similarity index 99%
rename from src/libmsc/smpp_openbsc.c
rename to src/libsmpputil/smpp_msc.c
index 91666a9..090905a 100644
--- a/src/libmsc/smpp_openbsc.c
+++ b/src/libsmpputil/smpp_msc.c
@@ -48,8 +48,7 @@
 #include <osmocom/msc/gsm_subscriber.h>
 #include <osmocom/msc/vlr.h>
 #include <osmocom/msc/msc_a.h>
-
-#include "smpp_smsc.h"
+#include <osmocom/smpp/smpp_smsc.h>
 
 #define VSUB_USE_SMPP "SMPP"
 #define VSUB_USE_SMPP_CMD "SMPP-cmd"
@@ -862,4 +861,3 @@
 
 	return 0;
 }
-
diff --git a/src/libmsc/smpp_smsc.c b/src/libsmpputil/smpp_smsc.c
similarity index 96%
rename from src/libmsc/smpp_smsc.c
rename to src/libsmpputil/smpp_smsc.c
index da66074..b03f7be 100644
--- a/src/libmsc/smpp_smsc.c
+++ b/src/libsmpputil/smpp_smsc.c
@@ -40,15 +40,9 @@
 #include <osmocom/core/talloc.h>
 #include <osmocom/gsm/protocol/gsm_04_11.h>
 
-#include "smpp_smsc.h"
-
 #include <osmocom/msc/debug.h>
 #include <osmocom/msc/gsm_data.h>
-
-/*! \brief Ugly wrapper. libsmpp34 should do this itself! */
-#define SMPP34_UNPACK(rc, type, str, data, len)		\
-	memset(str, 0, sizeof(*str));			\
-	rc = smpp34_unpack(type, str, data, len)
+#include <osmocom/smpp/smpp_smsc.h>
 
 enum emse_bind {
 	ESME_BIND_RX = 0x01,
@@ -333,18 +327,7 @@
 		return GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
 }
 
-
-/*! \brief initialize the libsmpp34 data structure for a response */
-#define INIT_RESP(type, resp, req) 		{ \
-	memset((resp), 0, sizeof(*(resp)));	  \
-	(resp)->command_length	= 0;		  \
-	(resp)->command_id	= type;		  \
-	(resp)->command_status	= ESME_ROK;	  \
-	(resp)->sequence_number	= (req)->sequence_number;	\
-}
-
 /*! \brief pack a libsmpp34 data strcutrure and send it to the ESME */
-#define PACK_AND_SEND(esme, ptr)	pack_and_send(esme, (ptr)->command_id, ptr)
 static int pack_and_send(struct osmo_esme *esme, uint32_t type, void *ptr)
 {
 	struct msgb *msg;
@@ -394,13 +377,6 @@
 	return PACK_AND_SEND(esme, &nack);
 }
 
-/*! \brief retrieve SMPP command ID from a msgb */
-static inline uint32_t smpp_msgb_cmdid(struct msgb *msg)
-{
-	uint8_t *tmp = msgb_data(msg) + 4;
-	return ntohl(*(uint32_t *)tmp);
-}
-
 /*! \brief retrieve SMPP sequence number from a msgb */
 static inline uint32_t smpp_msgb_seq(struct msgb *msg)
 {
diff --git a/src/libmsc/smpp_utils.c b/src/libsmpputil/smpp_utils.c
similarity index 94%
rename from src/libmsc/smpp_utils.c
rename to src/libsmpputil/smpp_utils.c
index 3c7757b..bada972 100644
--- a/src/libmsc/smpp_utils.c
+++ b/src/libsmpputil/smpp_utils.c
@@ -21,8 +21,16 @@
 
 #include <time.h>
 
-#include "smpp_smsc.h"
 #include <osmocom/core/logging.h>
+#include <osmocom/netif/stream.h>
+#include <osmocom/smpp/smpp_smsc.h>
+
+/*! \brief retrieve SMPP command ID from a msgb */
+uint32_t smpp_msgb_cmdid(struct msgb *msg)
+{
+	uint8_t *tmp = msgb_data(msg) + 4;
+	return ntohl(*(uint32_t *)tmp);
+}
 
 int smpp_determine_scheme(uint8_t dcs, uint8_t *data_coding, int *mode)
 {
diff --git a/src/libmsc/smpp_vty.c b/src/libsmpputil/smpp_vty.c
similarity index 99%
rename from src/libmsc/smpp_vty.c
rename to src/libsmpputil/smpp_vty.c
index da260a8..40514d4 100644
--- a/src/libmsc/smpp_vty.c
+++ b/src/libsmpputil/smpp_vty.c
@@ -34,8 +34,7 @@
 #include <osmocom/core/talloc.h>
 
 #include <osmocom/msc/vty.h>
-
-#include "smpp_smsc.h"
+#include <osmocom/smpp/smpp_smsc.h>
 
 struct smsc *smsc_from_vty(struct vty *v);
 
diff --git a/src/osmo-msc/Makefile.am b/src/osmo-msc/Makefile.am
index cdc3448..0380d5d 100644
--- a/src/osmo-msc/Makefile.am
+++ b/src/osmo-msc/Makefile.am
@@ -43,7 +43,6 @@
 	$(LIBOSMOCTRL_LIBS) \
 	$(LIBOSMOABIS_LIBS) \
 	$(LIBOSMONETIF_LIBS) \
-	$(LIBSMPP34_LIBS) \
 	$(LIBOSMORANAP_LIBS) \
 	$(LIBASN1C_LIBS) \
 	$(LIBOSMOSIGTRAN_LIBS) \
@@ -52,3 +51,12 @@
 	$(LIBSQLITE3_LIBS) \
 	-lsctp \
 	$(NULL)
+
+if BUILD_SMPP
+
+osmo_msc_LDADD += \
+	$(top_builddir)/src/libsmpputil/libsmpputil.a \
+	$(LIBSMPP34_LIBS) \
+	$(NULL)
+
+endif
diff --git a/src/osmo-msc/msc_main.c b/src/osmo-msc/msc_main.c
index bdffb41..4ef5948 100644
--- a/src/osmo-msc/msc_main.c
+++ b/src/osmo-msc/msc_main.c
@@ -60,7 +60,7 @@
 #include <osmocom/ctrl/control_if.h>
 #include <osmocom/ctrl/control_vty.h>
 #include <osmocom/ctrl/ports.h>
-#include <osmocom/msc/smpp.h>
+#include <osmocom/smpp/smpp.h>
 #include <osmocom/sigtran/osmo_ss7.h>
 #include <osmocom/mgcp_client/mgcp_client.h>
 #include <osmocom/msc/sgs_iface.h>
diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am
index cb0faf6..75a2926 100644
--- a/src/utils/Makefile.am
+++ b/src/utils/Makefile.am
@@ -34,12 +34,16 @@
 
 smpp_mirror_CFLAGS = \
 	$(LIBOSMOCORE_CFLAGS) \
+	$(LIBOSMOSCCP_CFLAGS) \
+	$(LIBOSMOMGCPCLIENT_CFLAGS) \
 	$(LIBSMPP34_CFLAGS) \
 	$(NULL)
 
 smpp_mirror_LDADD = \
+	$(top_builddir)/src/libsmpputil/libsmpputil.a \
 	$(LIBOSMOCORE_LIBS) \
 	$(LIBOSMOGSM_LIBS) \
+	$(LIBOSMONETIF_LIBS) \
 	$(LIBSMPP34_LIBS) \
 	$(NULL)
 endif
diff --git a/src/utils/smpp_mirror.c b/src/utils/smpp_mirror.c
index 72d15e3..3593895 100644
--- a/src/utils/smpp_mirror.c
+++ b/src/utils/smpp_mirror.c
@@ -19,18 +19,11 @@
 #include <osmocom/core/write_queue.h>
 
 #include <osmocom/msc/debug.h>
+#include <osmocom/smpp/smpp.h>
 
 /* FIXME: merge with smpp_smsc.c */
-#define SMPP_SYS_ID_LEN	16
-enum esme_read_state {
-	READ_ST_IN_LEN = 0,
-	READ_ST_IN_MSG = 1,
-};
-/* FIXME: merge with smpp_smsc.c */
 
 struct esme {
-	struct osmo_fd ofd;
-
 	uint32_t own_seq_nr;
 
 	struct osmo_wqueue wqueue;
@@ -45,22 +38,6 @@
 };
 
 /* FIXME: merge with smpp_smsc.c */
-#define SMPP34_UNPACK(rc, type, str, data, len)		\
-	memset(str, 0, sizeof(*str));			\
-	rc = smpp34_unpack(type, str, data, len)
-#define INIT_RESP(type, resp, req) 		{ \
-	memset((resp), 0, sizeof(*(resp)));	  \
-	(resp)->command_length	= 0;		  \
-	(resp)->command_id	= type;		  \
-	(resp)->command_status	= ESME_ROK;	  \
-	(resp)->sequence_number	= (req)->sequence_number;	\
-}
-#define PACK_AND_SEND(esme, ptr)	pack_and_send(esme, (ptr)->command_id, ptr)
-static inline uint32_t smpp_msgb_cmdid(struct msgb *msg)
-{
-	uint8_t *tmp = msgb_data(msg) + 4;
-	return ntohl(*(uint32_t *)tmp);
-}
 static uint32_t esme_inc_seq_nr(struct esme *esme)
 {
 	esme->own_seq_nr++;