[msgb] Add msgb_reset to reset an existing msgb* to the initial state

The reset is useful if one msgb is supposed to be used over and
over again and is avoiding to use msgb_free,msgb_alloc in the
application code.
diff --git a/openbsc/include/openbsc/msgb.h b/openbsc/include/openbsc/msgb.h
index 5ecac45..ab3c033 100644
--- a/openbsc/include/openbsc/msgb.h
+++ b/openbsc/include/openbsc/msgb.h
@@ -51,6 +51,7 @@
 extern void msgb_free(struct msgb *m);
 extern void msgb_enqueue(struct llist_head *queue, struct msgb *msg);
 extern struct msgb *msgb_dequeue(struct llist_head *queue);
+extern void msgb_reset(struct msgb *m);
 
 #define msgb_l2(m)	((void *)(m->l2h))
 #define msgb_l3(m)	((void *)(m->l3h))
diff --git a/openbsc/src/msgb.c b/openbsc/src/msgb.c
index 52edf2d..edeb975 100644
--- a/openbsc/src/msgb.c
+++ b/openbsc/src/msgb.c
@@ -74,6 +74,26 @@
 	return llist_entry(lh, struct msgb, list);
 }
 
+void msgb_reset(struct msgb *msg)
+{
+	msg->len = 0;
+	msg->len = 0;
+	msg->data = msg->_data;
+
+	msg->head = msg->data;
+	msg->data = msg->data;
+	/* reset tail pointer */
+	msg->tail = msg->data;
+
+	/* reset pointers */
+	msg->bts_link = NULL;
+	msg->trx = NULL;
+	msg->lchan = NULL;
+	msg->l2h = NULL;
+	msg->l3h = NULL;
+	msg->smsh = NULL;
+}
+
 static __attribute__((constructor)) void on_dso_load_trau_msgb(void)
 {
 	tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 1, "msgb");