aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/ipaccess/ipaccess-proxy.c
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-06-10 15:57:08 +0800
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-06-10 15:59:45 +0800
commit4fe22cc56df597cd18bedb2c2e0957e3ffc428b9 (patch)
tree2fad5bafabf7806a77d9888cf56f0e50cecaa3ce /openbsc/src/ipaccess/ipaccess-proxy.c
parent21e1c0d01c11bdfba2d69a0579745ddabc843035 (diff)
ipa-proxy: Patch the IPA Set Attribute messages for NSVCI
We will tell the BTS where we are listening, but the ACK will return the original settings... this should make it possible to intercept the GPRS stream..
Diffstat (limited to 'openbsc/src/ipaccess/ipaccess-proxy.c')
-rw-r--r--openbsc/src/ipaccess/ipaccess-proxy.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/openbsc/src/ipaccess/ipaccess-proxy.c b/openbsc/src/ipaccess/ipaccess-proxy.c
index 3f1005c92..3e1bcdc34 100644
--- a/openbsc/src/ipaccess/ipaccess-proxy.c
+++ b/openbsc/src/ipaccess/ipaccess-proxy.c
@@ -61,6 +61,7 @@ struct ipa_proxy {
struct timer_list reconn_timer;
/* global GPRS NS data */
struct in_addr gprs_addr;
+ struct in_addr listen_addr;
};
/* global pointer to the proxy structure */
@@ -101,6 +102,8 @@ struct ipa_bts_conn {
struct in_addr bts_addr;
struct bsc_fd gprs_ns_fd;
int gprs_local_port;
+ uint16_t gprs_orig_port;
+ uint32_t gprs_orig_ip;
char *id_tags[0xff];
u_int8_t *id_resp;
@@ -846,6 +849,44 @@ static void handle_dead_socket(struct bsc_fd *bfd)
talloc_free(ipc);
}
+static void patch_gprs_msg(struct ipa_bts_conn *ipbc, int priv_nr, struct msgb *msg)
+{
+ uint8_t *nsvci;
+
+ if ((priv_nr & 0xff) != OML_FROM_BTS && (priv_nr & 0xff) != OML_TO_BSC)
+ return;
+
+ if (msgb_l2len(msg) != 39)
+ return;
+
+ /*
+ * Check if this is a IPA Set Attribute or IPA Set Attribute ACK
+ * and if the FOM Class is GPRS NSVC0 and then we will patch it.
+ *
+ * The patch assumes the message looks like the one from the trace
+ * but we only match messages with a specific size anyway... So
+ * this hack should work just fine.
+ */
+
+ if (msg->l2h[0] == 0x10 && msg->l2h[1] == 0x80 &&
+ msg->l2h[2] == 0x00 && msg->l2h[3] == 0x15 &&
+ msg->l2h[18] == 0xf5 && msg->l2h[19] == 0xf2) {
+ printf("found GPRS NSVC SET foo...\n");
+ nsvci = &msg->l2h[23];
+ ipbc->gprs_orig_port = *(u_int16_t *)(nsvci+8);
+ ipbc->gprs_orig_ip = *(u_int32_t *)(nsvci+10);
+ *(u_int16_t *)(nsvci+8) = htons(ipbc->gprs_local_port);
+ *(u_int32_t *)(nsvci+10) = ipbc->ipp->listen_addr.s_addr;
+ } else if (msg->l2h[0] == 0x10 && msg->l2h[1] == 0x80 &&
+ msg->l2h[2] == 0x00 && msg->l2h[3] == 0x15 &&
+ msg->l2h[18] == 0xf6 && msg->l2h[19] == 0xf2) {
+ printf("found GPRS NSVC SET ACK...\n");
+ nsvci = &msg->l2h[23];
+ *(u_int16_t *)(nsvci+8) = ipbc->gprs_orig_port;
+ *(u_int32_t *)(nsvci+10) = ipbc->gprs_orig_ip;
+ }
+}
+
static int handle_tcp_read(struct bsc_fd *bfd)
{
struct ipa_proxy_conn *ipc = bfd->data;
@@ -903,6 +944,8 @@ static int handle_tcp_read(struct bsc_fd *bfd)
bsc_conn = ipc_by_priv_nr(ipbc, bfd->priv_nr);
if (bsc_conn) {
+ if (gprs_ns_ipaddr)
+ patch_gprs_msg(ipbc, bfd->priv_nr, msg);
/* enqueue packet towards BSC */
msgb_enqueue(&bsc_conn->tx_queue, msg);
/* mark respective filedescriptor as 'we want to write' */
@@ -1210,8 +1253,10 @@ static int ipaccess_proxy_setup(void)
return ret;
/* Connect the GPRS NS Socket */
- if (gprs_ns_ipaddr)
+ if (gprs_ns_ipaddr) {
inet_aton(gprs_ns_ipaddr, &ipp->gprs_addr);
+ inet_aton(listen_ipaddr, &ipp->listen_addr);
+ }
return ret;
}