Gb Proxy: Proper msgb memory management

The old idea was to take a msgb from gbprox_rcvmsg() and then
modify it and finally send it all the way down to nsip_sendmsg()
to the remote peer.

However, this introduces memory management difficulties, as we then
have to distinguish three cases:
 * msgb was sent to a remote peer
 * we sent some error message and need to free the msgb
 * we need to make n-1 copies in case of a BSSVC-RESET from the SGSN

So instead we now simply always copy the message if we pass it on.

All messages received by gbprox_rcvmsg() are msgb_free()d in the very
same routine

All messages allocated by tx2peer() or tx2sgsn() are freed after
nsip_sendmsg()
diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c
index d9639a4..7203a4b 100644
--- a/openbsc/src/gprs/gb_proxy.c
+++ b/openbsc/src/gprs/gb_proxy.c
@@ -119,6 +119,23 @@
 	talloc_free(peer);
 }
 
+/* FIXME: this needs to go to libosmocore/msgb.c */
+static struct msgb *msgb_copy(const struct msgb *msg, const char *name)
+{
+	struct msgb *new_msg;
+
+	new_msg = msgb_alloc(msg->data_len, name);
+	if (!new_msg)
+		return NULL;
+
+	/* copy header */
+	memcpy(new_msg, msg, sizeof(*new_msg));
+	/* copy data */
+	memcpy(new_msg->data, msg->data, new_msg->data_len);
+
+	return new_msg;
+}
+
 /* strip off the NS header */
 static void strip_ns_hdr(struct msgb *msg)
 {
@@ -127,8 +144,12 @@
 }
 
 /* feed a message down the NS-VC associated with the specified peer */
-static int gbprox_relay2sgsn(struct msgb *msg, uint16_t ns_bvci)
+static int gbprox_relay2sgsn(struct msgb *old_msg, uint16_t ns_bvci)
 {
+	/* create a copy of the message so the old one can
+	 * be free()d safely when we return from gbprox_rcvmsg() */
+	struct msgb *msg = msgb_copy(old_msg, "msgb_relay2sgsn");
+
 	DEBUGP(DGPRS, "NSEI=%u proxying BTS->SGSN (NS_BVCI=%u, NSEI=%u)\n",
 		msgb_nsei(msg), ns_bvci, gbcfg.nsip_sgsn_nsei);
 
@@ -141,9 +162,13 @@
 }
 
 /* feed a message down the NS-VC associated with the specified peer */
-static int gbprox_relay2peer(struct msgb *msg, struct gbprox_peer *peer,
+static int gbprox_relay2peer(struct msgb *old_msg, struct gbprox_peer *peer,
 			  uint16_t ns_bvci)
 {
+	/* create a copy of the message so the old one can
+	 * be free()d safely when we return from gbprox_rcvmsg() */
+	struct msgb *msg = msgb_copy(old_msg, "msgb_relay2peer");
+
 	DEBUGP(DGPRS, "NSEI=%u proxying to SGSN->BSS (NS_BVCI=%u, NSEI=%u)\n",
 		msgb_nsei(msg), ns_bvci, peer->nsvc->nsei);
 
@@ -466,6 +491,10 @@
 		}
 	}
 
+	/* We free the original message here, as we will have created a
+	 * copy in case it is forwarded to another peer */
+	msgb_free(msg);
+	
 	return rc;
 }