aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/osmo-ganc/ganc_server.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2012-06-23 21:58:41 +0200
committerHarald Welte <laforge@gnumonks.org>2015-11-15 14:04:06 +0100
commitda06516b26b459664ca4b5ea9e450dd76ac1d91f (patch)
tree04e87fbb47cef9726bd5063f3c7209f262c77d3a /openbsc/src/osmo-ganc/ganc_server.c
parent65482c919f82b28aa53cd519c4f7799b104051c0 (diff)
initial skeleton for accepting UMA/GAN connections
Diffstat (limited to 'openbsc/src/osmo-ganc/ganc_server.c')
-rw-r--r--openbsc/src/osmo-ganc/ganc_server.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/openbsc/src/osmo-ganc/ganc_server.c b/openbsc/src/osmo-ganc/ganc_server.c
new file mode 100644
index 000000000..b8153c9e5
--- /dev/null
+++ b/openbsc/src/osmo-ganc/ganc_server.c
@@ -0,0 +1,151 @@
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <arpa/inet.h>
+
+#include <osmocom/core/socket.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/tlv.h>
+#include <osmocom/gsm/protocol/gsm_44_318.h>
+
+#include "conn.h"
+#include "ganc_data.h"
+
+static struct msgb *unc_msgb_alloc(void)
+{
+ return msgb_alloc_headroom(1024+128, 128, "GANC Tx");
+}
+
+static int unc_peer_tx(struct gan_peer *peer, struct msgb *msg)
+{
+ return osmo_conn_enqueue(peer->conn, msg);
+}
+
+static int tx_unc_disco_acc(struct gan_peer *peer, const char *segw_host,
+ const char *ganc_host)
+{
+ struct msgb *msg = unc_msgb_alloc();
+ struct gan_rc_csr_hdr *gh = (struct gan_rc_csr_hdr*) msg->l2h;
+
+ if (!msg)
+ return -ENOMEM;
+
+ gh->pdisc = GA_PDISC_RC;
+ gh->msg_type = GA_MT_RC_DISCOVERY_ACCEPT;
+
+ msgb_tlv_put(msg, GA_IE_DEF_SEGW_FQDN, strlen(segw_host)+1, (uint8_t *) segw_host);
+ msgb_tlv_put(msg, GA_IE_DEF_GANC_FQDN, strlen(ganc_host)+1, (uint8_t *) ganc_host);
+
+ return unc_peer_tx(peer, msg);
+}
+
+static int rx_unc_discovery_req(struct gan_peer *peer, struct msgb *msg,
+ struct gan_rc_csr_hdr *gh)
+{
+ struct tlv_parsed tp;
+
+ tlv_parse(&tp, &tvlv_att_def, gh->data, msg->len - sizeof(*gh), 0, 0);
+
+ if (TLVP_PRESENT(&tp, GA_IE_MI)) {
+ char mi_string[32];
+ gsm48_mi_to_string(&mi_string, sizeof(mi_string),
+ TLVP_VAL(&tp, GA_IE_MI), TLVP_LEN(&tp, GA_IE_MI));
+
+ printf("DISCOVERY from %s\n", mi_string);
+ }
+
+ return tx_unc_disco_acc(peer, "segw.uma.sysmocom.de",
+ "ganc.uma.sysmocom.de");
+}
+
+static int rx_unc_rc(struct gan_peer *peer, struct msgb *msg, struct gan_rc_csr_hdr *gh)
+{
+ switch (gh->msg_type) {
+ case GA_MT_RC_DISCOVERY_REQUEST:
+ return rx_unc_discovery_req(peer, msg, gh);
+ case GA_MT_RC_REGISTER_REQUEST:
+ case GA_MT_RC_DEREGISTER:
+ break;
+ }
+
+ return 0;
+}
+
+static int rx_unc_msg(struct gan_peer *peer, struct msgb *msg)
+{
+ struct gan_rc_csr_hdr *gh = (struct gan_rc_csr_hdr *) msg->l2h;
+
+ printf("PDISC=%u TYPE=%u\n", gh->pdisc, gh->msg_type);
+
+ switch (gh->pdisc) {
+ case GA_PDISC_RC:
+ return rx_unc_rc(peer, msg, gh);
+ case GA_PDISC_CSR:
+ case GA_PDISC_PSR:
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int unc_read_cb(struct osmo_conn *conn)
+{
+ struct msgb *msg;
+ struct gan_rc_csr_hdr *gh;
+ int rc;
+
+ msg = msgb_alloc_headroom(1024 + 128, 128, "UNC Read");
+ if (!msg)
+ return -ENOMEM;
+
+ gh = (struct gan_rc_csr_hdr *) msg->data;
+ rc = read(conn->queue.bfd.fd, msg->data, sizeof(gh->len));
+ if (rc <= 0) {
+ msgb_free(msg);
+ return rc;
+ } else if (rc != sizeof(gh->len)) {
+ msgb_free(msg);
+ return -EIO;
+ }
+ msg->l2h = msg->data;
+ msgb_put(msg, rc);
+
+ rc = read(conn->queue.bfd.fd, msg->data, ntohs(gh->len));
+ if (rc <= 0)
+ return rc;
+ else if (rc != ntohs(gh->len)) {
+ msgb_free(msg);
+ return -EIO;
+ }
+
+ msgb_put(msg, rc);
+
+ return rx_unc_msg(conn->priv, msg);
+}
+
+static void unc_accept_cb(struct osmo_conn *conn)
+{
+ struct gan_peer *peer = talloc_zero(conn, struct gan_peer);
+ printf("accepted connection\n");
+
+ peer->conn = conn;
+ conn->priv = peer;
+}
+
+
+int ganc_server_start(const char *host, uint16_t port)
+{
+ struct osmo_link *link;
+
+ link = osmo_link_create(NULL, host, port, unc_read_cb, 10);
+ if (!link)
+ return -ENOMEM;
+
+ osmo_link_listen(link, unc_accept_cb);
+
+ return 0;
+}