aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/ipaccess/ipaccess-proxy.c
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-06-09 17:07:43 +0800
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-06-09 21:40:45 +0800
commit952aba740619512f8346f85ad48b096898451e2e (patch)
tree591c63b09b0ec44730fed70e74b6a76d999cd4e0 /openbsc/src/ipaccess/ipaccess-proxy.c
parent6147c5d7d0c6fee5e9c3f1868f9f4bcbd0e4c39c (diff)
ipa-proxy: Move UDP socket code to the BTS and forward messages...
Forward messages from BTS to Network, Network to BTS... now we only need to fix the Set GPRS attributes on the fly...
Diffstat (limited to 'openbsc/src/ipaccess/ipaccess-proxy.c')
-rw-r--r--openbsc/src/ipaccess/ipaccess-proxy.c97
1 files changed, 77 insertions, 20 deletions
diff --git a/openbsc/src/ipaccess/ipaccess-proxy.c b/openbsc/src/ipaccess/ipaccess-proxy.c
index 0a7b18b47..56e910111 100644
--- a/openbsc/src/ipaccess/ipaccess-proxy.c
+++ b/openbsc/src/ipaccess/ipaccess-proxy.c
@@ -55,13 +55,12 @@ struct ipa_proxy {
struct bsc_fd oml_listen_fd;
/* socket where we listen for incoming RSL from BTS */
struct bsc_fd rsl_listen_fd;
- /* socket where we get the GPRS NS data */
- struct bsc_fd gprs_ns_fd;
- int gprs_port;
/* list of BTS's (struct ipa_bts_conn */
struct llist_head bts_list;
/* the BSC reconnect timer */
struct timer_list reconn_timer;
+ /* global GPRS NS data */
+ struct in_addr gprs_addr;
};
/* global pointer to the proxy structure */
@@ -72,7 +71,6 @@ struct ipa_proxy_conn {
struct llist_head tx_queue;
struct ipa_bts_conn *bts_conn;
};
-
#define MAX_TRX 4
/* represents a particular BTS in our proxy */
@@ -99,6 +97,11 @@ struct ipa_bts_conn {
struct bsc_fd udp_bts_fd;
struct bsc_fd udp_bsc_fd;
+ /* NS data */
+ struct in_addr bts_addr;
+ struct bsc_fd gprs_ns_fd;
+ int gprs_local_port;
+
char *id_tags[0xff];
u_int8_t *id_resp;
unsigned int id_resp_len;
@@ -120,6 +123,9 @@ static char *listen_ipaddr;
static char *bsc_ipaddr;
static char *gprs_ns_ipaddr;
+static int make_gprs_sock(struct bsc_fd *bfd, int (*cb)(struct bsc_fd*,unsigned int), void *);
+static int gprs_ns_cb(struct bsc_fd *bfd, unsigned int what);
+
#define PROXY_ALLOC_SIZE 1200
static const u_int8_t pong[] = { 0, 1, IPAC_PROTO_IPACCESS, IPAC_MSGT_PONG };
@@ -501,6 +507,28 @@ static int ipbc_alloc_connect(struct ipa_proxy_conn *ipc, struct bsc_fd *bfd,
goto err_udp_bsc;
DEBUGP(DINP, "(%u/%u/%u) Created UDP socket for injection "
"towards BSC at port %u\n", site_id, bts_id, trx_id, udp_port);
+
+
+ /* GPRS NS related code */
+ if (gprs_ns_ipaddr) {
+ struct sockaddr_in sock;
+ socklen_t len = sizeof(sock);
+ ret = make_gprs_sock(&ipbc->gprs_ns_fd, gprs_ns_cb, ipbc);
+ if (ret < 0) {
+ LOGP(DINP, LOGL_ERROR, "Creating the GPRS socket failed.\n");
+ goto err_udp_bsc;
+ }
+
+ ret = getsockname(ipbc->gprs_ns_fd.fd, (struct sockaddr* ) &sock, &len);
+ ipbc->gprs_local_port = ntohs(sock.sin_port);
+ LOGP(DINP, LOGL_NOTICE,
+ "Created GPRS NS Socket. Listening on: %s:%d\n",
+ inet_ntoa(sock.sin_addr), ipbc->gprs_local_port);
+
+ ret = getpeername(bfd->fd, (struct sockaddr* ) &sock, &len);
+ ipbc->bts_addr = sock.sin_addr;
+ }
+
llist_add(&ipbc->list, &ipp->bts_list);
return 0;
@@ -986,8 +1014,49 @@ static int listen_fd_cb(struct bsc_fd *listen_bfd, unsigned int what)
return 0;
}
+static void send_ns(int fd, const char *buf, int size, struct in_addr ip, int port)
+{
+ int ret;
+ struct sockaddr_in addr;
+ socklen_t len = sizeof(addr);
+ memset(&addr, 0, sizeof(addr));
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = port;
+ addr.sin_addr = ip;
+
+ ret = sendto(fd, buf, size, 0, (struct sockaddr *) &addr, len);
+ if (ret < 0) {
+ LOGP(DINP, LOGL_ERROR, "Failed to forward GPRS message.\n");
+ }
+}
+
static int gprs_ns_cb(struct bsc_fd *bfd, unsigned int what)
{
+ struct ipa_bts_conn *bts;
+ char buf[4096];
+ int ret;
+ struct sockaddr_in sock;
+ socklen_t len = sizeof(sock);
+
+ /* 1. get the data... */
+ ret = recvfrom(bfd->fd, buf, sizeof(buf), 0, (struct sockaddr *) &sock, &len);
+ if (ret < 0) {
+ LOGP(DINP, LOGL_ERROR, "Failed to recv GPRS NS msg: %s.\n", strerror(errno));
+ return -1;
+ }
+
+ bts = bfd->data;
+
+ /* 2. figure out where to send it to */
+ if (memcmp(&sock.sin_addr, &ipp->gprs_addr, sizeof(sock.sin_addr)) == 0) {
+ LOGP(DINP, LOGL_DEBUG, "GPRS NS msg from network.\n");
+ send_ns(bfd->fd, buf, ret, bts->bts_addr, 23000);
+ } else if (memcmp(&sock.sin_addr, &bts->bts_addr, sizeof(sock.sin_addr)) == 0) {
+ LOGP(DINP, LOGL_DEBUG, "GPRS NS msg from BTS.\n");
+ send_ns(bfd->fd, buf, ret, ipp->gprs_addr, 23000);
+ }
+
return 0;
}
@@ -1034,13 +1103,14 @@ static int make_listen_sock(struct bsc_fd *bfd, u_int16_t port, int priv_nr,
return 0;
}
-static int make_gprs_sock(struct bsc_fd *bfd, int (*cb)(struct bsc_fd*,unsigned int))
+static int make_gprs_sock(struct bsc_fd *bfd, int (*cb)(struct bsc_fd*,unsigned int), void *data)
{
struct sockaddr_in addr;
int ret;
bfd->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
bfd->cb = cb;
+ bfd->data = data;
bfd->when = BSC_FD_READ;
memset(&addr, 0, sizeof(addr));
@@ -1131,21 +1201,8 @@ static int ipaccess_proxy_setup(void)
return ret;
/* Connect the GPRS NS Socket */
- if (gprs_ns_ipaddr) {
- struct sockaddr_in sock;
- socklen_t len = sizeof(sock);
- ret = make_gprs_sock(&ipp->gprs_ns_fd, gprs_ns_cb);
- if (ret < 0)
- return ret;
-
- ret = getsockname(ipp->gprs_ns_fd.fd, (struct sockaddr* ) &sock, &len);
- if (ret < 0)
- return ret;
- ipp->gprs_port = ntohs(sock.sin_port);
- LOGP(DINP, LOGL_NOTICE,
- "Created GPRS NS Socket. Listening on: %s:%d\n",
- inet_ntoa(sock.sin_addr), ipp->gprs_port);
- }
+ if (gprs_ns_ipaddr)
+ inet_aton(gprs_ns_ipaddr, &ipp->gprs_addr);
return ret;
}