diff options
author | Harald Welte <laforge@gnumonks.org> | 2010-03-14 15:45:01 +0800 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2010-05-04 07:20:41 +0200 |
commit | 9b455bf801411d0d3297febab68011e8ab6c13d9 (patch) | |
tree | 6f14b5eadc7db4f1b3c979808c2c0d6a4ae66f95 /openbsc/src/input/ipaccess.c | |
parent | 3c69a4cdbeed5cd877d3e688c0066acfa2b7b180 (diff) |
Create new 'gprs-sgsn' branch on top of 'gprs-conf'
This branch contains the partial SGSN/GGSN implementation that
was originally developed as part of the gprs branch.
Diffstat (limited to 'openbsc/src/input/ipaccess.c')
-rw-r--r-- | openbsc/src/input/ipaccess.c | 112 |
1 files changed, 103 insertions, 9 deletions
diff --git a/openbsc/src/input/ipaccess.c b/openbsc/src/input/ipaccess.c index 8a8a1987d..fae9428da 100644 --- a/openbsc/src/input/ipaccess.c +++ b/openbsc/src/input/ipaccess.c @@ -53,6 +53,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; }; @@ -602,6 +603,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", @@ -708,13 +790,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; @@ -739,11 +825,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); @@ -811,12 +898,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; } |