aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/input/ipaccess.c
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src/input/ipaccess.c')
-rw-r--r--openbsc/src/input/ipaccess.c112
1 files changed, 103 insertions, 9 deletions
diff --git a/openbsc/src/input/ipaccess.c b/openbsc/src/input/ipaccess.c
index 943a5e88d..38d931965 100644
--- a/openbsc/src/input/ipaccess.c
+++ b/openbsc/src/input/ipaccess.c
@@ -48,6 +48,7 @@
struct ia_e1_handle {
struct bsc_fd listen_fd;
struct bsc_fd rsl_listen_fd;
+ struct bsc_fd gprs_fd;
struct gsm_network *gsmnet;
};
@@ -486,6 +487,87 @@ static int ipaccess_fd_cb(struct bsc_fd *bfd, unsigned int what)
return rc;
}
+/* declare this as a weak symbol to ensure code will still build
+ * even if it does not provide this function */
+extern int gprs_ns_rcvmsg(struct msgb *msg) __attribute__((weak));
+
+static struct msgb *read_gprs_msg(struct bsc_fd *bfd, int *error)
+{
+ struct msgb *msg = msgb_alloc(TS1_ALLOC_SIZE, "Abis/IP/GPRS");
+ int ret = 0;
+
+ if (!msg) {
+ *error = -ENOMEM;
+ return NULL;
+ }
+
+ ret = recv(bfd->fd, msg->data, TS1_ALLOC_SIZE, 0);
+ if (ret < 0) {
+ fprintf(stderr, "recv error %s\n", strerror(errno));
+ msgb_free(msg);
+ *error = ret;
+ return NULL;
+ } else if (ret == 0) {
+ msgb_free(msg);
+ *error = ret;
+ return NULL;
+ }
+
+ msg->l2h = msg->data;
+ msgb_put(msg, ret);
+
+ return msg;
+}
+
+static int handle_gprs_read(struct bsc_fd *bfd)
+{
+ int error;
+ struct msgb *msg = read_gprs_msg(bfd, &error);
+
+ if (!msg)
+ return error;
+
+ if (gprs_ns_rcvmsg)
+ return gprs_ns_rcvmsg(msg);
+ else {
+ msgb_free(msg);
+ return 0;
+ }
+}
+
+static int handle_gprs_write(struct bsc_fd *bfd)
+{
+}
+
+int ipac_gprs_send(struct msgb *msg)
+{
+ struct sockaddr_in sin;
+ int rc;
+
+ sin.sin_family = AF_INET;
+ inet_aton("192.168.100.111", &sin.sin_addr);
+ sin.sin_port = htons(23000);
+
+ rc = sendto(e1h->gprs_fd.fd, msg->data, msg->len, 0,
+ (struct sockaddr *)&sin, sizeof(sin));
+
+ talloc_free(msg);
+
+ return rc;
+}
+
+/* UDP Port 23000 carries the LLC-in-BSSGP-in-NS protocol stack */
+static int gprs_fd_cb(struct bsc_fd *bfd, unsigned int what)
+{
+ int rc;
+
+ if (what & BSC_FD_READ)
+ rc = handle_gprs_read(bfd);
+ if (what & BSC_FD_WRITE)
+ rc = handle_gprs_write(bfd);
+
+ return rc;
+}
struct e1inp_driver ipaccess_driver = {
.name = "ip.access",
@@ -587,13 +669,17 @@ static int rsl_listen_fd_cb(struct bsc_fd *listen_bfd, unsigned int what)
return 0;
}
-static int make_sock(struct bsc_fd *bfd, u_int16_t port,
+static int make_sock(struct bsc_fd *bfd, int proto, u_int16_t port,
int (*cb)(struct bsc_fd *fd, unsigned int what))
{
struct sockaddr_in addr;
int ret, on = 1;
+ int type = SOCK_STREAM;
+
+ if (proto == IPPROTO_UDP)
+ type = SOCK_DGRAM;
- bfd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ bfd->fd = socket(AF_INET, type, proto);
bfd->cb = cb;
bfd->when = BSC_FD_READ;
//bfd->data = line;
@@ -618,11 +704,12 @@ static int make_sock(struct bsc_fd *bfd, u_int16_t port,
return -EIO;
}
- ret = listen(bfd->fd, 1);
- if (ret < 0) {
- perror("listen");
- close(bfd->fd);
- return ret;
+ if (proto != IPPROTO_UDP) {
+ ret = listen(bfd->fd, 1);
+ if (ret < 0) {
+ perror("listen");
+ return ret;
+ }
}
ret = bsc_register_fd(bfd);
@@ -690,12 +777,19 @@ int ipaccess_setup(struct gsm_network *gsmnet)
e1h->gsmnet = gsmnet;
/* Listen for OML connections */
- ret = make_sock(&e1h->listen_fd, IPA_TCP_PORT_OML, listen_fd_cb);
+ ret = make_sock(&e1h->listen_fd, IPPROTO_TCP, IPA_TCP_PORT_OML,
+ listen_fd_cb);
if (ret < 0)
return ret;
/* Listen for RSL connections */
- ret = make_sock(&e1h->rsl_listen_fd, IPA_TCP_PORT_RSL, rsl_listen_fd_cb);
+ ret = make_sock(&e1h->rsl_listen_fd, IPPROTO_TCP,
+ IPA_TCP_PORT_RSL, rsl_listen_fd_cb);
+ if (ret < 0)
+ return ret;
+
+ /* Listen for incoming GPRS packets */
+ ret = make_sock(&e1h->gprs_fd, IPPROTO_UDP, 23000, gprs_fd_cb);
return ret;
}