[GPRS] Add Frame Relay in GRE encapsulation for NS
This commit is contained in:
parent
3a318ab971
commit
5540c4cbd3
|
@ -13,6 +13,8 @@ struct gbproxy_config {
|
|||
u_int32_t nsip_listen_ip;
|
||||
u_int16_t nsip_listen_port;
|
||||
|
||||
int frgre_enabled;
|
||||
|
||||
u_int16_t nsip_sgsn_nsei;
|
||||
|
||||
/* misc */
|
||||
|
|
|
@ -107,6 +107,7 @@ enum ns_timeout {
|
|||
enum gprs_ns_ll {
|
||||
GPRS_NS_LL_UDP,
|
||||
GPRS_NS_LL_E1,
|
||||
GPRS_NS_LL_FR_GRE,
|
||||
};
|
||||
|
||||
enum gprs_ns_evt {
|
||||
|
@ -130,15 +131,14 @@ struct gprs_ns_inst {
|
|||
|
||||
uint16_t timeout[NS_TIMERS_COUNT];
|
||||
|
||||
/* which link-layer are we based on? */
|
||||
enum gprs_ns_ll ll;
|
||||
|
||||
union {
|
||||
/* NS-over-IP specific bits */
|
||||
struct {
|
||||
struct bsc_fd fd;
|
||||
} nsip;
|
||||
};
|
||||
/* NS-over-IP specific bits */
|
||||
struct {
|
||||
struct bsc_fd fd;
|
||||
} nsip;
|
||||
/* NS-over-FR-over-GRE-over-IP specific bits */
|
||||
struct {
|
||||
struct bsc_fd fd;
|
||||
} frgre;
|
||||
};
|
||||
|
||||
enum nsvc_timer_mode {
|
||||
|
@ -168,10 +168,16 @@ struct gprs_nsvc {
|
|||
|
||||
struct rate_ctr_group *ctrg;
|
||||
|
||||
/* which link-layer are we based on? */
|
||||
enum gprs_ns_ll ll;
|
||||
|
||||
union {
|
||||
struct {
|
||||
struct sockaddr_in bts_addr;
|
||||
} ip;
|
||||
struct {
|
||||
struct sockaddr_in bts_addr;
|
||||
} frgre;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -181,15 +187,11 @@ struct gprs_ns_inst *gprs_ns_instantiate(gprs_ns_cb_t *cb);
|
|||
/* Destroy a NS protocol instance */
|
||||
void gprs_ns_destroy(struct gprs_ns_inst *nsi);
|
||||
|
||||
/* Listen for incoming GPRS packets */
|
||||
int nsip_listen(struct gprs_ns_inst *nsi, uint16_t udp_port);
|
||||
/* Listen for incoming GPRS packets via NS/UDP */
|
||||
int nsip_listen(struct gprs_ns_inst *nsi, uint32_t ip, uint16_t udp_port);
|
||||
|
||||
struct sockaddr_in;
|
||||
|
||||
/* main entry point, here incoming NS frames enter */
|
||||
int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
|
||||
struct sockaddr_in *saddr);
|
||||
|
||||
/* main function for higher layers (BSSGP) to send NS messages */
|
||||
int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg);
|
||||
|
||||
|
@ -197,8 +199,8 @@ int gprs_ns_tx_reset(struct gprs_nsvc *nsvc, uint8_t cause);
|
|||
int gprs_ns_tx_block(struct gprs_nsvc *nsvc, uint8_t cause);
|
||||
int gprs_ns_tx_unblock(struct gprs_nsvc *nsvc);
|
||||
|
||||
/* Listen for incoming GPRS packets */
|
||||
int nsip_listen(struct gprs_ns_inst *nsi, uint16_t udp_port);
|
||||
/* Listen for incoming GPRS packets via NS/FR/GRE */
|
||||
int gprs_ns_frgre_listen(struct gprs_ns_inst *nsi, uint32_t ip);
|
||||
|
||||
/* Establish a connection (from the BSS) to the SGSN */
|
||||
struct gprs_nsvc *nsip_connect(struct gprs_ns_inst *nsi,
|
||||
|
@ -216,4 +218,7 @@ int gprs_nsvc_reset(struct gprs_nsvc *nsvc, uint8_t cause);
|
|||
/* Add NS-specific VTY stuff */
|
||||
int gprs_ns_vty_init(struct gprs_ns_inst *nsi);
|
||||
|
||||
#define NS_ALLOC_SIZE 1024
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#define IPPROTO_GRE 47
|
||||
#endif
|
||||
|
||||
int make_sock(struct bsc_fd *bfd, int proto, u_int16_t port,
|
||||
int make_sock(struct bsc_fd *bfd, int proto, u_int32_t ip, u_int16_t port,
|
||||
int (*cb)(struct bsc_fd *fd, unsigned int what));
|
||||
|
||||
#endif /* _BSC_SOCKET_H */
|
||||
|
|
|
@ -2,23 +2,24 @@ INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
|
|||
AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS)
|
||||
AM_LDFLAGS = $(LIBOSMOCORE_LIBS)
|
||||
|
||||
noinst_LIBRARIES = libgb.a
|
||||
|
||||
if HAVE_LIBGTP
|
||||
sbin_PROGRAMS = osmo-gbproxy osmo-sgsn
|
||||
noinst_LIBRARIES = libsgsn.a
|
||||
else
|
||||
sbin_PROGRAMS = osmo-gbproxy
|
||||
endif
|
||||
|
||||
|
||||
libsgsn_a_SOURCES = gprs_ns.c gprs_bssgp.c gprs_llc.c gprs_gmm.c \
|
||||
crc24.c gprs_sgsn.c gprs_bssgp_util.c gprs_bssgp_vty.c \
|
||||
gprs_llc_vty.c
|
||||
libgb_a_SOURCES = gprs_ns.c gprs_ns_frgre.c gprs_ns_vty.c \
|
||||
gprs_bssgp.c gprs_bssgp_util.c gprs_bssgp_vty.c \
|
||||
gprs_llc.c gprs_llc_vty.c crc24.c
|
||||
|
||||
osmo_gbproxy_SOURCES = gb_proxy.c gb_proxy_main.c gb_proxy_vty.c \
|
||||
gprs_ns.c gprs_ns_vty.c gprs_bssgp_util.c \
|
||||
$(top_srcdir)/src/socket.c $(top_srcdir)/src/debug.c
|
||||
osmo_gbproxy_LDADD = $(top_builddir)/src/libvty.a
|
||||
osmo_gbproxy_LDADD = libgb.a $(top_builddir)/src/libvty.a
|
||||
|
||||
osmo_sgsn_SOURCES = sgsn_main.c sgsn_vty.c gprs_ns_vty.c sgsn_libgtp.c \
|
||||
osmo_sgsn_SOURCES = gprs_gmm.c gprs_sgsn.c \
|
||||
sgsn_main.c sgsn_vty.c sgsn_libgtp.c \
|
||||
$(top_srcdir)/src/socket.c $(top_srcdir)/src/debug.c
|
||||
osmo_sgsn_LDADD = $(top_builddir)/src/libvty.a libsgsn.a -lgtp
|
||||
osmo_sgsn_LDADD = libgb.a $(top_builddir)/src/libvty.a -lgtp
|
||||
|
|
|
@ -583,7 +583,7 @@ gDEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy",
|
|||
"RAC %u-%u-%u-%u%s",
|
||||
nsvc->nsei, nsvc->nsvci, peer->bvci,
|
||||
raid.mcc, raid.mnc, raid.lac, raid.rac, VTY_NEWLINE);
|
||||
if (nsvc->nsi->ll == GPRS_NS_LL_UDP)
|
||||
if (nsvc->ll == GPRS_NS_LL_UDP)
|
||||
vty_out(vty, " remote address %s:%u%s",
|
||||
inet_ntoa(nsvc->ip.bts_addr.sin_addr),
|
||||
ntohs(nsvc->ip.bts_addr.sin_port), VTY_NEWLINE);
|
||||
|
|
|
@ -238,12 +238,22 @@ int main(int argc, char **argv)
|
|||
exit(2);
|
||||
}
|
||||
|
||||
rc = nsip_listen(bssgp_nsi, gbcfg.nsip_listen_port);
|
||||
rc = nsip_listen(bssgp_nsi, gbcfg.nsip_listen_ip,
|
||||
gbcfg.nsip_listen_port);
|
||||
if (rc < 0) {
|
||||
LOGP(DGPRS, LOGL_FATAL, "Cannot bind/listen on NSIP socket\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (gbcfg.frgre_enabled) {
|
||||
rc = gprs_ns_frgre_listen(bssgp_nsi, gbcfg.nsip_listen_ip);
|
||||
if (rc < 0) {
|
||||
LOGP(DGPRS, LOGL_FATAL, "Cannot bind/listen GRE "
|
||||
"socket. Do you have CAP_NET_RAW?\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset all the persistent NS-VCs that we've read from the config */
|
||||
gbprox_reset_persistent_nsvcs(bssgp_nsi);
|
||||
|
||||
|
|
|
@ -70,8 +70,6 @@
|
|||
#include <openbsc/gprs_ns.h>
|
||||
#include <openbsc/gprs_bssgp.h>
|
||||
|
||||
#define NS_ALLOC_SIZE 1024
|
||||
|
||||
static const struct tlv_definition ns_att_tlvdef = {
|
||||
.def = {
|
||||
[NS_IE_CAUSE] = { TLV_TYPE_TvLV, 0 },
|
||||
|
@ -204,6 +202,7 @@ const char *gprs_ns_cause_str(enum ns_cause cause)
|
|||
}
|
||||
|
||||
static int nsip_sendmsg(struct gprs_nsvc *nsvc, struct msgb *msg);
|
||||
extern int grps_ns_frgre_sendmsg(struct gprs_nsvc *nsvc, struct msgb *msg);
|
||||
|
||||
static int gprs_ns_tx(struct gprs_nsvc *nsvc, struct msgb *msg)
|
||||
{
|
||||
|
@ -215,12 +214,15 @@ static int gprs_ns_tx(struct gprs_nsvc *nsvc, struct msgb *msg)
|
|||
rate_ctr_inc(&nsvc->ctrg->ctr[NS_CTR_PKTS_OUT]);
|
||||
rate_ctr_add(&nsvc->ctrg->ctr[NS_CTR_BYTES_OUT], msgb_l2len(msg));
|
||||
|
||||
switch (nsvc->nsi->ll) {
|
||||
switch (nsvc->ll) {
|
||||
case GPRS_NS_LL_UDP:
|
||||
ret = nsip_sendmsg(nsvc, msg);
|
||||
break;
|
||||
case GPRS_NS_LL_FR_GRE:
|
||||
ret = gprs_ns_frgre_sendmsg(nsvc, msg);
|
||||
break;
|
||||
default:
|
||||
LOGP(DNS, LOGL_ERROR, "unsupported NS linklayer %u\n", nsvc->nsi->ll);
|
||||
LOGP(DNS, LOGL_ERROR, "unsupported NS linklayer %u\n", nsvc->ll);
|
||||
msgb_free(msg);
|
||||
ret = -EIO;
|
||||
break;
|
||||
|
@ -644,7 +646,7 @@ static int gprs_ns_rx_block(struct gprs_nsvc *nsvc, struct msgb *msg)
|
|||
|
||||
/* main entry point, here incoming NS frames enter */
|
||||
int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
|
||||
struct sockaddr_in *saddr)
|
||||
struct sockaddr_in *saddr, enum gprs_ns_ll ll)
|
||||
{
|
||||
struct gprs_ns_hdr *nsh = (struct gprs_ns_hdr *) msg->l2h;
|
||||
struct gprs_nsvc *nsvc;
|
||||
|
@ -667,6 +669,7 @@ int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
|
|||
nsvc->nsvci = nsvc->nsei = 0xfffe;
|
||||
nsvc->ip.bts_addr = *saddr;
|
||||
nsvc->state = NSE_S_ALIVE;
|
||||
nsvc->ll = ll;
|
||||
#if 0
|
||||
return gprs_ns_tx_reset(nsvc, NS_CAUSE_PDU_INCOMP_PSTATE);
|
||||
#else
|
||||
|
@ -691,6 +694,7 @@ int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
|
|||
nsvc = nsvc_by_nsei(nsi, nsei);
|
||||
if (!nsvc) {
|
||||
nsvc = nsvc_create(nsi, 0xffff);
|
||||
nsvc->ll = ll;
|
||||
log_set_context(BSC_CTX_NSVC, nsvc);
|
||||
LOGP(DNS, LOGL_INFO, "Creating NS-VC for BSS at %s:%u\n",
|
||||
inet_ntoa(saddr->sin_addr), ntohs(saddr->sin_port));
|
||||
|
@ -858,7 +862,7 @@ static int handle_nsip_read(struct bsc_fd *bfd)
|
|||
if (!msg)
|
||||
return error;
|
||||
|
||||
error = gprs_ns_rcvmsg(nsi, msg, &saddr);
|
||||
error = gprs_ns_rcvmsg(nsi, msg, &saddr, GPRS_NS_LL_UDP);
|
||||
|
||||
msgb_free(msg);
|
||||
|
||||
|
@ -871,7 +875,7 @@ static int handle_nsip_write(struct bsc_fd *bfd)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
int nsip_sendmsg(struct gprs_nsvc *nsvc, struct msgb *msg)
|
||||
static int nsip_sendmsg(struct gprs_nsvc *nsvc, struct msgb *msg)
|
||||
{
|
||||
int rc;
|
||||
struct gprs_ns_inst *nsi = nsvc->nsi;
|
||||
|
@ -898,19 +902,15 @@ static int nsip_fd_cb(struct bsc_fd *bfd, unsigned int what)
|
|||
return rc;
|
||||
}
|
||||
|
||||
extern int make_sock(struct bsc_fd *bfd, int proto, uint16_t port,
|
||||
int (*cb)(struct bsc_fd *fd, unsigned int what));
|
||||
|
||||
/* Listen for incoming GPRS packets */
|
||||
int nsip_listen(struct gprs_ns_inst *nsi, uint16_t udp_port)
|
||||
int nsip_listen(struct gprs_ns_inst *nsi, uint32_t ip, uint16_t udp_port)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = make_sock(&nsi->nsip.fd, IPPROTO_UDP, udp_port, nsip_fd_cb);
|
||||
ret = make_sock(&nsi->nsip.fd, IPPROTO_UDP, ip, udp_port, nsip_fd_cb);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
nsi->ll = GPRS_NS_LL_UDP;
|
||||
nsi->nsip.fd.data = nsi;
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -0,0 +1,222 @@
|
|||
/* GPRS Networks Service (NS) messages on the Gb interface
|
||||
* 3GPP TS 08.16 version 8.0.1 Release 1999 / ETSI TS 101 299 V8.0.1 (2002-05) */
|
||||
|
||||
/* NS-over-FR-over-GRE implementation */
|
||||
|
||||
/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <osmocore/select.h>
|
||||
#include <osmocore/msgb.h>
|
||||
#include <osmocore/talloc.h>
|
||||
|
||||
#include <openbsc/socket.h>
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/gprs_ns.h>
|
||||
|
||||
#define GRE_PTYPE_FR 0x6559
|
||||
|
||||
struct gre_hdr {
|
||||
uint16_t flags;
|
||||
uint16_t ptype;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static struct msgb *read_nsfrgre_msg(struct bsc_fd *bfd, int *error,
|
||||
struct sockaddr_in *saddr)
|
||||
{
|
||||
struct msgb *msg = msgb_alloc(NS_ALLOC_SIZE, "Gb/NS/FR/GRE Rx");
|
||||
int ret = 0;
|
||||
socklen_t saddr_len = sizeof(*saddr);
|
||||
struct gre_hdr *greh;
|
||||
uint8_t *frh;
|
||||
uint32_t dlci;
|
||||
|
||||
if (!msg) {
|
||||
*error = -ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = recvfrom(bfd->fd, msg->data, NS_ALLOC_SIZE, 0,
|
||||
(struct sockaddr *)saddr, &saddr_len);
|
||||
if (ret < 0) {
|
||||
LOGP(DNS, LOGL_ERROR, "recv error %s during NS-FR-GRE recv\n",
|
||||
strerror(errno));
|
||||
*error = ret;
|
||||
return NULL;
|
||||
} else if (ret == 0) {
|
||||
msgb_free(msg);
|
||||
*error = ret;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
msgb_put(msg, ret);
|
||||
|
||||
if (msg->len < sizeof(*greh)) {
|
||||
LOGP(DNS, LOGL_ERROR, "Short GRE packet: %u bytes\n", msg->len);
|
||||
*error = -EIO;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
greh = (struct gre_hdr *) msg->data;
|
||||
if (greh->flags) {
|
||||
LOGP(DNS, LOGL_NOTICE, "Unknown GRE flags 0x%04x\n",
|
||||
ntohs(greh->flags));
|
||||
}
|
||||
if (greh->ptype != htons(GRE_PTYPE_FR)) {
|
||||
LOGP(DNS, LOGL_NOTICE, "Unknown GRE protocol 0x%04x != FR\n",
|
||||
ntohs(greh->ptype));
|
||||
*error = -EIO;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (msg->len < sizeof(*greh) + 2) {
|
||||
LOGP(DNS, LOGL_ERROR, "Short FR header: %u bytes\n", msg->len);
|
||||
*error = -EIO;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
frh = msg->data + sizeof(*greh);
|
||||
if (frh[0] & 0x01) {
|
||||
LOGP(DNS, LOGL_NOTICE, "Unsupported single-byte FR address\n");
|
||||
*error = -EIO;
|
||||
goto out_err;
|
||||
}
|
||||
dlci = (frh[0] & 0xfc << 2);
|
||||
if ((frh[1] & 0x0f) != 0x01) {
|
||||
LOGP(DNS, LOGL_NOTICE, "Unknown second FR octet 0x%02x\n",
|
||||
frh[1]);
|
||||
*error = -EIO;
|
||||
goto out_err;
|
||||
}
|
||||
dlci |= frh[1] >> 4;
|
||||
if (dlci > 0xffff) {
|
||||
LOGP(DNS, LOGL_ERROR, "We don't support DLCI > 65535 (%u)\n",
|
||||
dlci);
|
||||
*error = -EINVAL;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
msg->l2h = msg->data + sizeof(*greh) + 2;
|
||||
|
||||
/* Store DLCI in NETWORK BYTEORDER in sockaddr port member */
|
||||
saddr->sin_port = htons(dlci & 0xffff);
|
||||
|
||||
return msg;
|
||||
|
||||
out_err:
|
||||
msgb_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
|
||||
struct sockaddr_in *saddr, enum gprs_ns_ll ll);
|
||||
|
||||
static int handle_nsfrgre_read(struct bsc_fd *bfd)
|
||||
{
|
||||
int error;
|
||||
struct sockaddr_in saddr;
|
||||
struct gprs_ns_inst *nsi = bfd->data;
|
||||
struct msgb *msg = read_nsfrgre_msg(bfd, &error, &saddr);
|
||||
|
||||
if (!msg)
|
||||
return error;
|
||||
|
||||
error = gprs_ns_rcvmsg(nsi, msg, &saddr, GPRS_NS_LL_FR_GRE);
|
||||
|
||||
msgb_free(msg);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int handle_nsfrgre_write(struct bsc_fd *bfd)
|
||||
{
|
||||
/* FIXME: actually send the data here instead of nsip_sendmsg() */
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
int gprs_ns_frgre_sendmsg(struct gprs_nsvc *nsvc, struct msgb *msg)
|
||||
{
|
||||
int rc;
|
||||
struct gprs_ns_inst *nsi = nsvc->nsi;
|
||||
struct sockaddr_in daddr;
|
||||
uint16_t dlci = ntohs(nsvc->frgre.bts_addr.sin_port);
|
||||
uint8_t *frh;
|
||||
struct gre_hdr *greh;
|
||||
|
||||
/* Build socket address for the packet destionation */
|
||||
daddr.sin_addr = nsvc->frgre.bts_addr.sin_addr;
|
||||
daddr.sin_port = IPPROTO_GRE;
|
||||
|
||||
/* Prepend the FR header */
|
||||
frh = msgb_push(msg, sizeof(frh));
|
||||
frh[0] = (dlci >> 2) & 0xfc;
|
||||
frh[1] = (dlci & 0xf0) | 0x01;
|
||||
|
||||
/* Prepend the GRE header */
|
||||
greh = (struct gre_hdr *) msgb_push(msg, sizeof(*greh));
|
||||
greh->flags = 0;
|
||||
greh->ptype = GRE_PTYPE_FR;
|
||||
|
||||
rc = sendto(nsi->frgre.fd.fd, msg->data, msg->len, 0,
|
||||
(struct sockaddr *)&daddr, sizeof(daddr));
|
||||
|
||||
talloc_free(msg);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int nsfrgre_fd_cb(struct bsc_fd *bfd, unsigned int what)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (what & BSC_FD_READ)
|
||||
rc = handle_nsfrgre_read(bfd);
|
||||
if (what & BSC_FD_WRITE)
|
||||
rc = handle_nsfrgre_write(bfd);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int gprs_ns_frgre_listen(struct gprs_ns_inst *nsi, uint32_t ip)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* Make sure we close any existing socket before changing it */
|
||||
if (nsi->frgre.fd.fd)
|
||||
close(nsi->frgre.fd.fd);
|
||||
|
||||
rc = make_sock(&nsi->frgre.fd, IPPROTO_GRE, ip, 0, nsfrgre_fd_cb);
|
||||
if (rc < 0) {
|
||||
LOGP(DNS, LOGL_ERROR, "Error creating GRE socket (%s)\n",
|
||||
strerror(errno));
|
||||
return rc;
|
||||
}
|
||||
nsi->frgre.fd.data = nsi;
|
||||
|
||||
return rc;
|
||||
}
|
|
@ -79,7 +79,10 @@ static int config_write_ns(struct vty *vty)
|
|||
vty_out(vty, " nse %u remote-role %s%s",
|
||||
nsvc->nsei, nsvc->remote_end_is_sgsn ? "sgsn" : "bss",
|
||||
VTY_NEWLINE);
|
||||
if (nsvc->nsi->ll == GPRS_NS_LL_UDP) {
|
||||
switch (nsvc->ll) {
|
||||
case GPRS_NS_LL_UDP:
|
||||
vty_out(vty, " nse %u encapsulation udp%s", nsvc->nsei,
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " nse %u remote-ip %s%s",
|
||||
nsvc->nsei,
|
||||
inet_ntoa(nsvc->ip.bts_addr.sin_addr),
|
||||
|
@ -87,6 +90,19 @@ static int config_write_ns(struct vty *vty)
|
|||
vty_out(vty, " nse %u remote-port %u%s",
|
||||
nsvc->nsei, ntohs(nsvc->ip.bts_addr.sin_port),
|
||||
VTY_NEWLINE);
|
||||
break;
|
||||
case GPRS_NS_LL_FR_GRE:
|
||||
vty_out(vty, " nse %u encapsulation framerelay-gre%s",
|
||||
nsvc->nsei, VTY_NEWLINE);
|
||||
vty_out(vty, " nse %u remote-ip %s%s",
|
||||
nsvc->nsei,
|
||||
inet_ntoa(nsvc->frgre.bts_addr.sin_addr),
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " nse %u fr-dlci %u%s",
|
||||
nsvc->nsei, ntohs(nsvc->frgre.bts_addr.sin_port),
|
||||
VTY_NEWLINE);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,8 +129,9 @@ static void dump_nse(struct vty *vty, struct gprs_nsvc *nsvc, int stats)
|
|||
nsvc->remote_end_is_sgsn ? "SGSN" : "BSS",
|
||||
nsvc->state & NSE_S_ALIVE ? "ALIVE" : "DEAD",
|
||||
nsvc->state & NSE_S_BLOCKED ? "BLOCKED" : "UNBLOCKED");
|
||||
if (nsvc->nsi->ll == GPRS_NS_LL_UDP)
|
||||
vty_out(vty, ", %15s:%u",
|
||||
if (nsvc->ll == GPRS_NS_LL_UDP || nsvc->ll == GPRS_NS_LL_FR_GRE)
|
||||
vty_out(vty, ", %s %15s:%u",
|
||||
nsvc->ll == GPRS_NS_LL_UDP ? "UDP" : "FR-GRE",
|
||||
inet_ntoa(nsvc->ip.bts_addr.sin_addr),
|
||||
ntohs(nsvc->ip.bts_addr.sin_port));
|
||||
vty_out(vty, "%s", VTY_NEWLINE);
|
||||
|
@ -243,11 +260,68 @@ DEFUN(cfg_nse_remoteport, cfg_nse_remoteport_cmd,
|
|||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (nsvc->ll != GPRS_NS_LL_UDP) {
|
||||
vty_out(vty, "Cannot set UDP Port on non-UDP NSE%s",
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
nsvc->ip.bts_addr.sin_port = htons(port);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_nse_fr_dlci, cfg_nse_fr_dlci_cmd,
|
||||
"nse <0-65535> fr-dlci <0-1023>",
|
||||
NSE_CMD_STR
|
||||
"Frame Relay DLCI\n"
|
||||
"Frame Relay DLCI Number\n")
|
||||
{
|
||||
uint16_t nsei = atoi(argv[0]);
|
||||
uint16_t dlci = atoi(argv[1]);
|
||||
struct gprs_nsvc *nsvc;
|
||||
|
||||
nsvc = nsvc_by_nsei(vty_nsi, nsei);
|
||||
if (!nsvc) {
|
||||
vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (nsvc->ll != GPRS_NS_LL_FR_GRE) {
|
||||
vty_out(vty, "Cannot set FR DLCI on non-FR NSE%s",
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
nsvc->frgre.bts_addr.sin_port = htons(dlci);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_nse_encaps, cfg_nse_encaps_cmd,
|
||||
"nse <0-65535> encapsulation (udp|framerelay-gre)",
|
||||
NSE_CMD_STR
|
||||
"Encapsulation for NS\n"
|
||||
"UDP/IP Encapsulation\n" "Frame-Relay/GRE/IP Encapsulation\n")
|
||||
{
|
||||
uint16_t nsei = atoi(argv[0]);
|
||||
struct gprs_nsvc *nsvc;
|
||||
|
||||
nsvc = nsvc_by_nsei(vty_nsi, nsei);
|
||||
if (!nsvc) {
|
||||
vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "udp"))
|
||||
nsvc->ll = GPRS_NS_LL_UDP;
|
||||
else
|
||||
nsvc->ll = GPRS_NS_LL_FR_GRE;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DEFUN(cfg_nse_remoterole, cfg_nse_remoterole_cmd,
|
||||
"nse <0-65535> remote-role (sgsn|bss)",
|
||||
NSE_CMD_STR
|
||||
|
@ -393,6 +467,8 @@ int gprs_ns_vty_init(struct gprs_ns_inst *nsi)
|
|||
install_element(NS_NODE, &cfg_nse_nsvci_cmd);
|
||||
install_element(NS_NODE, &cfg_nse_remoteip_cmd);
|
||||
install_element(NS_NODE, &cfg_nse_remoteport_cmd);
|
||||
install_element(NS_NODE, &cfg_nse_fr_dlci_cmd);
|
||||
install_element(NS_NODE, &cfg_nse_encaps_cmd);
|
||||
install_element(NS_NODE, &cfg_nse_remoterole_cmd);
|
||||
install_element(NS_NODE, &cfg_no_nse_cmd);
|
||||
install_element(NS_NODE, &cfg_ns_timer_cmd);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
!
|
||||
! OpenBSC configuration saved from vty
|
||||
! !
|
||||
! Osmocom Gb Proxy (0.9.0.404-6463) configuration saved from vty
|
||||
!!
|
||||
!
|
||||
line vty
|
||||
no login
|
||||
|
@ -13,3 +13,4 @@ ns
|
|||
nse 101 remote-ip 192.168.100.239
|
||||
nse 101 remote-port 7777
|
||||
nse 101 remote-role sgsn
|
||||
nse 101 encapsulation udp
|
||||
|
|
|
@ -175,7 +175,8 @@ int main(int argc, char **argv)
|
|||
if (rc)
|
||||
exit(2);
|
||||
|
||||
nsip_listen(sgsn_nsi, sgsn_inst.cfg.nsip_listen_port);
|
||||
nsip_listen(sgsn_nsi, sgsn_inst.cfg.nsip_listen_ip,
|
||||
sgsn_inst.cfg.nsip_listen_port);
|
||||
|
||||
while (1) {
|
||||
rc = bsc_select_main(0);
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include <openbsc/subchan_demux.h>
|
||||
#include <openbsc/e1_input.h>
|
||||
#include <openbsc/ipaccess.h>
|
||||
#include <openbsc/socket.h>
|
||||
#include <osmocore/talloc.h>
|
||||
|
||||
#define PRIV_OML 1
|
||||
|
@ -746,9 +747,6 @@ int ipaccess_connect(struct e1inp_line *line, struct sockaddr_in *sa)
|
|||
//return e1inp_line_register(line);
|
||||
}
|
||||
|
||||
extern int make_sock(struct bsc_fd *bfd, int proto, u_int16_t port,
|
||||
int (*cb)(struct bsc_fd *fd, unsigned int what));
|
||||
|
||||
int ipaccess_setup(struct gsm_network *gsmnet)
|
||||
{
|
||||
int ret;
|
||||
|
@ -766,13 +764,13 @@ int ipaccess_setup(struct gsm_network *gsmnet)
|
|||
e1h->gsmnet = gsmnet;
|
||||
|
||||
/* Listen for OML connections */
|
||||
ret = make_sock(&e1h->listen_fd, IPPROTO_TCP, IPA_TCP_PORT_OML,
|
||||
ret = make_sock(&e1h->listen_fd, IPPROTO_TCP, 0, IPA_TCP_PORT_OML,
|
||||
listen_fd_cb);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Listen for RSL connections */
|
||||
ret = make_sock(&e1h->rsl_listen_fd, IPPROTO_TCP,
|
||||
ret = make_sock(&e1h->rsl_listen_fd, IPPROTO_TCP, 0,
|
||||
IPA_TCP_PORT_RSL, rsl_listen_fd_cb);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#include <openbsc/gsm_data.h>
|
||||
#include <osmocore/talloc.h>
|
||||
|
||||
int make_sock(struct bsc_fd *bfd, int proto, u_int16_t port,
|
||||
int make_sock(struct bsc_fd *bfd, int proto, u_int32_t ip, u_int16_t port,
|
||||
int (*cb)(struct bsc_fd *fd, unsigned int what))
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
|
@ -75,7 +75,10 @@ int make_sock(struct bsc_fd *bfd, int proto, u_int16_t port,
|
|||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
if (ip)
|
||||
addr.sin_addr.s_addr = htonl(ip);
|
||||
else
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
||||
|
||||
|
|
Loading…
Reference in New Issue