include: reorganize headers file to include/osmocom/[gsm|core]

This patch moves all GSM-specific definitions to include/osmocom/gsm.
Moreover, the headers in include/osmocore/ have been moved to
include/osmocom/core.

This has been proposed by Harald Welte and Sylvain Munaunt.

Tested with `make distcheck'.

Signed-off-by: Pablo Neira Ayuso <pablo@gnumonks.org>
diff --git a/include/osmocom/core/Makefile.am b/include/osmocom/core/Makefile.am
new file mode 100644
index 0000000..6109f47
--- /dev/null
+++ b/include/osmocom/core/Makefile.am
@@ -0,0 +1,12 @@
+osmocore_HEADERS = signal.h linuxlist.h timer.h select.h msgb.h bits.h \
+		   bitvec.h statistics.h utils.h \
+		   gsmtap.h write_queue.h \
+		   logging.h rate_ctr.h gsmtap_util.h \
+		   plugin.h crc16.h panic.h process.h msgfile.h \
+		   backtrace.h
+
+if ENABLE_TALLOC
+osmocore_HEADERS += talloc.h
+endif
+
+osmocoredir = $(includedir)/osmocom/core
diff --git a/include/osmocom/core/backtrace.h b/include/osmocom/core/backtrace.h
new file mode 100644
index 0000000..bbbb2c2
--- /dev/null
+++ b/include/osmocom/core/backtrace.h
@@ -0,0 +1,6 @@
+#ifndef _OSMO_BACKTRACE_H_
+#define _OSMO_BACKTRACE_H_
+
+void generate_backtrace();
+
+#endif
diff --git a/include/osmocom/core/bits.h b/include/osmocom/core/bits.h
new file mode 100644
index 0000000..8d4a078
--- /dev/null
+++ b/include/osmocom/core/bits.h
@@ -0,0 +1,45 @@
+#ifndef _OSMO_BITS_H
+#define _OSMO_BITS_H
+
+#include <stdint.h>
+
+typedef uint8_t sbit_t;		/* soft bit (-127...127) */
+typedef uint8_t ubit_t;		/* unpacked bit (0 or 1) */
+typedef uint8_t pbit_t;		/* packed bis (8 bits in a byte) */
+
+/*
+   NOTE on the endianess of pbit_t:
+   Bits in a pbit_t are ordered MSB first, i.e. 0x80 is the first bit.
+   Bit i in a pbit_t array is array[i/8] & (1<<(7-i%8))
+*/
+
+/* determine how many bytes we would need for 'num_bits' packed bits */
+static inline unsigned int osmo_pbit_bytesize(unsigned int num_bits)
+{
+	unsigned int pbit_bytesize = num_bits / 8;
+
+	if (num_bits % 8)
+		pbit_bytesize++;
+
+	return pbit_bytesize;
+}
+
+/* convert unpacked bits to packed bits, return length in bytes */
+int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits);
+
+/* convert packed bits to unpacked bits, return length in bytes */
+int osmo_pbit2ubit(ubit_t *out, const pbit_t *in, unsigned int num_bits);
+
+/* convert unpacked bits to packed bits (extended options but slower),
+ * return length in bytes (max written ofs of output buffer + 1) */
+int osmo_ubit2pbit_ext(pbit_t *out, unsigned int out_ofs,
+                       const ubit_t *in, unsigned int in_ofs,
+                       unsigned int num_bits, int lsb_mode);
+
+/* convert packed bits to unpacked bits (extended options but slower),
+ * return length in bytes (max written ofs of output buffer + 1) */
+int osmo_pbit2ubit_ext(ubit_t *out, unsigned int out_ofs,
+                       const pbit_t *in, unsigned int in_ofs,
+                       unsigned int num_bits, int lsb_mode);
+
+#endif
diff --git a/include/osmocom/core/bitvec.h b/include/osmocom/core/bitvec.h
new file mode 100644
index 0000000..42977fb
--- /dev/null
+++ b/include/osmocom/core/bitvec.h
@@ -0,0 +1,75 @@
+#ifndef _BITVEC_H
+#define _BITVEC_H
+
+/* bit vector utility routines */
+
+/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+
+/* In GSM mac blocks, every bit can be 0 or 1, or L or H.  L/H are
+ * defined relative to the 0x2b padding pattern */
+enum bit_value {
+	ZERO	= 0,
+	ONE	= 1,
+	L	= 2,
+	H	= 3,
+};
+
+struct bitvec {
+	unsigned int cur_bit;	/* curser to the next unused bit */
+	unsigned int data_len;	/* length of data array in bytes */
+	uint8_t *data;		/* pointer to data array */
+};
+
+/* check if the bit is 0 or 1 for a given position inside a bitvec */
+enum bit_value bitvec_get_bit_pos(const struct bitvec *bv, unsigned int bitnr);
+
+/* check if the bit is L or H for a given position inside a bitvec */
+enum bit_value bitvec_get_bit_pos_high(const struct bitvec *bv,
+					unsigned int bitnr);
+
+/* get the Nth set bit inside the bit vector */
+unsigned int bitvec_get_nth_set_bit(const struct bitvec *bv, unsigned int n);
+
+/* Set a bit at given position */
+int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnum,
+			enum bit_value bit);
+
+/* Set the next bit in the vector */
+int bitvec_set_bit(struct bitvec *bv, enum bit_value bit);
+
+/* get the next bit (low/high) inside a bitvec */
+int bitvec_get_bit_high(struct bitvec *bv);
+
+/* Set multiple bits at the current position */
+int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, int count);
+
+/* Add an unsigned integer (of length count bits) to current position */
+int bitvec_set_uint(struct bitvec *bv, unsigned int in, int count);
+
+/* get multiple bits (based on numeric value) from current pos */
+int bitvec_get_uint(struct bitvec *bv, int num_bits);
+
+
+/* Pad the bit vector up to a certain bit position */
+int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit);
+
+#endif /* _BITVEC_H */
diff --git a/include/osmocom/core/crc16.h b/include/osmocom/core/crc16.h
new file mode 100644
index 0000000..7a51249
--- /dev/null
+++ b/include/osmocom/core/crc16.h
@@ -0,0 +1,34 @@
+/*
+ * This was copied from the linux kernel and adjusted for our types.
+ */
+/*
+ *	crc16.h - CRC-16 routine
+ *
+ * Implements the standard CRC-16:
+ *   Width 16
+ *   Poly  0x8005 (x^16 + x^15 + x^2 + 1)
+ *   Init  0
+ *
+ * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#ifndef __CRC16_H
+#define __CRC16_H
+
+#include <stdint.h>
+
+#include <sys/types.h>
+
+extern uint16_t const crc16_table[256];
+
+extern uint16_t crc16(uint16_t crc, const uint8_t *buffer, size_t len);
+
+static inline uint16_t crc16_byte(uint16_t crc, const uint8_t data)
+{
+	return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff];
+}
+
+#endif /* __CRC16_H */
diff --git a/include/osmocom/core/gsmtap.h b/include/osmocom/core/gsmtap.h
new file mode 100644
index 0000000..236b25a
--- /dev/null
+++ b/include/osmocom/core/gsmtap.h
@@ -0,0 +1,89 @@
+#ifndef _GSMTAP_H
+#define _GSMTAP_H
+
+/* gsmtap header, pseudo-header in front of the actua GSM payload */
+
+/* GSMTAP is a generic header format for GSM protocol captures,
+ * it uses the IANA-assigned UDP port number 4729 and carries
+ * payload in various formats of GSM interfaces such as Um MAC
+ * blocks or Um bursts.
+ *
+ * Example programs generating GSMTAP data are airprobe
+ * (http://airprobe.org/) or OsmocomBB (http://bb.osmocom.org/)
+ */
+
+#include <stdint.h>
+
+#define GSMTAP_VERSION		0x02
+
+#define GSMTAP_TYPE_UM		0x01
+#define GSMTAP_TYPE_ABIS	0x02
+#define GSMTAP_TYPE_UM_BURST	0x03	/* raw burst bits */
+#define GSMTAP_TYPE_SIM		0x04
+#define GSMTAP_TYPE_TETRA_I1		0x05	/* tetra air interface */
+#define GSMTAP_TYPE_TETRA_I1_BURST	0x06	/* tetra air interface */
+
+/* sub-types for TYPE_UM_BURST */
+#define GSMTAP_BURST_UNKNOWN		0x00
+#define GSMTAP_BURST_FCCH		0x01
+#define GSMTAP_BURST_PARTIAL_SCH	0x02
+#define GSMTAP_BURST_SCH		0x03
+#define GSMTAP_BURST_CTS_SCH		0x04
+#define GSMTAP_BURST_COMPACT_SCH	0x05
+#define GSMTAP_BURST_NORMAL		0x06
+#define GSMTAP_BURST_DUMMY		0x07
+#define GSMTAP_BURST_ACCESS		0x08
+#define GSMTAP_BURST_NONE		0x09
+
+/* sub-types for TYPE_UM */
+#define GSMTAP_CHANNEL_UNKNOWN	0x00
+#define GSMTAP_CHANNEL_BCCH	0x01
+#define GSMTAP_CHANNEL_CCCH	0x02
+#define GSMTAP_CHANNEL_RACH	0x03
+#define GSMTAP_CHANNEL_AGCH	0x04
+#define GSMTAP_CHANNEL_PCH	0x05
+#define GSMTAP_CHANNEL_SDCCH	0x06
+#define GSMTAP_CHANNEL_SDCCH4	0x07
+#define GSMTAP_CHANNEL_SDCCH8	0x08
+#define GSMTAP_CHANNEL_TCH_F	0x09
+#define GSMTAP_CHANNEL_TCH_H	0x0a
+#define GSMTAP_CHANNEL_ACCH	0x80
+
+/* sub-types for TYPE_TETRA_AIR */
+#define GSMTAP_TETRA_BSCH	0x01
+#define GSMTAP_TETRA_AACH	0x02
+#define GSMTAP_TETRA_SCH_HU	0x03
+#define GSMTAP_TETRA_SCH_HD	0x04
+#define GSMTAP_TETRA_SCH_F	0x05
+#define GSMTAP_TETRA_BNCH	0x06
+#define GSMTAP_TETRA_STCH	0x07
+#define GSMTAP_TETRA_TCH_F	0x08
+
+/* flags for the ARFCN */
+#define GSMTAP_ARFCN_F_PCS	0x8000
+#define GSMTAP_ARFCN_F_UPLINK	0x4000
+#define GSMTAP_ARFCN_MASK	0x3fff
+
+/* IANA-assigned well-known UDP port for GSMTAP messages */
+#define GSMTAP_UDP_PORT			4729
+
+struct gsmtap_hdr {
+	uint8_t version;	/* version, set to 0x01 currently */
+	uint8_t hdr_len;	/* length in number of 32bit words */
+	uint8_t type;		/* see GSMTAP_TYPE_* */
+	uint8_t timeslot;	/* timeslot (0..7 on Um) */
+
+	uint16_t arfcn;		/* ARFCN (frequency) */
+	int8_t signal_dbm;	/* signal level in dBm */
+	int8_t snr_db;		/* signal/noise ratio in dB */
+
+	uint32_t frame_number;	/* GSM Frame Number (FN) */
+
+	uint8_t sub_type;	/* Type of burst/channel, see above */
+	uint8_t antenna_nr;	/* Antenna Number */
+	uint8_t sub_slot;	/* sub-slot within timeslot */
+	uint8_t res;		/* reserved for future use (RFU) */
+
+} __attribute__((packed));
+
+#endif /* _GSMTAP_H */
diff --git a/include/osmocom/core/gsmtap_util.h b/include/osmocom/core/gsmtap_util.h
new file mode 100644
index 0000000..9644944
--- /dev/null
+++ b/include/osmocom/core/gsmtap_util.h
@@ -0,0 +1,21 @@
+#ifndef _GSMTAP_UTIL_H
+#define _GSMTAP_UTIL_H
+
+#include <stdint.h>
+
+/* convert RSL channel number to GSMTAP channel type */
+uint8_t chantype_rsl2gsmtap(uint8_t rsl_chantype, uint8_t rsl_link_id);
+
+/* receive a message from L1/L2 and put it in GSMTAP */
+struct msgb *gsmtap_makemsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type,
+			    uint8_t ss, uint32_t fn, int8_t signal_dbm,
+			    uint8_t snr, const uint8_t *data, unsigned int len);
+
+/* receive a message from L1/L2 and put it in GSMTAP */
+int gsmtap_sendmsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type, uint8_t ss,
+		   uint32_t fn, int8_t signal_dbm, uint8_t snr,
+		   const uint8_t *data, unsigned int len);
+
+int gsmtap_init(uint32_t dst_ip);
+
+#endif /* _GSMTAP_UTIL_H */
diff --git a/include/osmocom/core/linuxlist.h b/include/osmocom/core/linuxlist.h
new file mode 100644
index 0000000..fb99c5e
--- /dev/null
+++ b/include/osmocom/core/linuxlist.h
@@ -0,0 +1,360 @@
+#ifndef _LINUX_LLIST_H
+#define _LINUX_LLIST_H
+
+#include <stddef.h>
+
+#ifndef inline
+#define inline __inline__
+#endif
+
+static inline void prefetch(const void *x) {;}
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ *
+ * @ptr:	the pointer to the member.
+ * @type:	the type of the container struct this is embedded in.
+ * @member:	the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({			\
+        const typeof( ((type *)0)->member ) *__mptr = (typeof( ((type *)0)->member ) *)(ptr);	\
+        (type *)( (char *)__mptr - offsetof(type, member) );})
+
+
+/*
+ * These are non-NULL pointers that will result in page faults
+ * under normal circumstances, used to verify that nobody uses
+ * non-initialized llist entries.
+ */
+#define LLIST_POISON1  ((void *) 0x00100100)
+#define LLIST_POISON2  ((void *) 0x00200200)
+
+/*
+ * Simple doubly linked llist implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole llists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct llist_head {
+	struct llist_head *next, *prev;
+};
+
+#define LLIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LLIST_HEAD(name) \
+	struct llist_head name = LLIST_HEAD_INIT(name)
+
+#define INIT_LLIST_HEAD(ptr) do { \
+	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries. 
+ *
+ * This is only for internal llist manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __llist_add(struct llist_head *_new,
+			      struct llist_head *prev,
+			      struct llist_head *next)
+{
+	next->prev = _new;
+	_new->next = next;
+	_new->prev = prev;
+	prev->next = _new;
+}
+
+/**
+ * llist_add - add a new entry
+ * @new: new entry to be added
+ * @head: llist head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void llist_add(struct llist_head *_new, struct llist_head *head)
+{
+	__llist_add(_new, head, head->next);
+}
+
+/**
+ * llist_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: llist head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void llist_add_tail(struct llist_head *_new, struct llist_head *head)
+{
+	__llist_add(_new, head->prev, head);
+}
+
+/*
+ * Delete a llist entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal llist manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __llist_del(struct llist_head * prev, struct llist_head * next)
+{
+	next->prev = prev;
+	prev->next = next;
+}
+
+/**
+ * llist_del - deletes entry from llist.
+ * @entry: the element to delete from the llist.
+ * Note: llist_empty on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void llist_del(struct llist_head *entry)
+{
+	__llist_del(entry->prev, entry->next);
+	entry->next = (struct llist_head *)LLIST_POISON1;
+	entry->prev = (struct llist_head *)LLIST_POISON2;
+}
+
+/**
+ * llist_del_init - deletes entry from llist and reinitialize it.
+ * @entry: the element to delete from the llist.
+ */
+static inline void llist_del_init(struct llist_head *entry)
+{
+	__llist_del(entry->prev, entry->next);
+	INIT_LLIST_HEAD(entry); 
+}
+
+/**
+ * llist_move - delete from one llist and add as another's head
+ * @llist: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void llist_move(struct llist_head *llist, struct llist_head *head)
+{
+        __llist_del(llist->prev, llist->next);
+        llist_add(llist, head);
+}
+
+/**
+ * llist_move_tail - delete from one llist and add as another's tail
+ * @llist: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void llist_move_tail(struct llist_head *llist,
+				  struct llist_head *head)
+{
+        __llist_del(llist->prev, llist->next);
+        llist_add_tail(llist, head);
+}
+
+/**
+ * llist_empty - tests whether a llist is empty
+ * @head: the llist to test.
+ */
+static inline int llist_empty(const struct llist_head *head)
+{
+	return head->next == head;
+}
+
+static inline void __llist_splice(struct llist_head *llist,
+				 struct llist_head *head)
+{
+	struct llist_head *first = llist->next;
+	struct llist_head *last = llist->prev;
+	struct llist_head *at = head->next;
+
+	first->prev = head;
+	head->next = first;
+
+	last->next = at;
+	at->prev = last;
+}
+
+/**
+ * llist_splice - join two llists
+ * @llist: the new llist to add.
+ * @head: the place to add it in the first llist.
+ */
+static inline void llist_splice(struct llist_head *llist, struct llist_head *head)
+{
+	if (!llist_empty(llist))
+		__llist_splice(llist, head);
+}
+
+/**
+ * llist_splice_init - join two llists and reinitialise the emptied llist.
+ * @llist: the new llist to add.
+ * @head: the place to add it in the first llist.
+ *
+ * The llist at @llist is reinitialised
+ */
+static inline void llist_splice_init(struct llist_head *llist,
+				    struct llist_head *head)
+{
+	if (!llist_empty(llist)) {
+		__llist_splice(llist, head);
+		INIT_LLIST_HEAD(llist);
+	}
+}
+
+/**
+ * llist_entry - get the struct for this entry
+ * @ptr:	the &struct llist_head pointer.
+ * @type:	the type of the struct this is embedded in.
+ * @member:	the name of the llist_struct within the struct.
+ */
+#define llist_entry(ptr, type, member) \
+	container_of(ptr, type, member)
+
+/**
+ * llist_for_each	-	iterate over a llist
+ * @pos:	the &struct llist_head to use as a loop counter.
+ * @head:	the head for your llist.
+ */
+#define llist_for_each(pos, head) \
+	for (pos = (head)->next, prefetch(pos->next); pos != (head); \
+        	pos = pos->next, prefetch(pos->next))
+
+/**
+ * __llist_for_each	-	iterate over a llist
+ * @pos:	the &struct llist_head to use as a loop counter.
+ * @head:	the head for your llist.
+ *
+ * This variant differs from llist_for_each() in that it's the
+ * simplest possible llist iteration code, no prefetching is done.
+ * Use this for code that knows the llist to be very short (empty
+ * or 1 entry) most of the time.
+ */
+#define __llist_for_each(pos, head) \
+	for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * llist_for_each_prev	-	iterate over a llist backwards
+ * @pos:	the &struct llist_head to use as a loop counter.
+ * @head:	the head for your llist.
+ */
+#define llist_for_each_prev(pos, head) \
+	for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
+        	pos = pos->prev, prefetch(pos->prev))
+        	
+/**
+ * llist_for_each_safe	-	iterate over a llist safe against removal of llist entry
+ * @pos:	the &struct llist_head to use as a loop counter.
+ * @n:		another &struct llist_head to use as temporary storage
+ * @head:	the head for your llist.
+ */
+#define llist_for_each_safe(pos, n, head) \
+	for (pos = (head)->next, n = pos->next; pos != (head); \
+		pos = n, n = pos->next)
+
+/**
+ * llist_for_each_entry	-	iterate over llist of given type
+ * @pos:	the type * to use as a loop counter.
+ * @head:	the head for your llist.
+ * @member:	the name of the llist_struct within the struct.
+ */
+#define llist_for_each_entry(pos, head, member)				\
+	for (pos = llist_entry((head)->next, typeof(*pos), member),	\
+		     prefetch(pos->member.next);			\
+	     &pos->member != (head); 					\
+	     pos = llist_entry(pos->member.next, typeof(*pos), member),	\
+		     prefetch(pos->member.next))
+
+/**
+ * llist_for_each_entry_reverse - iterate backwards over llist of given type.
+ * @pos:	the type * to use as a loop counter.
+ * @head:	the head for your llist.
+ * @member:	the name of the llist_struct within the struct.
+ */
+#define llist_for_each_entry_reverse(pos, head, member)			\
+	for (pos = llist_entry((head)->prev, typeof(*pos), member),	\
+		     prefetch(pos->member.prev);			\
+	     &pos->member != (head); 					\
+	     pos = llist_entry(pos->member.prev, typeof(*pos), member),	\
+		     prefetch(pos->member.prev))
+
+/**
+ * llist_for_each_entry_continue -	iterate over llist of given type
+ *			continuing after existing point
+ * @pos:	the type * to use as a loop counter.
+ * @head:	the head for your llist.
+ * @member:	the name of the llist_struct within the struct.
+ */
+#define llist_for_each_entry_continue(pos, head, member) 		\
+	for (pos = llist_entry(pos->member.next, typeof(*pos), member),	\
+		     prefetch(pos->member.next);			\
+	     &pos->member != (head);					\
+	     pos = llist_entry(pos->member.next, typeof(*pos), member),	\
+		     prefetch(pos->member.next))
+
+/**
+ * llist_for_each_entry_safe - iterate over llist of given type safe against removal of llist entry
+ * @pos:	the type * to use as a loop counter.
+ * @n:		another type * to use as temporary storage
+ * @head:	the head for your llist.
+ * @member:	the name of the llist_struct within the struct.
+ */
+#define llist_for_each_entry_safe(pos, n, head, member)			\
+	for (pos = llist_entry((head)->next, typeof(*pos), member),	\
+		n = llist_entry(pos->member.next, typeof(*pos), member);	\
+	     &pos->member != (head); 					\
+	     pos = n, n = llist_entry(n->member.next, typeof(*n), member))
+
+/**
+ * llist_for_each_rcu	-	iterate over an rcu-protected llist
+ * @pos:	the &struct llist_head to use as a loop counter.
+ * @head:	the head for your llist.
+ */
+#define llist_for_each_rcu(pos, head) \
+	for (pos = (head)->next, prefetch(pos->next); pos != (head); \
+        	pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next))
+        	
+#define __llist_for_each_rcu(pos, head) \
+	for (pos = (head)->next; pos != (head); \
+        	pos = pos->next, ({ smp_read_barrier_depends(); 0;}))
+        	
+/**
+ * llist_for_each_safe_rcu	-	iterate over an rcu-protected llist safe
+ *					against removal of llist entry
+ * @pos:	the &struct llist_head to use as a loop counter.
+ * @n:		another &struct llist_head to use as temporary storage
+ * @head:	the head for your llist.
+ */
+#define llist_for_each_safe_rcu(pos, n, head) \
+	for (pos = (head)->next, n = pos->next; pos != (head); \
+		pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next)
+
+/**
+ * llist_for_each_entry_rcu	-	iterate over rcu llist of given type
+ * @pos:	the type * to use as a loop counter.
+ * @head:	the head for your llist.
+ * @member:	the name of the llist_struct within the struct.
+ */
+#define llist_for_each_entry_rcu(pos, head, member)			\
+	for (pos = llist_entry((head)->next, typeof(*pos), member),	\
+		     prefetch(pos->member.next);			\
+	     &pos->member != (head); 					\
+	     pos = llist_entry(pos->member.next, typeof(*pos), member),	\
+		     ({ smp_read_barrier_depends(); 0;}),		\
+		     prefetch(pos->member.next))
+
+
+/**
+ * llist_for_each_continue_rcu	-	iterate over an rcu-protected llist 
+ *			continuing after existing point.
+ * @pos:	the &struct llist_head to use as a loop counter.
+ * @head:	the head for your llist.
+ */
+#define llist_for_each_continue_rcu(pos, head) \
+	for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \
+        	(pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next))
+
+
+#endif
diff --git a/include/osmocom/core/logging.h b/include/osmocom/core/logging.h
new file mode 100644
index 0000000..db02940
--- /dev/null
+++ b/include/osmocom/core/logging.h
@@ -0,0 +1,154 @@
+#ifndef _OSMOCORE_LOGGING_H
+#define _OSMOCORE_LOGGING_H
+
+#include <stdio.h>
+#include <stdint.h>
+#include <osmocom/core/linuxlist.h>
+
+#define LOG_MAX_CATEGORY	32
+#define LOG_MAX_CTX		8
+#define LOG_MAX_FILTERS	8
+
+#define DEBUG
+
+#ifdef DEBUG
+#define DEBUGP(ss, fmt, args...) logp(ss, __FILE__, __LINE__, 0, fmt, ## args)
+#define DEBUGPC(ss, fmt, args...) logp(ss, __FILE__, __LINE__, 1, fmt, ## args)
+#else
+#define DEBUGP(xss, fmt, args...)
+#define DEBUGPC(ss, fmt, args...)
+#endif
+
+
+void logp(unsigned int subsys, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6)));
+
+/* new logging interface */
+#define LOGP(ss, level, fmt, args...) \
+	logp2(ss, level, __FILE__, __LINE__, 0, fmt, ##args)
+#define LOGPC(ss, level, fmt, args...) \
+	logp2(ss, level, __FILE__, __LINE__, 1, fmt, ##args)
+
+/* different levels */
+#define LOGL_DEBUG	1	/* debugging information */
+#define LOGL_INFO	3
+#define LOGL_NOTICE	5	/* abnormal/unexpected condition */
+#define LOGL_ERROR	7	/* error condition, requires user action */
+#define LOGL_FATAL	8	/* fatal, program aborted */
+
+#define LOG_FILTER_ALL	0x0001
+
+struct log_category {
+	uint8_t loglevel;
+	uint8_t enabled;
+};
+
+struct log_info_cat {
+	const char *name;
+	const char *color;
+	const char *description;
+	uint8_t loglevel;
+	uint8_t enabled;
+};
+
+/* log context information, passed to filter */
+struct log_context {
+	void *ctx[LOG_MAX_CTX+1];
+};
+
+struct log_target;
+
+typedef int log_filter(const struct log_context *ctx,
+		       struct log_target *target);
+
+struct log_info {
+	/* filter callback function */
+	log_filter *filter_fn;
+
+	/* per-category information */
+	const struct log_info_cat *cat;
+	unsigned int num_cat;
+};
+
+enum log_target_type {
+	LOG_TGT_TYPE_VTY,
+	LOG_TGT_TYPE_SYSLOG,
+	LOG_TGT_TYPE_FILE,
+	LOG_TGT_TYPE_STDERR,
+};
+
+struct log_target {
+        struct llist_head entry;
+
+	int filter_map;
+	void *filter_data[LOG_MAX_FILTERS+1];
+
+	struct log_category categories[LOG_MAX_CATEGORY+1];
+	uint8_t loglevel;
+	int use_color:1;
+	int print_timestamp:1;
+
+	enum log_target_type type;
+
+	union {
+		struct {
+			FILE *out;
+			const char *fname;
+		} tgt_file;
+
+		struct {
+			int priority;
+			int facility;
+		} tgt_syslog;
+
+		struct {
+			void *vty;
+		} tgt_vty;
+	};
+
+        void (*output) (struct log_target *target, unsigned int level,
+			const char *string);
+};
+
+/* use the above macros */
+void logp2(unsigned int subsys, unsigned int level, char *file,
+	   int line, int cont, const char *format, ...)
+				__attribute__ ((format (printf, 6, 7)));
+void log_init(const struct log_info *cat);
+
+/* context management */
+void log_reset_context(void);
+int log_set_context(uint8_t ctx, void *value);
+
+/* filter on the targets */
+void log_set_all_filter(struct log_target *target, int);
+
+void log_set_use_color(struct log_target *target, int);
+void log_set_print_timestamp(struct log_target *target, int);
+void log_set_log_level(struct log_target *target, int log_level);
+void log_parse_category_mask(struct log_target *target, const char* mask);
+int log_parse_level(const char *lvl);
+const char *log_level_str(unsigned int lvl);
+int log_parse_category(const char *category);
+void log_set_category_filter(struct log_target *target, int category,
+			       int enable, int level);
+
+/* management of the targets */
+struct log_target *log_target_create(void);
+void log_target_destroy(struct log_target *target);
+struct log_target *log_target_create_stderr(void);
+struct log_target *log_target_create_file(const char *fname);
+struct log_target *log_target_create_syslog(const char *ident, int option,
+					    int facility);
+int log_target_file_reopen(struct log_target *tgt);
+
+void log_add_target(struct log_target *target);
+void log_del_target(struct log_target *target);
+
+/* Generate command string for VTY use */
+const char *log_vty_command_string(const struct log_info *info);
+const char *log_vty_command_description(const struct log_info *info);
+
+struct log_target *log_target_find(int type, const char *fname);
+extern struct llist_head osmo_log_target_list;
+
+#endif /* _OSMOCORE_LOGGING_H */
diff --git a/include/osmocom/core/msgb.h b/include/osmocom/core/msgb.h
new file mode 100644
index 0000000..57b5d7f
--- /dev/null
+++ b/include/osmocom/core/msgb.h
@@ -0,0 +1,197 @@
+#ifndef _MSGB_H
+#define _MSGB_H
+
+/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdint.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/utils.h>
+
+#define MSGB_DEBUG
+
+struct msgb {
+	struct llist_head list;
+
+	/* Part of which TRX logical channel we were received / transmitted */
+	/* FIXME: move them into the control buffer */
+	struct gsm_bts_trx *trx;
+	struct gsm_lchan *lchan;
+
+	/* the Layer1 header (if any) */
+	unsigned char *l1h;
+	/* the A-bis layer 2 header: OML, RSL(RLL), NS */
+	unsigned char *l2h;
+	/* the layer 3 header. For OML: FOM; RSL: 04.08; GPRS: BSSGP */
+	unsigned char *l3h;
+	/* the layer 4 header */
+	unsigned char *l4h;
+
+	/* the 'control buffer', large enough to contain 5 pointers */
+	unsigned long cb[5];
+
+	uint16_t data_len;
+	uint16_t len;
+
+	unsigned char *head;
+	unsigned char *tail;
+	unsigned char *data;
+	unsigned char _data[0];
+};
+
+extern struct msgb *msgb_alloc(uint16_t size, const char *name);
+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);
+
+#ifdef MSGB_DEBUG
+#include <osmocom/core/panic.h>
+#define MSGB_ABORT(msg, fmt, args ...) do {		\
+	osmo_panic("msgb(%p): " fmt, msg, ## args);	\
+	} while(0)
+#else
+#define MSGB_ABORT(msg, fmt, args ...)
+#endif
+
+#define msgb_l1(m)	((void *)(m->l1h))
+#define msgb_l2(m)	((void *)(m->l2h))
+#define msgb_l3(m)	((void *)(m->l3h))
+#define msgb_sms(m)	((void *)(m->l4h))
+
+static inline unsigned int msgb_l1len(const struct msgb *msgb)
+{
+	return msgb->tail - (uint8_t *)msgb_l1(msgb);
+}
+
+static inline unsigned int msgb_l2len(const struct msgb *msgb)
+{
+	return msgb->tail - (uint8_t *)msgb_l2(msgb);
+}
+
+static inline unsigned int msgb_l3len(const struct msgb *msgb)
+{
+	return msgb->tail - (uint8_t *)msgb_l3(msgb);
+}
+
+static inline unsigned int msgb_headlen(const struct msgb *msgb)
+{
+	return msgb->len - msgb->data_len;
+}
+
+static inline int msgb_tailroom(const struct msgb *msgb)
+{
+	return (msgb->head + msgb->data_len) - msgb->tail;
+}
+
+static inline int msgb_headroom(const struct msgb *msgb)
+{
+	return (msgb->data - msgb->head);
+}
+
+static inline unsigned char *msgb_put(struct msgb *msgb, unsigned int len)
+{
+	unsigned char *tmp = msgb->tail;
+	if (msgb_tailroom(msgb) < (int) len)
+		MSGB_ABORT(msgb, "Not enough tailroom msgb_push (%u < %u)\n",
+			   msgb_tailroom(msgb), len);
+	msgb->tail += len;
+	msgb->len += len;
+	return tmp;
+}
+static inline void msgb_put_u8(struct msgb *msgb, uint8_t word)
+{
+	uint8_t *space = msgb_put(msgb, 1);
+	space[0] = word & 0xFF;
+}
+static inline void msgb_put_u16(struct msgb *msgb, uint16_t word)
+{
+	uint8_t *space = msgb_put(msgb, 2);
+	space[0] = word >> 8 & 0xFF;
+	space[1] = word & 0xFF;
+}
+static inline void msgb_put_u32(struct msgb *msgb, uint32_t word)
+{
+	uint8_t *space = msgb_put(msgb, 4);
+	space[0] = word >> 24 & 0xFF;
+	space[1] = word >> 16 & 0xFF;
+	space[2] = word >> 8 & 0xFF;
+	space[3] = word & 0xFF;
+}
+static inline unsigned char *msgb_get(struct msgb *msgb, unsigned int len)
+{
+	unsigned char *tmp = msgb->data;
+	msgb->data += len;
+	msgb->len -= len;
+	return tmp;
+}
+static inline uint8_t msgb_get_u8(struct msgb *msgb)
+{
+	uint8_t *space = msgb_get(msgb, 1);
+	return space[0];
+}
+static inline uint16_t msgb_get_u16(struct msgb *msgb)
+{
+	uint8_t *space = msgb_get(msgb, 2);
+	return space[0] << 8 | space[1];
+}
+static inline uint32_t msgb_get_u32(struct msgb *msgb)
+{
+	uint8_t *space = msgb_get(msgb, 4);
+	return space[0] << 24 | space[1] << 16 | space[2] << 8 | space[3];
+}
+static inline unsigned char *msgb_push(struct msgb *msgb, unsigned int len)
+{
+	if (msgb_headroom(msgb) < (int) len)
+		MSGB_ABORT(msgb, "Not enough headroom msgb_push (%u < %u)\n",
+			   msgb_headroom(msgb), len);
+	msgb->data -= len;
+	msgb->len += len;
+	return msgb->data;
+}
+static inline unsigned char *msgb_pull(struct msgb *msgb, unsigned int len)
+{
+	msgb->len -= len;
+	return msgb->data += len;
+}
+
+/* increase the headroom of an empty msgb, reducing the tailroom */
+static inline void msgb_reserve(struct msgb *msg, int len)
+{
+	msg->data += len;
+	msg->tail += len;
+}
+
+static inline struct msgb *msgb_alloc_headroom(int size, int headroom,
+						const char *name)
+{
+	static_assert(size > headroom, headroom_bigger);
+
+	struct msgb *msg = msgb_alloc(size, name);
+	if (msg)
+		msgb_reserve(msg, headroom);
+	return msg;
+}
+
+/* non inline functions to ease binding */
+uint8_t *msgb_data(const struct msgb *msg);
+uint16_t msgb_length(const struct msgb *msg);
+
+
+#endif /* _MSGB_H */
diff --git a/include/osmocom/core/msgfile.h b/include/osmocom/core/msgfile.h
new file mode 100644
index 0000000..92caa9f
--- /dev/null
+++ b/include/osmocom/core/msgfile.h
@@ -0,0 +1,49 @@
+/*
+ * (C) 2010 by Holger Hans Peter Freyther
+ * (C) 2010 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef MSG_FILE_H
+#define MSG_FILE_H
+
+#include "linuxlist.h"
+
+/**
+ * One message in the list.
+ */
+struct msg_entry {
+	struct llist_head list;
+
+	/* number for everyone to use */
+	int nr;
+
+	/* data from the file */
+	char *mcc;
+	char *mnc;
+	char *option;
+	char *text;
+};
+
+struct msg_entries {
+	struct llist_head entry;
+};
+
+struct msg_entries *msg_entry_parse(void *ctx, const char *filename);
+
+#endif
diff --git a/include/osmocom/core/panic.h b/include/osmocom/core/panic.h
new file mode 100644
index 0000000..c5a8377
--- /dev/null
+++ b/include/osmocom/core/panic.h
@@ -0,0 +1,11 @@
+#ifndef OSMOCORE_PANIC_H
+#define OSMOCORE_PANIC_H
+
+#include <stdarg.h>
+
+typedef void (*osmo_panic_handler_t)(const char *fmt, va_list args);
+
+void osmo_panic(const char *fmt, ...);
+void osmo_set_panic_handler(osmo_panic_handler_t h);
+
+#endif
diff --git a/include/osmocom/core/plugin.h b/include/osmocom/core/plugin.h
new file mode 100644
index 0000000..98f9b56
--- /dev/null
+++ b/include/osmocom/core/plugin.h
@@ -0,0 +1,6 @@
+#ifndef _OSMO_PLUGIN_H
+#define _OSMO_PLUGIN_H
+
+int plugin_load_all(const char *directory);
+
+#endif
diff --git a/include/osmocom/core/process.h b/include/osmocom/core/process.h
new file mode 100644
index 0000000..2d66382
--- /dev/null
+++ b/include/osmocom/core/process.h
@@ -0,0 +1,6 @@
+#ifndef _OSMO_PROCESS_H
+#define _OSMO_PROCESS_H
+
+int osmo_daemonize(void);
+
+#endif
diff --git a/include/osmocom/core/rate_ctr.h b/include/osmocom/core/rate_ctr.h
new file mode 100644
index 0000000..dba573d
--- /dev/null
+++ b/include/osmocom/core/rate_ctr.h
@@ -0,0 +1,81 @@
+#ifndef _RATE_CTR_H
+#define _RATE_CTR_H
+
+#include <stdint.h>
+
+#include <osmocom/core/linuxlist.h>
+
+#define RATE_CTR_INTV_NUM	4
+
+enum rate_ctr_intv {
+	RATE_CTR_INTV_SEC,
+	RATE_CTR_INTV_MIN,
+	RATE_CTR_INTV_HOUR,
+	RATE_CTR_INTV_DAY,
+};
+
+/* for each of the intervals, we keep the following values */
+struct rate_ctr_per_intv {
+	uint64_t last;
+	uint64_t rate;
+};
+
+/* for each actual value, we keep the following data */
+struct rate_ctr {
+	uint64_t current;
+	struct rate_ctr_per_intv intv[RATE_CTR_INTV_NUM];
+};
+
+struct rate_ctr_desc {
+	const char *name;
+	const char *description;
+};
+
+/* Describe a counter group class */
+struct rate_ctr_group_desc {
+	/* The prefix to the name of all counters in this group */
+	const char *group_name_prefix;
+	/* The human-readable description of the group */
+	const char *group_description;
+	/* The number of counters in this group */
+	const unsigned int num_ctr;
+	/* Pointer to array of counter names */
+	const struct rate_ctr_desc *ctr_desc;
+};
+
+/* One instance of a counter group class */
+struct rate_ctr_group {
+	/* Linked list of all counter groups in the system */
+	struct llist_head list;
+	/* Pointer to the counter group class */
+	const struct rate_ctr_group_desc *desc;
+	/* The index of this ctr_group within its class */
+	unsigned int idx;
+	/* Actual counter structures below */
+	struct rate_ctr ctr[0];
+};
+
+/* Allocate a new group of counters according to description */
+struct rate_ctr_group *rate_ctr_group_alloc(void *ctx,
+					    const struct rate_ctr_group_desc *desc,
+					    unsigned int idx);
+
+/* Free the memory for the specified group of counters */
+void rate_ctr_group_free(struct rate_ctr_group *grp);
+
+/* Add a number to the counter */
+void rate_ctr_add(struct rate_ctr *ctr, int inc);
+
+/* Increment the counter by 1 */
+static inline void rate_ctr_inc(struct rate_ctr *ctr)
+{
+	rate_ctr_add(ctr, 1);
+}
+
+/* Initialize the counter module */
+int rate_ctr_init(void *tall_ctx);
+
+struct vty;
+void vty_out_rate_ctr_group(struct vty *vty, const char *prefix,
+			    struct rate_ctr_group *ctrg);
+#endif /* RATE_CTR_H */
diff --git a/include/osmocom/core/select.h b/include/osmocom/core/select.h
new file mode 100644
index 0000000..5ca21c3
--- /dev/null
+++ b/include/osmocom/core/select.h
@@ -0,0 +1,22 @@
+#ifndef _BSC_SELECT_H
+#define _BSC_SELECT_H
+
+#include <osmocom/core/linuxlist.h>
+
+#define BSC_FD_READ	0x0001
+#define BSC_FD_WRITE	0x0002
+#define BSC_FD_EXCEPT	0x0004
+
+struct bsc_fd {
+	struct llist_head list;
+	int fd;
+	unsigned int when;
+	int (*cb)(struct bsc_fd *fd, unsigned int what);
+	void *data;
+	unsigned int priv_nr;
+};
+
+int bsc_register_fd(struct bsc_fd *fd);
+void bsc_unregister_fd(struct bsc_fd *fd);
+int bsc_select_main(int polling);
+#endif /* _BSC_SELECT_H */
diff --git a/include/osmocom/core/signal.h b/include/osmocom/core/signal.h
new file mode 100644
index 0000000..02d83d2
--- /dev/null
+++ b/include/osmocom/core/signal.h
@@ -0,0 +1,15 @@
+#ifndef OSMOCORE_SIGNAL_H
+#define OSMOCORE_SIGNAL_H
+
+typedef int signal_cbfn(unsigned int subsys, unsigned int signal,
+			void *handler_data, void *signal_data);
+
+
+/* Management */
+int register_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data);
+void unregister_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data);
+
+/* Dispatch */
+void dispatch_signal(unsigned int subsys, unsigned int signal, void *signal_data);
+
+#endif /* OSMOCORE_SIGNAL_H */
diff --git a/include/osmocom/core/statistics.h b/include/osmocom/core/statistics.h
new file mode 100644
index 0000000..1d56054
--- /dev/null
+++ b/include/osmocom/core/statistics.h
@@ -0,0 +1,31 @@
+#ifndef _STATISTICS_H
+#define _STATISTICS_H
+
+struct counter {
+	struct llist_head list;
+	const char *name;
+	const char *description;
+	unsigned long value;
+};
+
+static inline void counter_inc(struct counter *ctr)
+{
+	ctr->value++;
+}
+
+static inline unsigned long counter_get(struct counter *ctr)
+{
+	return ctr->value;
+}
+
+static inline void counter_reset(struct counter *ctr)
+{
+	ctr->value = 0;
+}
+
+struct counter *counter_alloc(const char *name);
+void counter_free(struct counter *ctr);
+
+int counters_for_each(int (*handle_counter)(struct counter *, void *), void *data);
+
+#endif /* _STATISTICS_H */
diff --git a/include/osmocom/core/talloc.h b/include/osmocom/core/talloc.h
new file mode 100644
index 0000000..f7f7643
--- /dev/null
+++ b/include/osmocom/core/talloc.h
@@ -0,0 +1,192 @@
+#ifndef _TALLOC_H_
+#define _TALLOC_H_
+/* 
+   Unix SMB/CIFS implementation.
+   Samba temporary memory allocation functions
+
+   Copyright (C) Andrew Tridgell 2004-2005
+   Copyright (C) Stefan Metzmacher 2006
+   
+     ** NOTE! The following LGPL license applies to the talloc
+     ** library. This does NOT imply that all of Samba is released
+     ** under the LGPL
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 3 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#define HAVE_VA_COPY
+
+/* this is only needed for compatibility with the old talloc */
+typedef void TALLOC_CTX;
+
+/*
+  this uses a little trick to allow __LINE__ to be stringified
+*/
+#ifndef __location__
+#define __TALLOC_STRING_LINE1__(s)    #s
+#define __TALLOC_STRING_LINE2__(s)   __TALLOC_STRING_LINE1__(s)
+#define __TALLOC_STRING_LINE3__  __TALLOC_STRING_LINE2__(__LINE__)
+#define __location__ __FILE__ ":" __TALLOC_STRING_LINE3__
+#endif
+
+#ifndef TALLOC_DEPRECATED
+#define TALLOC_DEPRECATED 0
+#endif
+
+#ifndef PRINTF_ATTRIBUTE
+#if (__GNUC__ >= 3)
+/** Use gcc attribute to check printf fns.  a1 is the 1-based index of
+ * the parameter containing the format, and a2 the index of the first
+ * argument. Note that some gcc 2.x versions don't handle this
+ * properly **/
+#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
+#else
+#define PRINTF_ATTRIBUTE(a1, a2)
+#endif
+#endif
+
+/* try to make talloc_set_destructor() and talloc_steal() type safe,
+   if we have a recent gcc */
+#if (__GNUC__ >= 3)
+#define _TALLOC_TYPEOF(ptr) __typeof__(ptr)
+#define talloc_set_destructor(ptr, function)				      \
+	do {								      \
+		int (*_talloc_destructor_fn)(_TALLOC_TYPEOF(ptr)) = (function);	      \
+		_talloc_set_destructor((ptr), (int (*)(void *))_talloc_destructor_fn); \
+	} while(0)
+/* this extremely strange macro is to avoid some braindamaged warning
+   stupidity in gcc 4.1.x */
+#define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)); __talloc_steal_ret; })
+#else
+#define talloc_set_destructor(ptr, function) \
+	_talloc_set_destructor((ptr), (int (*)(void *))(function))
+#define _TALLOC_TYPEOF(ptr) void *
+#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr))
+#endif
+
+#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference((ctx),(ptr))
+#define talloc_move(ctx, ptr) (_TALLOC_TYPEOF(*(ptr)))_talloc_move((ctx),(void *)(ptr))
+
+/* useful macros for creating type checked pointers */
+#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type)
+#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__)
+#define talloc_ptrtype(ctx, ptr) (_TALLOC_TYPEOF(ptr))talloc_size(ctx, sizeof(*(ptr)))
+
+#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__)
+
+#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type)
+#define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__)
+
+#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type)
+#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type)
+#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__)
+#define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count)
+#define talloc_array_length(ctx) (talloc_get_size(ctx)/sizeof(*ctx))
+
+#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type)
+#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__)
+
+#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__)
+
+#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type)
+#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type)
+#define talloc_get_type_abort(ptr, type) (type *)_talloc_get_type_abort(ptr, #type, __location__)
+
+#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type)
+
+#if TALLOC_DEPRECATED
+#define talloc_zero_p(ctx, type) talloc_zero(ctx, type)
+#define talloc_p(ctx, type) talloc(ctx, type)
+#define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count)
+#define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count)
+#define talloc_destroy(ctx) talloc_free(ctx)
+#define talloc_append_string(c, s, a) (s?talloc_strdup_append(s,a):talloc_strdup(c, a))
+#endif
+
+#define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0)
+
+/* The following definitions come from talloc.c  */
+void *_talloc(const void *context, size_t size);
+void *talloc_pool(const void *context, size_t size);
+void _talloc_set_destructor(const void *ptr, int (*_destructor)(void *));
+int talloc_increase_ref_count(const void *ptr);
+size_t talloc_reference_count(const void *ptr);
+void *_talloc_reference(const void *context, const void *ptr);
+int talloc_unlink(const void *context, void *ptr);
+const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+void talloc_set_name_const(const void *ptr, const char *name);
+void *talloc_named(const void *context, size_t size, 
+		   const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
+void *talloc_named_const(const void *context, size_t size, const char *name);
+const char *talloc_get_name(const void *ptr);
+void *talloc_check_name(const void *ptr, const char *name);
+void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location);
+void *talloc_parent(const void *ptr);
+const char *talloc_parent_name(const void *ptr);
+void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
+int talloc_free(void *ptr);
+void talloc_free_children(void *ptr);
+void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name);
+void *_talloc_steal(const void *new_ctx, const void *ptr);
+void *_talloc_move(const void *new_ctx, const void *pptr);
+size_t talloc_total_size(const void *ptr);
+size_t talloc_total_blocks(const void *ptr);
+void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
+			    void (*callback)(const void *ptr,
+			  		     int depth, int max_depth,
+					     int is_ref,
+					     void *private_data),
+			    void *private_data);
+void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f);
+void talloc_report_full(const void *ptr, FILE *f);
+void talloc_report(const void *ptr, FILE *f);
+void talloc_enable_null_tracking(void);
+void talloc_disable_null_tracking(void);
+void talloc_enable_leak_report(void);
+void talloc_enable_leak_report_full(void);
+void *_talloc_zero(const void *ctx, size_t size, const char *name);
+void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name);
+void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name);
+void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name);
+void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name);
+void *talloc_realloc_fn(const void *context, void *ptr, size_t size);
+void *talloc_autofree_context(void);
+size_t talloc_get_size(const void *ctx);
+void *talloc_find_parent_byname(const void *ctx, const char *name);
+void talloc_show_parents(const void *context, FILE *file);
+int talloc_is_parent(const void *context, const void *ptr);
+
+char *talloc_strdup(const void *t, const char *p);
+char *talloc_strdup_append(char *s, const char *a);
+char *talloc_strdup_append_buffer(char *s, const char *a);
+
+char *talloc_strndup(const void *t, const char *p, size_t n);
+char *talloc_strndup_append(char *s, const char *a, size_t n);
+char *talloc_strndup_append_buffer(char *s, const char *a, size_t n);
+
+char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+
+char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+
+void talloc_set_abort_fn(void (*abort_fn)(const char *reason));
+
+#endif
diff --git a/include/osmocom/core/timer.h b/include/osmocom/core/timer.h
new file mode 100644
index 0000000..1966478
--- /dev/null
+++ b/include/osmocom/core/timer.h
@@ -0,0 +1,72 @@
+/*
+ * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef TIMER_H
+#define TIMER_H
+
+#include <sys/time.h>
+
+#include <osmocom/core/linuxlist.h>
+
+/**
+ * Timer management:
+ *      - Create a struct timer_list
+ *      - Fill out timeout and use add_timer or
+ *        use schedule_timer to schedule a timer in
+ *        x seconds and microseconds from now...
+ *      - Use del_timer to remove the timer
+ *
+ *  Internally:
+ *      - We hook into select.c to give a timeval of the
+ *        nearest timer. On already passed timers we give
+ *        it a 0 to immediately fire after the select
+ *      - update_timers will call the callbacks and remove
+ *        the timers.
+ *
+ */
+struct timer_list {
+	struct llist_head entry;
+	struct timeval timeout;
+	unsigned int active  : 1;
+	unsigned int handled : 1;
+	unsigned int in_list : 1;
+
+	void (*cb)(void*);
+	void *data;
+};
+
+/**
+ * timer management
+ */
+void bsc_add_timer(struct timer_list *timer);
+void bsc_schedule_timer(struct timer_list *timer, int seconds, int microseconds);
+void bsc_del_timer(struct timer_list *timer);
+int bsc_timer_pending(struct timer_list *timer);
+
+
+/**
+ * internal timer list management
+ */
+struct timeval *bsc_nearest_timer();
+void bsc_prepare_timers();
+int bsc_update_timers();
+int bsc_timer_check(void);
+
+#endif
diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h
new file mode 100644
index 0000000..0cdf03b
--- /dev/null
+++ b/include/osmocom/core/utils.h
@@ -0,0 +1,30 @@
+#ifndef OSMOCORE_UTIL_H
+#define OSMOCORE_UTIL_H
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#include <stdint.h>
+
+struct value_string {
+	unsigned int value;
+	const char *str;
+};
+
+const char *get_value_string(const struct value_string *vs, uint32_t val);
+int get_string_value(const struct value_string *vs, const char *str);
+
+char bcd2char(uint8_t bcd);
+/* only works for numbers in ascci */
+uint8_t char2bcd(char c);
+
+int hexparse(const char *str, uint8_t *b, int max_len);
+char *hexdump(const unsigned char *buf, int len);
+char *hexdump_nospc(const unsigned char *buf, int len);
+char *ubit_dump(const uint8_t *bits, unsigned int len);
+
+#define static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1];
+
+void osmo_str2lower(char *out, const char *in);
+void osmo_str2upper(char *out, const char *in);
+
+#endif
diff --git a/include/osmocom/core/write_queue.h b/include/osmocom/core/write_queue.h
new file mode 100644
index 0000000..ef244c3
--- /dev/null
+++ b/include/osmocom/core/write_queue.h
@@ -0,0 +1,46 @@
+/* Generic write queue implementation */
+/*
+ * (C) 2010 by Holger Hans Peter Freyther
+ * (C) 2010 by On-Waves
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#ifndef write_queue_h
+#define write_queue_h
+
+#include "select.h"
+#include "msgb.h"
+
+struct write_queue {
+	struct bsc_fd bfd;
+	unsigned int max_length;
+	unsigned int current_length;
+
+	struct llist_head msg_queue;
+
+	int (*read_cb)(struct bsc_fd *fd);
+	int (*write_cb)(struct bsc_fd *fd, struct msgb *msg);
+	int (*except_cb)(struct bsc_fd *fd);
+};
+
+void write_queue_init(struct write_queue *queue, int max_length);
+void write_queue_clear(struct write_queue *queue);
+int write_queue_enqueue(struct write_queue *queue, struct msgb *data);
+int write_queue_bfd_cb(struct bsc_fd *fd, unsigned int what);
+
+#endif