Public release of the cellmgr_ng code to convert E1 to IPA SCCP
commit
97f66e2b53
|
@ -0,0 +1,4 @@
|
|||
AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6
|
||||
|
||||
INCLUDES = $(all_includes) -I$(top_srcdir)/include
|
||||
SUBDIRS = include src tests
|
|
@ -0,0 +1,75 @@
|
|||
== Building the cellmgr_ng ==
|
||||
|
||||
=== Requirements ===
|
||||
|
||||
==== OpenBSC ====
|
||||
The result of "make install" of OpenBSC is required. The cellmgr_ng is using
|
||||
the osmocomm and sccp library provided by OpenBSC.
|
||||
|
||||
==== NexusWare C7 =====
|
||||
The NexusWare C7 library must be available. It is used to communicate with
|
||||
MTP up to Level3.
|
||||
|
||||
==== NexusWare Uniporte ====
|
||||
The NexusWare Uniported library must be available. It is used to handle
|
||||
the configuration of the MGW.
|
||||
|
||||
|
||||
=== Configuring & Building ===
|
||||
The cellmgr_ng is using autoconf. At first the configure script must be
|
||||
generated, after this ./configure can be called. The configure script will
|
||||
use pkg-config to find the CFLAGS and LIBS for the Osmocomm, SCCP, NexusWare
|
||||
C7 and NexusWare Uniporte libraries.
|
||||
|
||||
The NexusWare libraries naturally do not come with pkg-config files. There
|
||||
are two example files in the pkg-config directory of the cellmgr_ng that can
|
||||
be changed to point to the proper paths. Alternatively the NEXUSWARE_C7_CFLAGS,
|
||||
NEXUSWARE_C7_LIBS, NEXUSWARE_UNIPORTE_CFLAGS, NEXUSWARE_UNIPORTE_LIBS environment
|
||||
variables can be set instead.
|
||||
|
||||
$ autoreconf --install --force
|
||||
$ export PKG_CONFIG_PATH=/openbsc/install/lib/pkg-config:$PWD/pkgconfig
|
||||
$ . /stuff/NexusWare/SETUP.SH
|
||||
$ ./configure --host=ppc-linux
|
||||
$ make
|
||||
|
||||
|
||||
|
||||
== Reset handling ==
|
||||
|
||||
=== Loss of the TCP connection to the MSC ===
|
||||
* All open SCCP connections need to be closed
|
||||
* All circuits allocated for voice calls need to be closed
|
||||
* On reconnect the cellmgr needs to generate the reset messages
|
||||
* The SCCP link is considered to be up
|
||||
|
||||
=== Loss of the MTP link/SLTM timeouts ===
|
||||
* We will have to generate a SCCP reset to the network
|
||||
* We will have to close ever voice call/mgcp and such
|
||||
|
||||
== Filtering ==
|
||||
=== Filtering reset acks ===
|
||||
For the above reset handling we filter the reset on both sides. Whenever
|
||||
we connect to the MSC or lose the BSC we send it a reset.
|
||||
|
||||
Whenever the BSC is sending us a reset we directly respond with a reset act
|
||||
|
||||
=== Filtering RLSD messages ===
|
||||
We are using the RLSD from the network and immediately reply with a RLC
|
||||
if we don't know about this combination of src and dest reference. If we
|
||||
do have a pair we set a flag and will send a RLC when we receive a RLC from
|
||||
the BSC.
|
||||
|
||||
If we receive a RLSD from the BSC we do have a bug as we didn't respond
|
||||
within a short enough timeout. We will close the connection. At which point
|
||||
we will handle the above.
|
||||
|
||||
The reason to handle RLSD is that the BSC has a rather short timeout from
|
||||
cleanup complete to wanting a RLSD and then the MSC and BSC will have some
|
||||
issues...
|
||||
|
||||
== Header Rewriting ==
|
||||
=== POI ===
|
||||
We do not want to have the point code indicator in the SCCP header. Currently
|
||||
we are removing this from the CR and DT1 messages.
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
cellmgr
|
||||
mtp dpc 1
|
||||
mtp opc 2
|
||||
mtp sltm once 0
|
||||
! commenting the next line switches to C7 mode
|
||||
udp dest ip 127.0.0.1
|
||||
udp dest port 5000
|
||||
udp src port 1313
|
||||
udp reset 3
|
||||
msc ip 127.0.0.1
|
||||
msc token hey
|
|
@ -0,0 +1,35 @@
|
|||
dnl Process this file with autoconf to produce a configure script
|
||||
AC_INIT
|
||||
|
||||
AM_INIT_AUTOMAKE(cellmgr_ng, 0.0.1)
|
||||
|
||||
dnl kernel style compile messages
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
|
||||
dnl checks for programs
|
||||
AC_PROG_MAKE_SET
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_RANLIB
|
||||
|
||||
dnl checks for header files
|
||||
AC_HEADER_STDC
|
||||
|
||||
dnl Check for the SNMP header
|
||||
AC_CHECK_HEADERS([net-snmp/net-snmp-config.h])
|
||||
|
||||
dnl Checks for typedefs, structures and compiler characteristics
|
||||
PKG_CHECK_MODULES([LAFORGE], [liblaf0rge1])
|
||||
PKG_CHECK_MODULES([SCCP], [libsccp])
|
||||
#PKG_CHECK_MODULES([NEXUSWARE_C7], [nexusware-c7])
|
||||
#PKG_CHECK_MODULES([NEXUSWARE_UNIPORTE], [nexusware-uniporte])
|
||||
|
||||
AC_OUTPUT(
|
||||
include/Makefile
|
||||
include/mgcp/Makefile
|
||||
include/openbsc_nat/Makefile
|
||||
src/Makefile
|
||||
tests/Makefile
|
||||
tests/mtp/Makefile
|
||||
tests/patching/Makefile
|
||||
Makefile)
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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 */
|
|
@ -0,0 +1 @@
|
|||
noinst_HEADERS = mgcp.h mgcp_internal.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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
noinst_HEADERS = bssap.h tlv.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
|
|
@ -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;
|