nat: Attempt to have a single BSC write method

This method currently prepends the IPA header and sends
the data. In the future we might be able to use SCTP for
it.

We have to remove the IPA header from the static messages
for that to work.

This code is untested.
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index d3cd462..62e3c52 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -196,7 +196,6 @@
 /**
  * MGCP/Audio handling
  */
-int bsc_write_mgcp_msg(struct bsc_connection *bsc, struct msgb *msg);
 int bsc_write_mgcp(struct bsc_connection *bsc, const u_int8_t *data, unsigned int length);
 int bsc_mgcp_assign(struct sccp_connections *, struct msgb *msg);
 void bsc_mgcp_clear(struct sccp_connections *);
@@ -212,4 +211,7 @@
 int bsc_mgcp_parse_response(const char *str, int *code, char transaction[60]);
 int bsc_mgcp_extract_ci(const char *resp);
 
+
+int bsc_write(struct bsc_connection *bsc, struct msgb *msg, int id);
+
 #endif
diff --git a/openbsc/src/nat/bsc_mgcp_utils.c b/openbsc/src/nat/bsc_mgcp_utils.c
index 81465ca..a273af4 100644
--- a/openbsc/src/nat/bsc_mgcp_utils.c
+++ b/openbsc/src/nat/bsc_mgcp_utils.c
@@ -177,7 +177,7 @@
 		mgcp_free_endp(mgcp_endp);
 	}
 
-	bsc_write_mgcp_msg(bsc_con, bsc_msg);
+	bsc_write(bsc_con, bsc_msg, NAT_IPAC_PROTO_MGCP);
 	return MGCP_POLICY_DEFER;
 }
 
diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c
index f44cb13..e521516 100644
--- a/openbsc/src/nat/bsc_nat.c
+++ b/openbsc/src/nat/bsc_nat.c
@@ -58,7 +58,7 @@
 
 
 static struct bsc_nat *nat;
-static void bsc_send_data(struct bsc_connection *bsc, const u_int8_t *data, unsigned int length);
+static void bsc_send_data(struct bsc_connection *bsc, const u_int8_t *data, unsigned int length, int);
 static void remove_bsc_connection(struct bsc_connection *connection);
 static void msc_send_reset(struct bsc_msc_connection *con);
 
@@ -93,28 +93,27 @@
 static void send_reset_ack(struct bsc_connection *bsc)
 {
 	static const u_int8_t gsm_reset_ack[] = {
-		0x00, 0x13, 0xfd,
 		0x09, 0x00, 0x03, 0x07, 0x0b, 0x04, 0x43, 0x01,
 		0x00, 0xfe, 0x04, 0x43, 0x5c, 0x00, 0xfe, 0x03,
 		0x00, 0x01, 0x31,
 	};
 
-	bsc_send_data(bsc, gsm_reset_ack, sizeof(gsm_reset_ack));
+	bsc_send_data(bsc, gsm_reset_ack, sizeof(gsm_reset_ack), IPAC_PROTO_SCCP);
 }
 
 static void send_id_ack(struct bsc_connection *bsc)
 {
 	static const u_int8_t id_ack[] = {
-		0, 1, IPAC_PROTO_IPACCESS, IPAC_MSGT_ID_ACK
+		IPAC_MSGT_ID_ACK
 	};
 
-	bsc_send_data(bsc, id_ack, sizeof(id_ack));
+	bsc_send_data(bsc, id_ack, sizeof(id_ack), IPAC_PROTO_IPACCESS);
 }
 
 static void send_id_req(struct bsc_connection *bsc)
 {
 	static const u_int8_t id_req[] = {
-		0, 17, IPAC_PROTO_IPACCESS, IPAC_MSGT_ID_GET,
+		IPAC_MSGT_ID_GET,
 		0x01, IPAC_IDTAG_UNIT,
 		0x01, IPAC_IDTAG_MACADDR,
 		0x01, IPAC_IDTAG_LOCATION1,
@@ -125,7 +124,7 @@
 		0x01, IPAC_IDTAG_SERNR,
 	};
 
-	bsc_send_data(bsc, id_req, sizeof(id_req));
+	bsc_send_data(bsc, id_req, sizeof(id_req), IPAC_PROTO_IPACCESS);
 }
 
 static void nat_send_rlsd(struct sccp_connections *conn)
@@ -180,27 +179,25 @@
 /*
  * Currently we are lacking refcounting so we need to copy each message.
  */
-static void bsc_send_data(struct bsc_connection *bsc, const u_int8_t *data, unsigned int length)
+static void bsc_send_data(struct bsc_connection *bsc, const u_int8_t *data, unsigned int length, int proto)
 {
 	struct msgb *msg;
 
-	if (length > 4096) {
+	if (length > 4096 - 128) {
 		LOGP(DINP, LOGL_ERROR, "Can not send message of that size.\n");
 		return;
 	}
 
-	msg = msgb_alloc(4096, "to-bsc");
+	msg = msgb_alloc_headroom(4096, 128, "to-bsc");
 	if (!msg) {
 		LOGP(DINP, LOGL_ERROR, "Failed to allocate memory for BSC msg.\n");
 		return;
 	}
 
-	msgb_put(msg, length);
+	msg->l2h = msgb_put(msg, length);
 	memcpy(msg->data, data, length);
-	if (write_queue_enqueue(&bsc->write_queue, msg) != 0) {
-		LOGP(DINP, LOGL_ERROR, "Failed to enqueue the write.\n");
-		msgb_free(msg);
-	}
+
+	bsc_write(bsc, msg, proto);
 }
 
 static int forward_sccp_to_bts(struct msgb *msg)
@@ -208,6 +205,7 @@
 	struct sccp_connections *con;
 	struct bsc_connection *bsc;
 	struct bsc_nat_parsed *parsed;
+	int proto;
 
 	/* filter, drop, patch the message? */
 	parsed = bsc_nat_parse(msg);
@@ -219,8 +217,10 @@
 	if (bsc_nat_filter_ipa(DIR_BSC, msg, parsed))
 		goto exit;
 
+	proto = parsed->ipa_proto;
+
 	/* Route and modify the SCCP packet */
-	if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
+	if (proto == IPAC_PROTO_SCCP) {
 		switch (parsed->sccp_type) {
 		case SCCP_MSG_TYPE_UDT:
 			/* forward UDT messages to every BSC */
@@ -266,7 +266,7 @@
 		return -1;
 	}
 
-	bsc_send_data(con->bsc, msg->data, msg->len);
+	bsc_send_data(con->bsc, msg->l2h, msgb_l2len(msg), proto);
 	return 0;
 
 send_to_all:
@@ -278,7 +278,7 @@
 	if (parsed->ipa_proto == IPAC_PROTO_SCCP && parsed->gsm_type == BSS_MAP_MSG_PAGING) {
 		bsc = bsc_nat_find_bsc(nat, msg);
 		if (bsc)
-			bsc_send_data(bsc, msg->data, msg->len);
+			bsc_send_data(bsc, msg->l2h, msgb_l2len(msg), parsed->ipa_proto);
 		else
 			LOGP(DNAT, LOGL_ERROR, "Could not determine BSC for paging.\n");
 
@@ -289,7 +289,7 @@
 		if (!bsc->authenticated)
 			continue;
 
-		bsc_send_data(bsc, msg->data, msg->len);
+		bsc_send_data(bsc, msg->l2h, msgb_l2len(msg), parsed->ipa_proto);
 	}
 
 exit:
diff --git a/openbsc/src/nat/bsc_nat_utils.c b/openbsc/src/nat/bsc_nat_utils.c
index eddcaff..3307e68 100644
--- a/openbsc/src/nat/bsc_nat_utils.c
+++ b/openbsc/src/nat/bsc_nat_utils.c
@@ -146,13 +146,13 @@
 	msg->l3h = msgb_put(msg, length);
 	memcpy(msg->l3h, data, length);
 
-        return bsc_write_mgcp_msg(bsc, msg);
+        return bsc_write(bsc, msg, NAT_IPAC_PROTO_MGCP);
 }
 
-int bsc_write_mgcp_msg(struct bsc_connection *bsc, struct msgb *msg)
+int bsc_write(struct bsc_connection *bsc, struct msgb *msg, int proto)
 {
 	/* prepend the header */
-	ipaccess_prepend_header(msg, NAT_IPAC_PROTO_MGCP);
+	ipaccess_prepend_header(msg, proto);
 
 	if (write_queue_enqueue(&bsc->write_queue, msg) != 0) {
 		LOGP(DINP, LOGL_ERROR, "Failed to enqueue the write.\n");