diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h index ad0405fd6..40c88d216 100644 --- a/openbsc/include/openbsc/gb_proxy.h +++ b/openbsc/include/openbsc/gb_proxy.h @@ -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 */ diff --git a/openbsc/include/openbsc/gprs_ns.h b/openbsc/include/openbsc/gprs_ns.h index 08519f244..319ff3d3a 100644 --- a/openbsc/include/openbsc/gprs_ns.h +++ b/openbsc/include/openbsc/gprs_ns.h @@ -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 diff --git a/openbsc/include/openbsc/socket.h b/openbsc/include/openbsc/socket.h index f2e264ea6..4d3161146 100644 --- a/openbsc/include/openbsc/socket.h +++ b/openbsc/include/openbsc/socket.h @@ -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 */ diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am index d04b5cda3..3a014f73c 100644 --- a/openbsc/src/gprs/Makefile.am +++ b/openbsc/src/gprs/Makefile.am @@ -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 diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index 1fe9e9662..11e8d887a 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -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); diff --git a/openbsc/src/gprs/gb_proxy_main.c b/openbsc/src/gprs/gb_proxy_main.c index 68d07ae32..1b39a2e72 100644 --- a/openbsc/src/gprs/gb_proxy_main.c +++ b/openbsc/src/gprs/gb_proxy_main.c @@ -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); diff --git a/openbsc/src/gprs/gprs_ns.c b/openbsc/src/gprs/gprs_ns.c index 6d028aba1..4ef3603a3 100644 --- a/openbsc/src/gprs/gprs_ns.c +++ b/openbsc/src/gprs/gprs_ns.c @@ -70,8 +70,6 @@ #include #include -#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; diff --git a/openbsc/src/gprs/gprs_ns_frgre.c b/openbsc/src/gprs/gprs_ns_frgre.c new file mode 100644 index 000000000..d58c1d9da --- /dev/null +++ b/openbsc/src/gprs/gprs_ns_frgre.c @@ -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 + * + * 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 +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#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; +} diff --git a/openbsc/src/gprs/gprs_ns_vty.c b/openbsc/src/gprs/gprs_ns_vty.c index c20016aa5..7d439445a 100644 --- a/openbsc/src/gprs/gprs_ns_vty.c +++ b/openbsc/src/gprs/gprs_ns_vty.c @@ -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); diff --git a/openbsc/src/gprs/osmo_gbproxy.cfg b/openbsc/src/gprs/osmo_gbproxy.cfg index 29dbe93aa..79f391f2c 100644 --- a/openbsc/src/gprs/osmo_gbproxy.cfg +++ b/openbsc/src/gprs/osmo_gbproxy.cfg @@ -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 diff --git a/openbsc/src/gprs/sgsn_main.c b/openbsc/src/gprs/sgsn_main.c index 550f2bff0..63ef9f5f1 100644 --- a/openbsc/src/gprs/sgsn_main.c +++ b/openbsc/src/gprs/sgsn_main.c @@ -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); diff --git a/openbsc/src/input/ipaccess.c b/openbsc/src/input/ipaccess.c index 8e1832660..4968e8093 100644 --- a/openbsc/src/input/ipaccess.c +++ b/openbsc/src/input/ipaccess.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #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; diff --git a/openbsc/src/socket.c b/openbsc/src/socket.c index c72f6bc27..d60c43e01 100644 --- a/openbsc/src/socket.c +++ b/openbsc/src/socket.c @@ -41,7 +41,7 @@ #include #include -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));