aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-07-28 03:32:52 +0800
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-07-28 03:36:32 +0800
commit97f66e2b534e2a54c63360a3f8134a0189c54e25 (patch)
tree903e34443767b09ef1d11575f8a1502f6295c7fd /include
Public release of the cellmgr_ng code to convert E1 to IPA SCCP
Diffstat (limited to 'include')
-rw-r--r--include/Makefile.am5
-rw-r--r--include/bsc_data.h131
-rw-r--r--include/bss_patch.h48
-rw-r--r--include/bssap_sccp.h33
-rw-r--r--include/ipaccess.h52
-rw-r--r--include/mgcp/Makefile.am1
-rw-r--r--include/mgcp/mgcp.h141
-rw-r--r--include/mgcp/mgcp_internal.h89
-rw-r--r--include/mgcp_ss7.h68
-rw-r--r--include/mtp_data.h88
-rw-r--r--include/mtp_level3.h164
-rw-r--r--include/mtp_pcap.h29
-rw-r--r--include/openbsc_nat/Makefile.am1
-rw-r--r--include/openbsc_nat/bssap.h339
-rw-r--r--include/openbsc_nat/tlv.h234
-rw-r--r--include/snmp_mtp.h39
-rw-r--r--include/thread.h59
-rw-r--r--include/udp_input.h52
-rw-r--r--include/write_queue.h48
19 files changed, 1621 insertions, 0 deletions
diff --git a/include/Makefile.am b/include/Makefile.am
new file mode 100644
index 0000000..7a2960e
--- /dev/null
+++ b/include/Makefile.am
@@ -0,0 +1,5 @@
+noinst_HEADERS = mtp_level3.h mtp_data.h ipaccess.h thread.h mtp_pcap.h \
+ mgcp_ss7.h bss_patch.h write_queue.h bssap_sccp.h bsc_data.h udp_input.h \
+ snmp_mtp.h
+
+SUBDIRS = mgcp openbsc_nat
diff --git a/include/bsc_data.h b/include/bsc_data.h
new file mode 100644
index 0000000..6d61a22
--- /dev/null
+++ b/include/bsc_data.h
@@ -0,0 +1,131 @@
+/* Everything related to the BSC connection */
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (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 BSC_DATA_H
+#define BSC_DATA_H
+
+#include <laf0rge1/linuxlist.h>
+#include <laf0rge1/select.h>
+#include <laf0rge1/timer.h>
+
+#include <sccp/sccp.h>
+
+#include "write_queue.h"
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+struct bsc_data;
+struct snmp_mtp_session;
+
+/**
+ * A link to the underlying MTP2 library or such
+ */
+struct link_data {
+ union {
+ struct {
+ struct thread_notifier *notifier;
+ struct llist_head mtp_queue;
+ struct timer_list mtp_timeout;
+ } c7;
+ struct {
+ struct write_queue write_queue;
+ struct sockaddr_in remote;
+ struct snmp_mtp_session *session;
+ int reset_timeout;
+ } udp;
+ };
+
+ int pcap_fd;
+ struct bsc_data *bsc;
+ struct mtp_link *the_link;
+
+ struct timer_list link_activate;
+ int forced_down;
+
+ int (*start)(struct link_data *);
+ int (*write)(struct link_data *, struct msgb *msg);
+ int (*shutdown)(struct link_data *);
+ int (*reset)(struct link_data *data);
+ int (*clear_queue)(struct link_data *data);
+};
+
+
+struct bsc_data {
+ /* MSC */
+ char *msc_address;
+ struct write_queue msc_connection;
+ struct timer_list reconnect_timer;
+ int first_contact;
+ int msc_time;
+ struct timer_list msc_timeout;
+ int msc_ip_dscp;
+
+ int ping_time;
+ int pong_time;
+ struct timer_list ping_timeout;
+ struct timer_list pong_timeout;
+
+ int closing;
+ struct llist_head sccp_connections;
+ struct timer_list reset_timeout;
+ int reset_count;
+
+ struct timer_list start_timer;
+
+ int setup;
+
+ struct link_data link;
+
+ const char *token;
+
+ /* mgcp messgaes */
+ struct write_queue mgcp_agent;
+};
+
+/* bsc related functions */
+void release_bsc_resources(struct bsc_data *bsc);
+void bsc_link_down(struct link_data *data);
+void bsc_link_up(struct link_data *data);
+
+/* msc related functions */
+int msc_init(struct bsc_data *bsc);
+void msc_schedule_reconnect(struct bsc_data *bsc);
+void msc_send_rlc(struct bsc_data *bsc, struct sccp_source_reference *src, struct sccp_source_reference *dest);
+void msc_send_reset(struct bsc_data *bsc);
+void msc_send_msg(struct bsc_data *bsc, int rc, struct sccp_parse_result *, struct msgb *msg);
+void msc_clear_queue(struct bsc_data *data);
+
+/* connection tracking and action */
+void update_con_state(int rc, struct sccp_parse_result *result, struct msgb *msg, int from_msc, int sls);
+unsigned int sls_for_src_ref(struct sccp_source_reference *ref);
+
+/* c7 init */
+int link_c7_init(struct link_data *data);
+
+/* udp init */
+int link_udp_init(struct link_data *data, int src_port, const char *dest_ip, int port);
+
+/* MGCP */
+void mgcp_forward(struct bsc_data *bsc, const u_int8_t *data, unsigned int length);
+
+#endif
diff --git a/include/bss_patch.h b/include/bss_patch.h
new file mode 100644
index 0000000..43dc5f1
--- /dev/null
+++ b/include/bss_patch.h
@@ -0,0 +1,48 @@
+/* Patch Messages to and from the MSC */
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (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 bss_patch_h
+#define bss_patch_h
+
+#include <laf0rge1/msgb.h>
+
+#include <sccp/sccp.h>
+
+#define BSS_FILTER_RESET 1
+#define BSS_FILTER_RESET_ACK 2
+#define BSS_FILTER_RLSD 3
+#define BSS_FILTER_RLC 4
+#define BSS_FILTER_CLEAR_COMPL 5
+
+/**
+ * Error is < 0
+ * Success is == 0
+ * Filter is > 0
+ */
+int bss_patch_filter_msg(struct msgb *msg, struct sccp_parse_result *result);
+
+/*
+ * Copy inpt->l2h to target->l2h but rewrite the SCCP header on the way
+ */
+void bss_rewrite_header_for_msc(int, struct msgb *target, struct msgb *inpt, struct sccp_parse_result *result);
+int bss_rewrite_header_to_bsc(struct msgb *target, int opc, int dpc);
+
+#endif
diff --git a/include/bssap_sccp.h b/include/bssap_sccp.h
new file mode 100644
index 0000000..f2dd45c
--- /dev/null
+++ b/include/bssap_sccp.h
@@ -0,0 +1,33 @@
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (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 bssap_sccp_h
+#define bssap_sccp_h
+
+#include <sys/types.h>
+#include <sccp/sccp_types.h>
+
+struct msgb *create_clear_command(struct sccp_source_reference *dest_ref);
+struct msgb *create_sccp_rlsd(struct sccp_source_reference *src_ref, struct sccp_source_reference *dst);
+struct msgb *create_sccp_rlc(struct sccp_source_reference *src_ref, struct sccp_source_reference *dst);
+struct msgb *create_sccp_refuse(struct sccp_source_reference *dest_ref);
+struct msgb *create_reset();
+
+#endif
diff --git a/include/ipaccess.h b/include/ipaccess.h
new file mode 100644
index 0000000..345ed3c
--- /dev/null
+++ b/include/ipaccess.h
@@ -0,0 +1,52 @@
+#ifndef _IPACCESS_H
+#define _IPACCESS_H
+
+#include <laf0rge1/linuxlist.h>
+
+#define IPA_TCP_PORT_OML 3002
+#define IPA_TCP_PORT_RSL 3003
+
+struct ipaccess_head {
+ u_int16_t len; /* network byte order */
+ u_int8_t proto;
+ u_int8_t data[0];
+} __attribute__ ((packed));
+
+enum ipaccess_proto {
+ IPAC_PROTO_RSL = 0x00,
+ IPAC_PROTO_IPACCESS = 0xfe,
+ IPAC_PROTO_SCCP = 0xfd,
+ IPAC_PROTO_OML = 0xff,
+};
+
+enum ipaccess_msgtype {
+ IPAC_MSGT_PING = 0x00,
+ IPAC_MSGT_PONG = 0x01,
+ IPAC_MSGT_ID_GET = 0x04,
+ IPAC_MSGT_ID_RESP = 0x05,
+ IPAC_MSGT_ID_ACK = 0x06,
+};
+
+enum ipaccess_id_tags {
+ IPAC_IDTAG_SERNR = 0x00,
+ IPAC_IDTAG_UNITNAME = 0x01,
+ IPAC_IDTAG_LOCATION1 = 0x02,
+ IPAC_IDTAG_LOCATION2 = 0x03,
+ IPAC_IDTAG_EQUIPVERS = 0x04,
+ IPAC_IDTAG_SWVERSION = 0x05,
+ IPAC_IDTAG_IPADDR = 0x06,
+ IPAC_IDTAG_MACADDR = 0x07,
+ IPAC_IDTAG_UNIT = 0x08,
+};
+
+/*
+ * methods for parsing and sending a message
+ */
+int ipaccess_rcvmsg_base(struct msgb *msg, struct bsc_fd *bfd);
+struct msgb *ipaccess_read_msg(struct bsc_fd *bfd, int *error);
+void ipaccess_prepend_header(struct msgb *msg, int proto);
+int ipaccess_send_id_ack(int fd);
+int ipaccess_send_id_req(int fd);
+
+
+#endif /* _IPACCESS_H */
diff --git a/include/mgcp/Makefile.am b/include/mgcp/Makefile.am
new file mode 100644
index 0000000..55199ff
--- /dev/null
+++ b/include/mgcp/Makefile.am
@@ -0,0 +1 @@
+noinst_HEADERS = mgcp.h mgcp_internal.h
diff --git a/include/mgcp/mgcp.h b/include/mgcp/mgcp.h
new file mode 100644
index 0000000..914571a
--- /dev/null
+++ b/include/mgcp/mgcp.h
@@ -0,0 +1,141 @@
+/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
+
+/*
+ * (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-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 OPENBSC_MGCP_H
+#define OPENBSC_MGCP_H
+
+#include <laf0rge1/msgb.h>
+
+#include <arpa/inet.h>
+
+#define RTP_PORT_DEFAULT 4000
+/**
+ * Calculate the RTP audio port for the given multiplex
+ * and the direction. This allows a semi static endpoint
+ * to port calculation removing the need for the BSC
+ * and the MediaGateway to communicate.
+ *
+ * Port usage explained:
+ * base + (multiplex * 2) + 0 == local port to wait for network packets
+ * base + (multiplex * 2) + 1 == local port for rtcp
+ *
+ * The above port will receive packets from the BTS that need
+ * to be patched and forwarded to the network.
+ * The above port will receive packets from the network that
+ * need to be patched and forwarded to the BTS.
+ *
+ * We assume to have a static BTS IP address so we can differentiate
+ * network and BTS.
+ *
+ */
+static inline int rtp_calculate_port(int multiplex, int base)
+{
+ return base + (multiplex * 2);
+}
+
+
+/*
+ * Handling of MGCP Endpoints and the MGCP Config
+ */
+struct mgcp_endpoint;
+struct mgcp_config;
+
+#define MGCP_ENDP_CRCX 1
+#define MGCP_ENDP_DLCX 2
+#define MGCP_ENDP_MDCX 3
+
+/*
+ * what to do with the msg?
+ * - continue as usual?
+ * - reject and send a failure code?
+ * - defer? do not send anything
+ */
+#define MGCP_POLICY_CONT 4
+#define MGCP_POLICY_REJECT 5
+#define MGCP_POLICY_DEFER 6
+
+typedef int (*mgcp_change)(struct mgcp_config *cfg, int endpoint, int state, int local_rtp);
+typedef int (*mgcp_policy)(struct mgcp_config *cfg, int endpoint, int state, const char *transactio_id);
+typedef int (*mgcp_reset)(struct mgcp_config *cfg);
+
+struct mgcp_config {
+ /* common configuration */
+ int source_port;
+ char *local_ip;
+ char *source_addr;
+ char *bts_ip;
+ char *call_agent_addr;
+
+ /* default endpoint data */
+ struct in_addr bts_in;
+ char *audio_name;
+ int audio_payload;
+ int audio_loop;
+ int early_bind;
+ int rtp_base_port;
+ int endp_dscp;
+
+ /* only used in forward mode */
+ char *forward_ip;
+ int forward_port;
+
+ unsigned int last_call_id;
+
+ /* endpoint configuration */
+ unsigned int number_endpoints;
+ struct mgcp_endpoint *endpoints;
+
+ /* spec handling */
+ int force_realloc;
+
+ /* callback functionality */
+ mgcp_change change_cb;
+ mgcp_policy policy_cb;
+ mgcp_reset reset_cb;
+ void *data;
+};
+
+/* config management */
+struct mgcp_config *mgcp_config_alloc(void);
+int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg);
+int mgcp_vty_init(void);
+int mgcp_endpoints_allocate(struct mgcp_config *cfg);
+int mgcp_bind_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
+void mgcp_free_endp(struct mgcp_endpoint *endp);
+
+/*
+ * format helper functions
+ */
+struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg);
+struct msgb *mgcp_create_response_with_data(int code, const char *msg, const char *trans, const char *data);
+
+/* adc helper */
+static inline int mgcp_timeslot_to_endpoint(int multiplex, int timeslot)
+{
+ if (timeslot == 0)
+ timeslot = 1;
+ return timeslot + (31 * multiplex);
+}
+
+
+#endif
diff --git a/include/mgcp/mgcp_internal.h b/include/mgcp/mgcp_internal.h
new file mode 100644
index 0000000..d1a6523
--- /dev/null
+++ b/include/mgcp/mgcp_internal.h
@@ -0,0 +1,89 @@
+/* MGCP Private Data */
+
+/*
+ * (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-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 OPENBSC_MGCP_DATA_H
+#define OPENBSC_MGCP_DATA_H
+
+#include <laf0rge1/select.h>
+
+#define CI_UNUSED 0
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+#endif
+
+enum mgcp_connection_mode {
+ MGCP_CONN_NONE = 0,
+ MGCP_CONN_RECV_ONLY = 1,
+ MGCP_CONN_SEND_ONLY = 2,
+ MGCP_CONN_RECV_SEND = MGCP_CONN_RECV_ONLY | MGCP_CONN_SEND_ONLY,
+};
+
+struct mgcp_endpoint {
+ int ci;
+ char *callid;
+ char *local_options;
+ int conn_mode;
+
+ int bts_payload_type;
+ int net_payload_type;
+
+ /* the local rtp port we are binding to */
+ int rtp_port;
+
+ /*
+ * RTP mangling:
+ * - we get RTP and RTCP to us and need to forward to the BTS
+ * - we get RTP and RTCP from the BTS and forward to the network
+ */
+ struct bsc_fd local_rtp;
+ struct bsc_fd local_rtcp;
+
+ struct in_addr remote;
+ struct in_addr bts;
+
+ /* in network byte order */
+ int net_rtp, net_rtcp;
+ int bts_rtp, bts_rtcp;
+
+ /* backpointer */
+ struct mgcp_config *cfg;
+
+ /* statistics */
+ unsigned int in_bts;
+ unsigned int in_remote;
+};
+
+#define ENDPOINT_NUMBER(endp) abs(endp - endp->cfg->endpoints)
+
+struct mgcp_msg_ptr {
+ unsigned int start;
+ unsigned int length;
+};
+
+int mgcp_analyze_header(struct mgcp_config *cfg, struct msgb *msg,
+ struct mgcp_msg_ptr *ptr, int size,
+ const char **transaction_id, struct mgcp_endpoint **endp);
+int mgcp_send_dummy(struct mgcp_endpoint *endp);
+
+#endif
diff --git a/include/mgcp_ss7.h b/include/mgcp_ss7.h
new file mode 100644
index 0000000..04eeb5e
--- /dev/null
+++ b/include/mgcp_ss7.h
@@ -0,0 +1,68 @@
+/* mgcp_ss7 helper coder */
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (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 mgcp_ss7_h
+#define mgcp_ss7_h
+
+#include <laf0rge1/timer.h>
+
+#include "write_queue.h"
+#include "thread.h"
+
+
+struct mgcp_ss7_endpoint;
+struct mgcp_ss7 {
+ struct mgcp_config *cfg;
+ struct write_queue mgcp_fd;
+ struct msgb *mgcp_msg;
+
+ struct mgcp_ss7_endpoint *mgw_end;
+
+ /* timer */
+ struct timer_list poll_timer;
+
+ /* thread handling */
+ struct thread_notifier *cmd_queue;
+ pthread_t thread;
+};
+
+enum {
+ MGCP_SS7_MUTE_STATUS,
+ MGCP_SS7_ALLOCATE,
+ MGCP_SS7_DELETE,
+ MGCP_SS7_SHUTDOWN,
+};
+
+struct mgcp_ss7_cmd {
+ struct llist_head entry;
+ u_int8_t type;
+ u_int32_t port;
+ u_int32_t param;
+};
+
+void mgcp_ss7_exec(struct mgcp_ss7 *mgcp, u_int8_t type, u_int32_t port, u_int32_t param);
+
+struct mgcp_ss7 *mgcp_ss7_init(int endpoints, const char *local_ip, const char *mgw_ip, int base_port, int payload);
+void mgcp_ss7_reset(struct mgcp_ss7 *mgcp);
+void mgcp_ss7_free(struct mgcp_ss7 *mgcp);
+
+#endif
diff --git a/include/mtp_data.h b/include/mtp_data.h
new file mode 100644
index 0000000..d8cdff3
--- /dev/null
+++ b/include/mtp_data.h
@@ -0,0 +1,88 @@
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (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 mtp_data_h
+#define mtp_data_h
+
+#include <laf0rge1/msgb.h>
+#include <laf0rge1/timer.h>
+
+/* MTP Level3 timers */
+
+/* Timers for SS7 */
+#define MTP_T1 12, 0
+#define MTP_T2 30, 0
+#define START_DELAY 8, 0
+
+/**
+ * The state of the mtp_link in terms of layer3 and upwards
+ */
+struct mtp_link {
+ /* routing info.. */
+ int dpc, opc;
+
+ /* internal state */
+ /* the MTP1 link is up */
+ int available;
+ int running;
+ int sccp_up;
+
+ /* misc data */
+ u_int8_t test_ptrn[14];
+
+ int sltm_pending;
+ struct llist_head pending_msgs;
+ int sltm_once;
+ int was_up;
+
+
+ /* the associated link */
+ int link;
+
+ int slta_misses;
+ struct timer_list t1_timer;
+ struct timer_list t2_timer;
+
+ struct timer_list delay_timer;
+};
+
+
+struct mtp_link *mtp_link_alloc(void);
+void mtp_link_stop(struct mtp_link *link);
+void mtp_link_reset(struct mtp_link *link);
+int mtp_link_data(struct mtp_link *link, struct msgb *msg);
+int mtp_link_submit_sccp_data(struct mtp_link *link, int sls, const u_int8_t *data, unsigned int length);
+
+
+/* one time init function */
+void mtp_link_init(void);
+
+/* to be implemented for MSU sending */
+void mtp_link_submit(struct mtp_link *link, struct msgb *msg);
+void mtp_link_forward_sccp(struct mtp_link *link, struct msgb *msg, int sls);
+void mtp_link_restart(struct mtp_link *link);
+void mtp_link_slta_recv(struct mtp_link *link);
+void mtp_link_sccp_down(struct mtp_link *link);
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+#endif
+
+#endif
diff --git a/include/mtp_level3.h b/include/mtp_level3.h
new file mode 100644
index 0000000..46cde40
--- /dev/null
+++ b/include/mtp_level3.h
@@ -0,0 +1,164 @@
+/* Q.701-Q.704, Q.706, Q.707 handling code */
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (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 mtp_level3_h
+#define mtp_level3_h
+
+#include <endian.h>
+#include <sys/types.h>
+
+
+/*
+ * pssible service information octets..
+ */
+#define MTP_NI_NATION_NET 0x02
+
+#define MTP_SI_MNT_SNM_MSG 0x00
+#define MTP_SI_MNT_REG_MSG 0x01
+#define MTP_SI_MNT_SCCP 0x03
+
+/*
+ * h0 contains the group, h1 the semantic of it
+ */
+
+#define MTP_TST_MSG_GRP 0x01
+#define MTP_PROHIBIT_MSG_GRP 0x04
+#define MTP_TRF_RESTR_MSG_GRP 0x07
+
+/* h1 values for different groups */
+#define MTP_TST_MSG_SLTM 0x01
+#define MTP_TST_MSG_SLTA 0x02
+
+#define MTP_RESTR_MSG_ALLWED 0x01
+
+#define MTP_PROHIBIT_MSG_SIG 0x01
+
+
+#define SCCP_SST 0x03
+#define SCCP_SSA 0x01
+
+#define MTP_LINK_MASK 0x0F
+#define MTP_ADDR_MASK 0x0FFF
+#define MTP_APOC_MASK 0x3f
+
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define MTP_LINK_SLS(addr) ((addr >>28) & MTP_LINK_MASK)
+#define MTP_ADDR(link, dpc, opc) \
+ (((dpc) & MTP_ADDR_MASK) << 0 | \
+ ((opc) & MTP_ADDR_MASK) << 14| \
+ ((link) & MTP_LINK_MASK) << 28)
+#define MTP_MAKE_APOC(apoc) \
+ (apoc & 0x3fff)
+#elif __BYTE_ORDER == __BIG_ENDIAN
+static inline u_int32_t c_swap_32(u_int32_t in)
+{
+ return (((in & 0x000000ff) << 24) |
+ ((in & 0x0000ff00) << 8) |
+ ((in & 0x00ff0000) >> 8) |
+ ((in & 0xff000000) >> 24));
+}
+static inline u_int16_t c_swap_16(u_int16_t in)
+{
+ return (((in & 0x00ff) << 8) |
+ (in & 0xff00) >> 8);
+}
+#define MTP_LINK_SLS(addr) ((c_swap_32(addr)>>28) & MTP_LINK_MASK)
+#define MTP_ADDR(link, dpc, opc) \
+ c_swap_32(((dpc) & MTP_ADDR_MASK) << 0 | \
+ ((opc) & MTP_ADDR_MASK) << 14| \
+ ((link) & MTP_LINK_MASK) << 28)
+#define MTP_MAKE_APOC(apoc) \
+ c_swap_16((apoc & 0x3fff))
+#endif
+
+
+
+/*
+ * not the on wire address...
+ */
+struct mtp_addr {
+ u_int16_t dpc;
+ u_int16_t opc;
+ u_int8_t link;
+} __attribute__((packed));
+
+/*
+ * the struct is defined in Q.704 and can be seen in the
+ * wireshark dissectors too
+ */
+struct mtp_level_3_hdr {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ u_int8_t ser_ind : 4,
+ spare : 2,
+ ni : 2;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ u_int8_t ni : 2,
+ spare : 2,
+ ser_ind : 4;
+#endif
+ u_int32_t addr;
+ u_int8_t data[0];
+} __attribute__((packed));
+
+struct mtp_level_3_cmn {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ u_int8_t h0 : 4,
+ h1 : 4;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ u_int8_t h1 : 4,
+ h0 : 4;
+#endif
+} __attribute__((packed));
+
+struct mtp_level_3_mng {
+ struct mtp_level_3_cmn cmn;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ u_int8_t spare : 4,
+ length : 4;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ u_int8_t length : 4,
+ spare : 4;
+#endif
+ u_int8_t data[0];
+} __attribute__((packed));
+
+struct mtp_level_3_prohib {
+ struct mtp_level_3_cmn cmn;
+
+ u_int16_t apoc;
+} __attribute__((packed));
+
+struct sccp_con_ctrl_prt_mgt {
+ u_int8_t sst;
+ u_int8_t assn; /* affected sub system number */
+ u_int16_t apoc;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ u_int8_t mul_ind : 2,
+ spare : 6;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ u_int8_t spare : 6,
+ mul_ind : 2;
+#endif
+} __attribute__((packed));
+
+#endif
diff --git a/include/mtp_pcap.h b/include/mtp_pcap.h
new file mode 100644
index 0000000..9334393
--- /dev/null
+++ b/include/mtp_pcap.h
@@ -0,0 +1,29 @@
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (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 mtp_pcap_h
+#define mtp_pcap_h
+
+#include <sys/types.h>
+
+int mtp_pcap_write_header(int fd);
+int mtp_pcap_write_msu(int fd, const u_int8_t *data, int length);
+
+#endif
diff --git a/include/openbsc_nat/Makefile.am b/include/openbsc_nat/Makefile.am
new file mode 100644
index 0000000..96bb305
--- /dev/null
+++ b/include/openbsc_nat/Makefile.am
@@ -0,0 +1 @@
+noinst_HEADERS = bssap.h tlv.h
diff --git a/include/openbsc_nat/bssap.h b/include/openbsc_nat/bssap.h
new file mode 100644
index 0000000..8c785bb
--- /dev/null
+++ b/include/openbsc_nat/bssap.h
@@ -0,0 +1,339 @@
+/* From GSM08.08 */
+
+#ifndef BSSAP_H
+#define BSSAP_H
+
+#include <stdlib.h>
+
+#include <laf0rge1/msgb.h>
+#include <sccp/sccp.h>
+
+struct gsm_network;
+struct bss_sccp_connection_data;
+
+/*
+ * this is from GSM 03.03 CGI but is copied in GSM 08.08
+ * in § 3.2.2.27 for Cell Identifier List
+ */
+enum CELL_IDENT {
+ CELL_IDENT_WHOLE_GLOBAL = 0,
+ CELL_IDENT_LAC_AND_CI = 1,
+ CELL_IDENT_CI = 2,
+ CELL_IDENT_NO_CELL = 3,
+ CELL_IDENT_LAI_AND_LAC = 4,
+ CELL_IDENT_LAC = 5,
+ CELL_IDENT_BSS = 6,
+ CELL_IDENT_UTRAN_PLMN_LAC_RNC = 8,
+ CELL_IDENT_UTRAN_RNC = 9,
+ CELL_IDENT_UTRAN_LAC_RNC = 10,
+};
+
+
+/* GSM 08.06 § 6.3 */
+enum BSSAP_MSG_TYPE {
+ BSSAP_MSG_BSS_MANAGEMENT = 0x0,
+ BSSAP_MSG_DTAP = 0x1,
+};
+
+struct bssmap_header {
+ u_int8_t type;
+ u_int8_t length;
+} __attribute__((packed));
+
+struct dtap_header {
+ u_int8_t type;
+ u_int8_t link_id;
+ u_int8_t length;
+} __attribute__((packed));
+
+
+enum BSS_MAP_MSG_TYPE {
+ BSS_MAP_MSG_RESERVED_0 = 0,
+
+ /* ASSIGNMENT MESSAGES */
+ BSS_MAP_MSG_ASSIGMENT_RQST = 1,
+ BSS_MAP_MSG_ASSIGMENT_COMPLETE = 2,
+ BSS_MAP_MSG_ASSIGMENT_FAILURE = 3,
+
+ /* HANDOVER MESSAGES */
+ BSS_MAP_MSG_HANDOVER_RQST = 16,
+ BSS_MAP_MSG_HANDOVER_REQUIRED = 17,
+ BSS_MAP_MSG_HANDOVER_RQST_ACKNOWLEDGE= 18,
+ BSS_MAP_MSG_HANDOVER_CMD = 19,
+ BSS_MAP_MSG_HANDOVER_COMPLETE = 20,
+ BSS_MAP_MSG_HANDOVER_SUCCEEDED = 21,
+ BSS_MAP_MSG_HANDOVER_FAILURE = 22,
+ BSS_MAP_MSG_HANDOVER_PERFORMED = 23,
+ BSS_MAP_MSG_HANDOVER_CANDIDATE_ENQUIRE = 24,
+ BSS_MAP_MSG_HANDOVER_CANDIDATE_RESPONSE = 25,
+ BSS_MAP_MSG_HANDOVER_REQUIRED_REJECT = 26,
+ BSS_MAP_MSG_HANDOVER_DETECT = 27,
+
+ /* RELEASE MESSAGES */
+ BSS_MAP_MSG_CLEAR_CMD = 32,
+ BSS_MAP_MSG_CLEAR_COMPLETE = 33,
+ BSS_MAP_MSG_CLEAR_RQST = 34,
+ BSS_MAP_MSG_RESERVED_1 = 35,
+ BSS_MAP_MSG_RESERVED_2 = 36,
+ BSS_MAP_MSG_SAPI_N_REJECT = 37,
+ BSS_MAP_MSG_CONFUSION = 38,
+
+ /* OTHER CONNECTION RELATED MESSAGES */
+ BSS_MAP_MSG_SUSPEND = 40,
+ BSS_MAP_MSG_RESUME = 41,
+ BSS_MAP_MSG_CONNECTION_ORIENTED_INFORMATION = 42,
+ BSS_MAP_MSG_PERFORM_LOCATION_RQST = 43,
+ BSS_MAP_MSG_LSA_INFORMATION = 44,
+ BSS_MAP_MSG_PERFORM_LOCATION_RESPONSE = 45,
+ BSS_MAP_MSG_PERFORM_LOCATION_ABORT = 46,
+ BSS_MAP_MSG_COMMON_ID = 47,
+
+ /* GENERAL MESSAGES */
+ BSS_MAP_MSG_RESET = 48,
+ BSS_MAP_MSG_RESET_ACKNOWLEDGE = 49,
+ BSS_MAP_MSG_OVERLOAD = 50,
+ BSS_MAP_MSG_RESERVED_3 = 51,
+ BSS_MAP_MSG_RESET_CIRCUIT = 52,
+ BSS_MAP_MSG_RESET_CIRCUIT_ACKNOWLEDGE = 53,
+ BSS_MAP_MSG_MSC_INVOKE_TRACE = 54,
+ BSS_MAP_MSG_BSS_INVOKE_TRACE = 55,
+ BSS_MAP_MSG_CONNECTIONLESS_INFORMATION = 58,
+
+ /* TERRESTRIAL RESOURCE MESSAGES */
+ BSS_MAP_MSG_BLOCK = 64,
+ BSS_MAP_MSG_BLOCKING_ACKNOWLEDGE = 65,
+ BSS_MAP_MSG_UNBLOCK = 66,
+ BSS_MAP_MSG_UNBLOCKING_ACKNOWLEDGE = 67,
+ BSS_MAP_MSG_CIRCUIT_GROUP_BLOCK = 68,
+ BSS_MAP_MSG_CIRCUIT_GROUP_BLOCKING_ACKNOWLEDGE = 69,
+ BSS_MAP_MSG_CIRCUIT_GROUP_UNBLOCK = 70,
+ BSS_MAP_MSG_CIRCUIT_GROUP_UNBLOCKING_ACKNOWLEDGE = 71,
+ BSS_MAP_MSG_UNEQUIPPED_CIRCUIT = 72,
+ BSS_MAP_MSG_CHANGE_CIRCUIT = 78,
+ BSS_MAP_MSG_CHANGE_CIRCUIT_ACKNOWLEDGE = 79,
+
+ /* RADIO RESOURCE MESSAGES */
+ BSS_MAP_MSG_RESOURCE_RQST = 80,
+ BSS_MAP_MSG_RESOURCE_INDICATION = 81,
+ BSS_MAP_MSG_PAGING = 82,
+ BSS_MAP_MSG_CIPHER_MODE_CMD = 83,
+ BSS_MAP_MSG_CLASSMARK_UPDATE = 84,
+ BSS_MAP_MSG_CIPHER_MODE_COMPLETE = 85,
+ BSS_MAP_MSG_QUEUING_INDICATION = 86,
+ BSS_MAP_MSG_COMPLETE_LAYER_3 = 87,
+ BSS_MAP_MSG_CLASSMARK_RQST = 88,
+ BSS_MAP_MSG_CIPHER_MODE_REJECT = 89,
+ BSS_MAP_MSG_LOAD_INDICATION = 90,
+
+ /* VGCS/VBS */
+ BSS_MAP_MSG_VGCS_VBS_SETUP = 4,
+ BSS_MAP_MSG_VGCS_VBS_SETUP_ACK = 5,
+ BSS_MAP_MSG_VGCS_VBS_SETUP_REFUSE = 6,
+ BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RQST = 7,
+ BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RESULT = 28,
+ BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_FAILURE = 29,
+ BSS_MAP_MSG_VGCS_VBS_QUEUING_INDICATION = 30,
+ BSS_MAP_MSG_UPLINK_RQST = 31,
+ BSS_MAP_MSG_UPLINK_RQST_ACKNOWLEDGE = 39,
+ BSS_MAP_MSG_UPLINK_RQST_CONFIRMATION = 73,
+ BSS_MAP_MSG_UPLINK_RELEASE_INDICATION = 74,
+ BSS_MAP_MSG_UPLINK_REJECT_CMD = 75,
+ BSS_MAP_MSG_UPLINK_RELEASE_CMD = 76,
+ BSS_MAP_MSG_UPLINK_SEIZED_CMD = 77,
+};
+
+enum GSM0808_IE_CODING {
+ GSM0808_IE_CIRCUIT_IDENTITY_CODE = 1,
+ GSM0808_IE_RESERVED_0 = 2,
+ GSM0808_IE_RESOURCE_AVAILABLE = 3,
+ GSM0808_IE_CAUSE = 4,
+ GSM0808_IE_CELL_IDENTIFIER = 5,
+ GSM0808_IE_PRIORITY = 6,
+ GSM0808_IE_LAYER_3_HEADER_INFORMATION = 7,
+ GSM0808_IE_IMSI = 8,
+ GSM0808_IE_TMSI = 9,
+ GSM0808_IE_ENCRYPTION_INFORMATION = 10,
+ GSM0808_IE_CHANNEL_TYPE = 11,
+ GSM0808_IE_PERIODICITY = 12,
+ GSM0808_IE_EXTENDED_RESOURCE_INDICATOR = 13,
+ GSM0808_IE_NUMBER_OF_MSS = 14,
+ GSM0808_IE_RESERVED_1 = 15,
+ GSM0808_IE_RESERVED_2 = 16,
+ GSM0808_IE_RESERVED_3 = 17,
+ GSM0808_IE_CLASSMARK_INFORMATION_T2 = 18,
+ GSM0808_IE_CLASSMARK_INFORMATION_T3 = 19,
+ GSM0808_IE_INTERFERENCE_BAND_TO_USE = 20,
+ GSM0808_IE_RR_CAUSE = 21,
+ GSM0808_IE_RESERVED_4 = 22,
+ GSM0808_IE_LAYER_3_INFORMATION = 23,
+ GSM0808_IE_DLCI = 24,
+ GSM0808_IE_DOWNLINK_DTX_FLAG = 25,
+ GSM0808_IE_CELL_IDENTIFIER_LIST = 26,
+ GSM0808_IE_RESPONSE_RQST = 27,
+ GSM0808_IE_RESOURCE_INDICATION_METHOD = 28,
+ GSM0808_IE_CLASSMARK_INFORMATION_TYPE_1 = 29,
+ GSM0808_IE_CIRCUIT_IDENTITY_CODE_LIST = 30,
+ GSM0808_IE_DIAGNOSTIC = 31,
+ GSM0808_IE_LAYER_3_MESSAGE_CONTENTS = 32,
+ GSM0808_IE_CHOSEN_CHANNEL = 33,
+ GSM0808_IE_TOTAL_RESOURCE_ACCESSIBLE = 34,
+ GSM0808_IE_CIPHER_RESPONSE_MODE = 35,
+ GSM0808_IE_CHANNEL_NEEDED = 36,
+ GSM0808_IE_TRACE_TYPE = 37,
+ GSM0808_IE_TRIGGERID = 38,
+ GSM0808_IE_TRACE_REFERENCE = 39,
+ GSM0808_IE_TRANSACTIONID = 40,
+ GSM0808_IE_MOBILE_IDENTITY = 41,
+ GSM0808_IE_OMCID = 42,
+ GSM0808_IE_FORWARD_INDICATOR = 43,
+ GSM0808_IE_CHOSEN_ENCR_ALG = 44,
+ GSM0808_IE_CIRCUIT_POOL = 45,
+ GSM0808_IE_CIRCUIT_POOL_LIST = 46,
+ GSM0808_IE_TIME_INDICATION = 47,
+ GSM0808_IE_RESOURCE_SITUATION = 48,
+ GSM0808_IE_CURRENT_CHANNEL_TYPE_1 = 49,
+ GSM0808_IE_QUEUEING_INDICATOR = 50,
+ GSM0808_IE_SPEECH_VERSION = 64,
+ GSM0808_IE_ASSIGNMENT_REQUIREMENT = 51,
+ GSM0808_IE_TALKER_FLAG = 53,
+ GSM0808_IE_CONNECTION_RELEASE_RQSTED = 54,
+ GSM0808_IE_GROUP_CALL_REFERENCE = 55,
+ GSM0808_IE_EMLPP_PRIORITY = 56,
+ GSM0808_IE_CONFIG_EVO_INDI = 57,
+ GSM0808_IE_OLD_BSS_TO_NEW_BSS_INFORMATION = 58,
+ GSM0808_IE_LSA_IDENTIFIER = 59,
+ GSM0808_IE_LSA_IDENTIFIER_LIST = 60,
+ GSM0808_IE_LSA_INFORMATION = 61,
+ GSM0808_IE_LCS_QOS = 62,
+ GSM0808_IE_LSA_ACCESS_CTRL_SUPPR = 63,
+ GSM0808_IE_LCS_PRIORITY = 67,
+ GSM0808_IE_LOCATION_TYPE = 68,
+ GSM0808_IE_LOCATION_ESTIMATE = 69,
+ GSM0808_IE_POSITIONING_DATA = 70,
+ GSM0808_IE_LCS_CAUSE = 71,
+ GSM0808_IE_LCS_CLIENT_TYPE = 72,
+ GSM0808_IE_APDU = 73,
+ GSM0808_IE_NETWORK_ELEMENT_IDENTITY = 74,
+ GSM0808_IE_GPS_ASSISTANCE_DATA = 75,
+ GSM0808_IE_DECIPHERING_KEYS = 76,
+ GSM0808_IE_RETURN_ERROR_RQST = 77,
+ GSM0808_IE_RETURN_ERROR_CAUSE = 78,
+ GSM0808_IE_SEGMENTATION = 79,
+ GSM0808_IE_SERVICE_HANDOVER = 80,
+ GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_UMTS = 81,
+ GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_CDMA2000= 82,
+ GSM0808_IE_RESERVED_5 = 65,
+ GSM0808_IE_RESERVED_6 = 66,
+};
+
+enum gsm0808_cause {
+ GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE = 0,
+ GSM0808_CAUSE_RADIO_INTERFACE_FAILURE = 1,
+ GSM0808_CAUSE_UPLINK_QUALITY = 2,
+ GSM0808_CAUSE_UPLINK_STRENGTH = 3,
+ GSM0808_CAUSE_DOWNLINK_QUALITY = 4,
+ GSM0808_CAUSE_DOWNLINK_STRENGTH = 5,
+ GSM0808_CAUSE_DISTANCE = 6,
+ GSM0808_CAUSE_O_AND_M_INTERVENTION = 7,
+ GSM0808_CAUSE_RESPONSE_TO_MSC_INVOCATION = 8,
+ GSM0808_CAUSE_CALL_CONTROL = 9,
+ GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION = 10,
+ GSM0808_CAUSE_HANDOVER_SUCCESSFUL = 11,
+ GSM0808_CAUSE_BETTER_CELL = 12,
+ GSM0808_CAUSE_DIRECTED_RETRY = 13,
+ GSM0808_CAUSE_JOINED_GROUP_CALL_CHANNEL = 14,
+ GSM0808_CAUSE_TRAFFIC = 15,
+ GSM0808_CAUSE_EQUIPMENT_FAILURE = 32,
+ GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE = 33,
+ GSM0808_CAUSE_RQSTED_TERRESTRIAL_RESOURCE_UNAVAILABLE = 34,
+ GSM0808_CAUSE_CCCH_OVERLOAD = 35,
+ GSM0808_CAUSE_PROCESSOR_OVERLOAD = 36,
+ GSM0808_CAUSE_BSS_NOT_EQUIPPED = 37,
+ GSM0808_CAUSE_MS_NOT_EQUIPPED = 38,
+ GSM0808_CAUSE_INVALID_CELL = 39,
+ GSM0808_CAUSE_TRAFFIC_LOAD = 40,
+ GSM0808_CAUSE_PREEMPTION = 41,
+ GSM0808_CAUSE_RQSTED_TRANSCODING_RATE_ADAPTION_UNAVAILABLE = 48,
+ GSM0808_CAUSE_CIRCUIT_POOL_MISMATCH = 49,
+ GSM0808_CAUSE_SWITCH_CIRCUIT_POOL = 50,
+ GSM0808_CAUSE_RQSTED_SPEECH_VERSION_UNAVAILABLE = 51,
+ GSM0808_CAUSE_LSA_NOT_ALLOWED = 52,
+ GSM0808_CAUSE_CIPHERING_ALGORITHM_NOT_SUPPORTED = 64,
+ GSM0808_CAUSE_TERRESTRIAL_CIRCUIT_ALREADY_ALLOCATED = 80,
+ GSM0808_CAUSE_INVALID_MESSAGE_CONTENTS = 81,
+ GSM0808_CAUSE_INFORMATION_ELEMENT_OR_FIELD_MISSING = 82,
+ GSM0808_CAUSE_INCORRECT_VALUE = 83,
+ GSM0808_CAUSE_UNKNOWN_MESSAGE_TYPE = 84,
+ GSM0808_CAUSE_UNKNOWN_INFORMATION_ELEMENT = 85,
+ GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC = 96,
+};
+
+/* GSM 08.08 3.2.2.11 Channel Type */
+enum gsm0808_chan_indicator {
+ GSM0808_CHAN_SPEECH = 1,
+ GSM0808_CHAN_DATA = 2,
+ GSM0808_CHAN_SIGN = 3,
+};
+
+enum gsm0808_chan_rate_type_data {
+ GSM0808_DATA_FULL_BM = 0x8,
+ GSM0808_DATA_HALF_LM = 0x9,
+ GSM0808_DATA_FULL_RPREF = 0xa,
+ GSM0808_DATA_HALF_PREF = 0xb,
+ GSM0808_DATA_FULL_PREF_NO_CHANGE = 0x1a,
+ GSM0808_DATA_HALF_PREF_NO_CHANGE = 0x1b,
+ GSM0808_DATA_MULTI_MASK = 0x20,
+ GSM0808_DATA_MULTI_MASK_NO_CHANGE = 0x30,
+};
+
+enum gsm0808_chan_rate_type_speech {
+ GSM0808_SPEECH_FULL_BM = 0x8,
+ GSM0808_SPEECH_HALF_LM = 0x9,
+ GSM0808_SPEECH_FULL_PREF= 0xa,
+ GSM0808_SPEECH_HALF_PREF= 0xb,
+ GSM0808_SPEECH_FULL_PREF_NO_CHANGE = 0x1a,
+ GSM0808_SPEECH_HALF_PREF_NO_CHANGE = 0x1b,
+ GSM0808_SPEECH_PERM = 0xf,
+ GSM0808_SPEECH_PERM_NO_CHANGE = 0x1f,
+};
+
+enum gsm0808_permitted_speech {
+ GSM0808_PERM_FR1 = 0x01,
+ GSM0808_PERM_FR2 = 0x11,
+ GSM0808_PERM_FR3 = 0x21,
+ GSM0808_PERM_HR1 = GSM0808_PERM_FR1 | 0x4,
+ GSM0808_PERM_HR2 = GSM0808_PERM_FR2 | 0x4,
+ GSM0808_PERM_HR3 = GSM0808_PERM_FR3 | 0x4,
+};
+
+int bssmap_rcvmsg_dt1(struct sccp_connection *conn, struct msgb *msg, unsigned int length);
+int bssmap_rcvmsg_udt(struct gsm_network *net, struct msgb *msg, unsigned int length);
+
+struct msgb *bssmap_create_layer3(struct msgb *msg);
+struct msgb *bssmap_create_reset(void);
+struct msgb *bssmap_create_clear_complete(void);
+struct msgb *bssmap_create_cipher_complete(struct msgb *layer3);
+struct msgb *bssmap_create_cipher_reject(u_int8_t cause);
+struct msgb *bssmap_create_sapi_reject(u_int8_t link_id);
+struct msgb *bssmap_create_assignment_completed(struct gsm_lchan *lchan, u_int8_t rr_cause);
+struct msgb *bssmap_create_assignment_failure(u_int8_t cause, u_int8_t *rr_cause);
+struct msgb *bssmap_create_classmark_update(const u_int8_t *classmark, u_int8_t length);
+
+void gsm0808_send_assignment_failure(struct gsm_lchan *l, u_int8_t cause, u_int8_t *rr_value);
+void gsm0808_send_assignment_compl(struct gsm_lchan *l, u_int8_t rr_value);
+
+int dtap_rcvmsg(struct gsm_lchan *lchan, struct msgb *msg, unsigned int length);
+struct msgb *dtap_create_msg(struct msgb *msg_l3, u_int8_t link_id);
+
+void bsc_queue_connection_write(struct sccp_connection *conn, struct msgb *msg);
+void bsc_free_queued(struct sccp_connection *conn);
+void bsc_send_queued(struct sccp_connection *conn);
+
+void bts_queue_send(struct msgb *msg, int link_id);
+void bts_send_queued(struct bss_sccp_connection_data*);
+void bts_free_queued(struct bss_sccp_connection_data*);
+void bts_unblock_queue(struct bss_sccp_connection_data*);
+
+const struct tlv_definition *gsm0808_att_tlvdef();
+
+#endif
diff --git a/include/openbsc_nat/tlv.h b/include/openbsc_nat/tlv.h
new file mode 100644
index 0000000..0fa8e40
--- /dev/null
+++ b/include/openbsc_nat/tlv.h
@@ -0,0 +1,234 @@
+#ifndef _TLV_H
+#define _TLV_H
+
+#include <sys/types.h>
+#include <string.h>
+
+#include <laf0rge1/msgb.h>
+
+/* Terminology / wording
+ tag length value (in bits)
+
+ V - - 8
+ LV - 8 N * 8
+ TLV 8 8 N * 8
+ TL16V 8 16 N * 8
+ TLV16 8 8 N * 16
+ TvLV 8 8/16 N * 8
+
+*/
+
+#define LV_GROSS_LEN(x) (x+1)
+#define TLV_GROSS_LEN(x) (x+2)
+#define TLV16_GROSS_LEN(x) ((2*x)+2)
+#define TL16V_GROSS_LEN(x) (x+3)
+#define L16TV_GROSS_LEN(x) (x+3)
+
+#define TVLV_MAX_ONEBYTE 0x7f
+
+static inline u_int16_t TVLV_GROSS_LEN(u_int16_t len)
+{
+ if (len <= TVLV_MAX_ONEBYTE)
+ return TLV_GROSS_LEN(len);
+ else
+ return TL16V_GROSS_LEN(len);
+}
+
+/* TLV generation */
+
+static inline u_int8_t *lv_put(u_int8_t *buf, u_int8_t len,
+ const u_int8_t *val)
+{
+ *buf++ = len;
+ memcpy(buf, val, len);
+ return buf + len;
+}
+
+static inline u_int8_t *tlv_put(u_int8_t *buf, u_int8_t tag, u_int8_t len,
+ const u_int8_t *val)
+{
+ *buf++ = tag;
+ *buf++ = len;
+ memcpy(buf, val, len);
+ return buf + len;
+}
+
+static inline u_int8_t *tlv16_put(u_int8_t *buf, u_int8_t tag, u_int8_t len,
+ const u_int16_t *val)
+{
+ *buf++ = tag;
+ *buf++ = len;
+ memcpy(buf, val, len*2);
+ return buf + len*2;
+}
+
+static inline u_int8_t *tl16v_put(u_int8_t *buf, u_int8_t tag, u_int16_t len,
+ const u_int8_t *val)
+{
+ *buf++ = tag;
+ *buf++ = len >> 8;
+ *buf++ = len & 0xff;
+ memcpy(buf, val, len);
+ return buf + len*2;
+}
+
+static inline u_int8_t *tvlv_put(u_int8_t *buf, u_int8_t tag, u_int16_t len,
+ const u_int8_t *val)
+{
+ u_int8_t *ret;
+
+ if (len <= TVLV_MAX_ONEBYTE) {
+ ret = tlv_put(buf, tag, len, val);
+ buf[1] |= 0x80;
+ } else
+ ret = tl16v_put(buf, tag, len, val);
+
+ return ret;
+}
+
+static inline u_int8_t *msgb_tlv16_put(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int16_t *val)
+{
+ u_int8_t *buf = msgb_put(msg, TLV16_GROSS_LEN(len));
+ return tlv16_put(buf, tag, len, val);
+}
+
+static inline u_int8_t *msgb_tl16v_put(struct msgb *msg, u_int8_t tag, u_int16_t len,
+ const u_int8_t *val)
+{
+ u_int8_t *buf = msgb_put(msg, TL16V_GROSS_LEN(len));
+ return tl16v_put(buf, tag, len, val);
+}
+
+static inline u_int8_t *msgb_tvlv_put(struct msgb *msg, u_int8_t tag, u_int16_t len,
+ const u_int8_t *val)
+{
+ u_int8_t *buf = msgb_put(msg, TVLV_GROSS_LEN(len));
+ return tvlv_put(buf, tag, len, val);
+}
+
+static inline u_int8_t *msgb_l16tv_put(struct msgb *msg, u_int16_t len, u_int8_t tag,
+ const u_int8_t *val)
+{
+ u_int8_t *buf = msgb_put(msg, L16TV_GROSS_LEN(len));
+
+ *buf++ = len >> 8;
+ *buf++ = len & 0xff;
+ *buf++ = tag;
+ memcpy(buf, val, len);
+ return buf + len;
+}
+
+static inline u_int8_t *v_put(u_int8_t *buf, u_int8_t val)
+{
+ *buf++ = val;
+ return buf;
+}
+
+static inline u_int8_t *tv_put(u_int8_t *buf, u_int8_t tag,
+ u_int8_t val)
+{
+ *buf++ = tag;
+ *buf++ = val;
+ return buf;
+}
+
+/* 'val' is still in host byte order! */
+static inline u_int8_t *tv16_put(u_int8_t *buf, u_int8_t tag,
+ u_int16_t val)
+{
+ *buf++ = tag;
+ *buf++ = val >> 8;
+ *buf++ = val & 0xff;
+ return buf;
+}
+
+static inline u_int8_t *msgb_lv_put(struct msgb *msg, u_int8_t len, const u_int8_t *val)
+{
+ u_int8_t *buf = msgb_put(msg, LV_GROSS_LEN(len));
+ return lv_put(buf, len, val);
+}
+
+static inline u_int8_t *msgb_tlv_put(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int8_t *val)
+{
+ u_int8_t *buf = msgb_put(msg, TLV_GROSS_LEN(len));
+ return tlv_put(buf, tag, len, val);
+}
+
+static inline u_int8_t *msgb_tv_put(struct msgb *msg, u_int8_t tag, u_int8_t val)
+{
+ u_int8_t *buf = msgb_put(msg, 2);
+ return tv_put(buf, tag, val);
+}
+
+static inline u_int8_t *msgb_v_put(struct msgb *msg, u_int8_t val)
+{
+ u_int8_t *buf = msgb_put(msg, 1);
+ return v_put(buf, val);
+}
+
+static inline u_int8_t *msgb_tv16_put(struct msgb *msg, u_int8_t tag, u_int16_t val)
+{
+ u_int8_t *buf = msgb_put(msg, 3);
+ return tv16_put(buf, tag, val);
+}
+
+static inline u_int8_t *msgb_tlv_push(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int8_t *val)
+{
+ u_int8_t *buf = msgb_push(msg, TLV_GROSS_LEN(len));
+ return tlv_put(buf, tag, len, val);
+}
+
+static inline u_int8_t *msgb_tv_push(struct msgb *msg, u_int8_t tag, u_int8_t val)
+{
+ u_int8_t *buf = msgb_push(msg, 2);
+ return tv_put(buf, tag, val);
+}
+
+static inline u_int8_t *msgb_tv16_push(struct msgb *msg, u_int8_t tag, u_int16_t val)
+{
+ u_int8_t *buf = msgb_push(msg, 3);
+ return tv16_put(buf, tag, val);
+}
+
+/* TLV parsing */
+
+struct tlv_p_entry {
+ u_int16_t len;
+ const u_int8_t *val;
+};
+
+enum tlv_type {
+ TLV_TYPE_FIXED,
+ TLV_TYPE_T,
+ TLV_TYPE_TV,
+ TLV_TYPE_TLV,
+ TLV_TYPE_TL16V,
+ TLV_TYPE_TvLV,
+};
+
+struct tlv_def {
+ enum tlv_type type;
+ u_int8_t fixed_len;
+};
+
+struct tlv_definition {
+ struct tlv_def def[0xff];
+};
+
+struct tlv_parsed {
+ struct tlv_p_entry lv[0xff];
+};
+
+extern struct tlv_definition tvlv_att_def;
+
+int tlv_parse_one(u_int8_t *o_tag, u_int16_t *o_len, const u_int8_t **o_val,
+ const struct tlv_definition *def,
+ const u_int8_t *buf, int buf_len);
+int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def,
+ const u_int8_t *buf, int buf_len, u_int8_t lv_tag, u_int8_t lv_tag2);
+
+#define TLVP_PRESENT(x, y) ((x)->lv[y].val)
+#define TLVP_LEN(x, y) (x)->lv[y].len
+#define TLVP_VAL(x, y) (x)->lv[y].val
+
+#endif /* _TLV_H */
diff --git a/include/snmp_mtp.h b/include/snmp_mtp.h
new file mode 100644
index 0000000..6a70a5c
--- /dev/null
+++ b/include/snmp_mtp.h
@@ -0,0 +1,39 @@
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (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 snmp_mtp_h
+#define snmp_mtp_h
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/utilities.h>
+#include <net-snmp/net-snmp-includes.h>
+
+struct snmp_mtp_session {
+ netsnmp_session session, *ss;
+};
+
+void snmp_mtp_start_c7_datalink(struct snmp_mtp_session *, int link_id);
+void snmp_mtp_stop_c7_datalink(struct snmp_mtp_session *, int link_id);
+
+struct snmp_mtp_session *snmp_mtp_session_create(char *host);
+void snmp_mtp_deactivate(struct snmp_mtp_session *);
+void snmp_mtp_activate(struct snmp_mtp_session *);
+
+#endif
diff --git a/include/thread.h b/include/thread.h
new file mode 100644
index 0000000..f23cae7
--- /dev/null
+++ b/include/thread.h
@@ -0,0 +1,59 @@
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (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 thread_h
+#define thread_h
+
+#include <laf0rge1/linuxlist.h>
+#include <laf0rge1/select.h>
+
+#include <pthread.h>
+
+/**
+ * routines for dealing with threads
+ */
+struct thread_notifier {
+ struct bsc_fd bfd;
+
+ int no_write;
+ int fd[2];
+
+ pthread_mutex_t guard;
+ struct llist_head *main_head;
+ struct llist_head *thread_head;
+
+ struct llist_head __head1;
+ struct llist_head __head2;
+};
+
+struct thread_notifier *thread_notifier_alloc();
+
+/**
+ * atomically swap two llist heads. This can be used
+ * to have two queues of data and then swap them for
+ * processing.
+ */
+void thread_swap(struct thread_notifier *);
+
+void thread_safe_add(struct thread_notifier *, struct llist_head *_new);
+
+void thread_init(void);
+
+#endif
diff --git a/include/udp_input.h b/include/udp_input.h
new file mode 100644
index 0000000..1715733
--- /dev/null
+++ b/include/udp_input.h
@@ -0,0 +1,52 @@
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (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.
+ *
+ */
+/* UDP Input for the SNMP On-Waves packets */
+
+#ifndef c7_udp_input_h
+#define c7_udp_input_h
+
+#include <stdint.h>
+#include "write_queue.h"
+
+#define UDP_FORMAT_SIMPLE_UDP 2
+#define UDP_FORMAT_SIMPLE_TCP 3
+
+#define UDP_DATA_MSU_PRIO_0 0
+#define UDP_DATA_MSU_PRIO_1 1
+#define UDP_DATA_MSU_PRIO_2 2
+#define UDP_DATA_MSU_PRIO_3 3
+#define UDP_DATA_RETR_PRIO_0 16
+#define UDP_DATA_RETR_PRIO_1 17
+#define UDP_DATA_RETR_PRIO_2 18
+#define UDP_DATA_RETR_PRIO_3 19
+#define UDP_DATA_RETR_COMPL 32
+#define UDP_DATA_RETR_IMPOS 33
+
+struct udp_data_hdr {
+ uint8_t format_type;
+ uint8_t data_type;
+ uint16_t data_link_index;
+ uint32_t user_context;
+ uint32_t data_length;
+ uint8_t data[0];
+} __attribute__((packed));
+
+#endif
diff --git a/include/write_queue.h b/include/write_queue.h
new file mode 100644
index 0000000..45191e0
--- /dev/null
+++ b/include/write_queue.h
@@ -0,0 +1,48 @@
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (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.
+ *
+ */
+/* Generic write queue implementation */
+#ifndef write_queue_h
+#define write_queue_h
+
+#include <laf0rge1/select.h>
+#include <laf0rge1/msgb.h>
+
+struct write_queue {
+ struct bsc_fd bfd;
+ unsigned int max_length;
+ unsigned int current_length;
+
+ unsigned int paused;
+
+ struct llist_head msg_queue;
+
+ int (*read_cb)(struct bsc_fd *fd);
+ int (*write_cb)(struct bsc_fd *fd, struct msgb *msg);
+};
+
+void write_queue_init(struct write_queue *queue, int max_length);
+int write_queue_enqueue(struct write_queue *queue, struct msgb *data);
+int write_queue_bfd_cb(struct bsc_fd *fd, unsigned int what);
+
+void write_queue_pause(struct write_queue *queue);
+void write_queue_unpause(struct write_queue *queue);
+
+#endif