move various generic IPA related functions to libosmocore

libosmo-abis is about forming A-bis interfaces/lines by means
of E1 or the IPA multiplex (or possibly other link layers).

The IPA multiplex is used in other contexts, such as the Control
interface, or the A interface.  In that context, it makes sense to have
generic IPA related functions in libosmocore.
diff --git a/src/input/ipaccess.c b/src/input/ipaccess.c
index 8ae00d3..b8932a2 100644
--- a/src/input/ipaccess.c
+++ b/src/input/ipaccess.c
@@ -47,6 +47,7 @@
 #include <osmocom/core/socket.h>
 #include <osmocom/abis/ipa.h>
 #include <osmocom/core/backtrace.h>
+#include <osmocom/gsm/ipa.h>
 
 static void *tall_ipa_ctx;
 
@@ -56,250 +57,6 @@
 #define DEFAULT_TCP_KEEPALIVE_INTERVAL     3
 #define DEFAULT_TCP_KEEPALIVE_RETRY_COUNT  10
 
-/*
- * Common propietary IPA messages:
- *      - PONG: in reply to PING.
- *      - ID_REQUEST: first messages once OML has been established.
- *      - ID_ACK: in reply to ID_ACK.
- */
-static const uint8_t ipa_pong_msg[] = {
-	0, 1, IPAC_PROTO_IPACCESS, IPAC_MSGT_PONG
-};
-
-static const uint8_t ipa_id_ack_msg[] = {
-	0, 1, IPAC_PROTO_IPACCESS, IPAC_MSGT_ID_ACK
-};
-
-static const uint8_t ipa_id_req_msg[] = {
-	0, 17, IPAC_PROTO_IPACCESS, IPAC_MSGT_ID_GET,
-	0x01, IPAC_IDTAG_UNIT,
-	0x01, IPAC_IDTAG_MACADDR,
-	0x01, IPAC_IDTAG_LOCATION1,
-	0x01, IPAC_IDTAG_LOCATION2,
-	0x01, IPAC_IDTAG_EQUIPVERS,
-	0x01, IPAC_IDTAG_SWVERSION,
-	0x01, IPAC_IDTAG_UNITNAME,
-	0x01, IPAC_IDTAG_SERNR,
-};
-
-static const char *idtag_names[] = {
-	[IPAC_IDTAG_SERNR]	= "Serial_Number",
-	[IPAC_IDTAG_UNITNAME]	= "Unit_Name",
-	[IPAC_IDTAG_LOCATION1]	= "Location_1",
-	[IPAC_IDTAG_LOCATION2]	= "Location_2",
-	[IPAC_IDTAG_EQUIPVERS]	= "Equipment_Version",
-	[IPAC_IDTAG_SWVERSION]	= "Software_Version",
-	[IPAC_IDTAG_IPADDR]	= "IP_Address",
-	[IPAC_IDTAG_MACADDR]	= "MAC_Address",
-	[IPAC_IDTAG_UNIT]	= "Unit_ID",
-};
-
-const char *ipaccess_idtag_name(uint8_t tag)
-{
-	if (tag >= ARRAY_SIZE(idtag_names))
-		return "unknown";
-
-	return idtag_names[tag];
-}
-
-int ipaccess_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len)
-{
-	uint8_t t_len;
-	uint8_t t_tag;
-	uint8_t *cur = buf;
-
-	memset(dec, 0, sizeof(*dec));
-
-	while (len >= 2) {
-		len -= 2;
-		t_len = *cur++;
-		t_tag = *cur++;
-
-		if (t_len > len + 1) {
-			LOGP(DLMI, LOGL_ERROR, "The tag does not fit: %d\n", t_len);
-			return -EINVAL;
-		}
-
-		DEBUGPC(DLMI, "%s='%s' ", ipaccess_idtag_name(t_tag), cur);
-
-		dec->lv[t_tag].len = t_len;
-		dec->lv[t_tag].val = cur;
-
-		cur += t_len;
-		len -= t_len;
-	}
-	return 0;
-}
-
-int ipaccess_parse_unitid(const char *str, struct ipaccess_unit *unit_data)
-{
-	unsigned long ul;
-	char *endptr;
-	const char *nptr;
-
-	nptr = str;
-	ul = strtoul(nptr, &endptr, 10);
-	if (endptr <= nptr)
-		return -EINVAL;
-	unit_data->site_id = ul & 0xffff;
-
-	if (*endptr++ != '/')
-		return -EINVAL;
-
-	nptr = endptr;
-	ul = strtoul(nptr, &endptr, 10);
-	if (endptr <= nptr)
-		return -EINVAL;
-	unit_data->bts_id = ul & 0xffff;
-
-	if (*endptr++ != '/')
-		return -EINVAL;
-
-	nptr = endptr;
-	ul = strtoul(nptr, &endptr, 10);
-	if (endptr <= nptr)
-		return -EINVAL;
-	unit_data->trx_id = ul & 0xffff;
-
-	return 0;
-}
-
-int ipaccess_tlv_to_unitdata(struct ipaccess_unit *ud,
-			     const struct tlv_parsed *tp)
-{
-	int rc = 0;
-
-	if (TLVP_PRES_LEN(tp, IPAC_IDTAG_SERNR, 1))
-		ud->serno = talloc_strdup(ud, (char *)
-					TLVP_VAL(tp, IPAC_IDTAG_SERNR));
-
-	if (TLVP_PRES_LEN(tp, IPAC_IDTAG_UNITNAME, 1))
-		ud->unit_name = talloc_strdup(ud, (char *)
-					TLVP_VAL(tp, IPAC_IDTAG_UNITNAME));
-
-	if (TLVP_PRES_LEN(tp, IPAC_IDTAG_LOCATION1, 1))
-		ud->location1 = talloc_strdup(ud, (char *)
-					TLVP_VAL(tp, IPAC_IDTAG_LOCATION1));
-
-	if (TLVP_PRES_LEN(tp, IPAC_IDTAG_LOCATION2, 1))
-		ud->location2 = talloc_strdup(ud, (char *)
-					TLVP_VAL(tp, IPAC_IDTAG_LOCATION2));
-
-	if (TLVP_PRES_LEN(tp, IPAC_IDTAG_EQUIPVERS, 1))
-		ud->equipvers = talloc_strdup(ud, (char *)
-					TLVP_VAL(tp, IPAC_IDTAG_EQUIPVERS));
-
-	if (TLVP_PRES_LEN(tp, IPAC_IDTAG_SWVERSION, 1))
-		ud->swversion = talloc_strdup(ud, (char *)
-					TLVP_VAL(tp, IPAC_IDTAG_SWVERSION));
-
-	if (TLVP_PRES_LEN(tp, IPAC_IDTAG_MACADDR, 17)) {
-		rc = osmo_macaddr_parse(ud->mac_addr, (char *)
-					TLVP_VAL(tp, IPAC_IDTAG_MACADDR));
-		if (rc < 0)
-			goto out;
-	}
-
-	if (TLVP_PRES_LEN(tp, IPAC_IDTAG_UNIT, 1))
-		rc = ipaccess_parse_unitid((char *)
-					TLVP_VAL(tp, IPAC_IDTAG_UNIT), ud);
-
-out:
-	return rc;
-}
-
-static int ipaccess_send(int fd, const void *msg, size_t msglen)
-{
-	int ret;
-
-	ret = write(fd, msg, msglen);
-	if (ret < 0)
-		return ret;
-	if (ret < msglen) {
-		LOGP(DLINP, LOGL_ERROR, "ipaccess_send: short write\n");
-		return -EIO;
-	}
-	return ret;
-}
-
-int ipaccess_send_pong(int fd)
-{
-	return ipaccess_send(fd, ipa_pong_msg, sizeof(ipa_pong_msg));
-}
-
-int ipaccess_send_id_ack(int fd)
-{
-	return ipaccess_send(fd, ipa_id_ack_msg, sizeof(ipa_id_ack_msg));
-}
-
-int ipaccess_send_id_req(int fd)
-{
-	return ipaccess_send(fd, ipa_id_req_msg, sizeof(ipa_id_req_msg));
-}
-
-/* base handling of the ip.access protocol */
-int ipaccess_rcvmsg_base(struct msgb *msg, struct osmo_fd *bfd)
-{
-	uint8_t msg_type = *(msg->l2h);
-	int ret;
-
-	switch (msg_type) {
-	case IPAC_MSGT_PING:
-		ret = ipaccess_send_pong(bfd->fd);
-		if (ret < 0) {
-			LOGP(DLINP, LOGL_ERROR, "Cannot send PING "
-			     "message. Reason: %s\n", strerror(errno));
-			break;
-		}
-		ret = 1;
-		break;
-	case IPAC_MSGT_PONG:
-		DEBUGP(DLMI, "PONG!\n");
-		ret = 1;
-		break;
-	case IPAC_MSGT_ID_ACK:
-		DEBUGP(DLMI, "ID_ACK? -> ACK!\n");
-		ret = ipaccess_send_id_ack(bfd->fd);
-		if (ret < 0) {
-			LOGP(DLINP, LOGL_ERROR, "Cannot send ID_ACK "
-			     "message. Reason: %s\n", strerror(errno));
-			break;
-		}
-		ret = 1;
-		break;
-	default:
-		/* This is not an IPA PING, PONG or ID_ACK message */
-		ret = 0;
-		break;
-	}
-	return ret;
-}
-
-/* base handling of the ip.access protocol */
-int ipaccess_rcvmsg_bts_base(struct msgb *msg,
-			     struct osmo_fd *bfd)
-{
-	uint8_t msg_type = *(msg->l2h);
-	int ret = 0;
-
-	switch (msg_type) {
-	case IPAC_MSGT_PING:
-		ret = ipaccess_send_pong(bfd->fd);
-		if (ret < 0) {
-			LOGP(DLINP, LOGL_ERROR, "Cannot send PONG "
-			     "message. Reason: %s\n", strerror(errno));
-		}
-		break;
-	case IPAC_MSGT_PONG:
-		DEBUGP(DLMI, "PONG!\n");
-		break;
-	case IPAC_MSGT_ID_ACK:
-		DEBUGP(DLMI, "ID_ACK\n");
-		break;
-	}
-	return ret;
-}
-
 static int ipaccess_drop(struct osmo_fd *bfd, struct e1inp_line *line)
 {
 	int ret = 1;
@@ -336,7 +93,7 @@
 	int len, ret;
 
 	/* Handle IPA PING, PONG and ID_ACK messages. */
-	ret = ipaccess_rcvmsg_base(msg, bfd);
+	ret = ipa_ccm_rcvmsg_base(msg, bfd);
 	switch(ret) {
 	case -1:
 		/* error in IPA control message handling */
@@ -349,7 +106,7 @@
 		break;
 	default:
 		LOGP(DLINP, LOGL_ERROR, "Unexpected return from "
-					"ipaccess_rcvmsg_base "
+					"ipa_ccm_rcvmsg_base "
 					"(ret=%d)\n", ret);
 		goto err;
 	}
@@ -358,7 +115,7 @@
 	case IPAC_MSGT_ID_RESP:
 		DEBUGP(DLMI, "ID_RESP\n");
 		/* parse tags, search for Unit ID */
-		ret = ipaccess_idtag_parse(&tlvp, (uint8_t *)msg->l2h + 2,
+		ret = ipa_ccm_idtag_parse(&tlvp, (uint8_t *)msg->l2h + 2,
 						msgb_l2len(msg)-2);
 		DEBUGP(DLMI, "\n");
 		if (ret < 0) {
@@ -383,7 +140,7 @@
 		}
 		unitid = (char *) TLVP_VAL(&tlvp, IPAC_IDTAG_UNIT);
 		unitid[len - 1] = '\0';
-		ipaccess_parse_unitid(unitid, &unit_data);
+		ipa_parse_unitid(unitid, &unit_data);
 
 		if (!line->ops->sign_link_up) {
 			LOGP(DLINP, LOGL_ERROR,
@@ -528,25 +285,6 @@
 	return ret;
 }
 
-void ipaccess_prepend_header_ext(struct msgb *msg, int proto)
-{
-	struct ipaccess_head_ext *hh_ext;
-
-	/* prepend the osmo ip.access header extension */
-	hh_ext = (struct ipaccess_head_ext *) msgb_push(msg, sizeof(*hh_ext));
-	hh_ext->proto = proto;
-}
-
-void ipaccess_prepend_header(struct msgb *msg, int proto)
-{
-	struct ipaccess_head *hh;
-
-	/* prepend the ip.access header */
-	hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh));
-	hh->len = htons(msg->len - sizeof(*hh));
-	hh->proto = proto;
-}
-
 static int ts_want_write(struct e1inp_ts *e1i_ts)
 {
 	e1i_ts->driver.ipaccess.fd.when |= BSC_FD_WRITE;
@@ -598,7 +336,7 @@
 	}
 
 	msg->l2h = msg->data;
-	ipaccess_prepend_header(msg, sign_link->tei);
+	ipa_prepend_header(msg, sign_link->tei);
 
 	DEBUGP(DLMI, "TX %u: %s\n", ts_nr, osmo_hexdump(msg->l2h, msgb_l2len(msg)));
 
@@ -752,7 +490,7 @@
 	update_fd_settings(line, bfd->fd);
 
 	/* Request ID. FIXME: request LOCATION, HW/SW VErsion, Unit Name, Serno */
-	ret = ipaccess_send_id_req(bfd->fd);
+	ret = ipa_ccm_send_id_req(bfd->fd);
 	if (ret < 0) {
 		LOGP(DLINP, LOGL_ERROR, "could not send ID REQ. Reason: %s\n",
 			strerror(errno));
@@ -805,7 +543,7 @@
 		goto err_line;
 	}
 	/* Request ID. FIXME: request LOCATION, HW/SW VErsion, Unit Name, Serno */
-	ret = ipaccess_send_id_req(bfd->fd);
+	ret = ipa_ccm_send_id_req(bfd->fd);
 	if (ret < 0) {
 		LOGP(DLINP, LOGL_ERROR, "could not send ID REQ. Reason: %s\n",
 			strerror(errno));
@@ -939,7 +677,7 @@
 		uint8_t msg_type = *(msg->l2h);
 
 		/* ping, pong and acknowledgment cases. */
-		ret = ipaccess_rcvmsg_bts_base(msg, link->ofd);
+		ret = ipa_ccm_rcvmsg_bts_base(msg, link->ofd);
 		if (ret < 0)
 			goto err;
 
@@ -950,8 +688,7 @@
 
 			LOGP(DLINP, LOGL_NOTICE, "received ID get\n");
 			rmsg = ipa_bts_id_resp(dev, data + 1, len - 1);
-			ret = ipaccess_send(link->ofd->fd, rmsg->data,
-						rmsg->len);
+			ret = ipa_send(link->ofd->fd, rmsg->data, rmsg->len);
 			if (ret != rmsg->len) {
 				LOGP(DLINP, LOGL_ERROR, "cannot send ID_RESP "
 				     "message. Reason: %s\n", strerror(errno));
@@ -961,8 +698,7 @@
 
 			/* send ID_ACK. */
 			rmsg = ipa_bts_id_ack();
-			ret = ipaccess_send(link->ofd->fd, rmsg->data,
-						rmsg->len);
+			ret = ipa_send(link->ofd->fd, rmsg->data, rmsg->len);
 			if (ret != rmsg->len) {
 				LOGP(DLINP, LOGL_ERROR, "cannot send ID_ACK "
 				     "message. Reason: %s\n", strerror(errno));