nat: Return the SCCP connection, change order of patching and updating
* Return the SCCP connection. This will be needed to store the assigned timeslot in there. * Update code to work with this change * This uncovered a bug in the CC handling, at the time the BSC was passed it was still a null pointer and the code would have failed.
This commit is contained in:
parent
72ba1624b3
commit
49c7fb52f0
|
@ -156,9 +156,9 @@ struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg);
|
||||||
* SCCP patching and handling
|
* SCCP patching and handling
|
||||||
*/
|
*/
|
||||||
int create_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed);
|
int create_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed);
|
||||||
int update_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed);
|
int update_sccp_src_ref(struct sccp_connections *sccp, struct bsc_nat_parsed *parsed);
|
||||||
void remove_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed);
|
void remove_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed);
|
||||||
struct bsc_connection *patch_sccp_src_ref_to_bsc(struct msgb *, struct bsc_nat_parsed *, struct bsc_nat *);
|
struct sccp_connections *patch_sccp_src_ref_to_bsc(struct msgb *, struct bsc_nat_parsed *, struct bsc_nat *);
|
||||||
struct bsc_connection *patch_sccp_src_ref_to_msc(struct msgb *, struct bsc_nat_parsed *, struct bsc_nat *);
|
struct sccp_connections *patch_sccp_src_ref_to_msc(struct msgb *, struct bsc_nat_parsed *, struct bsc_nat *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -168,7 +168,8 @@ static void bsc_write(struct bsc_connection *bsc, const u_int8_t *data, unsigned
|
||||||
|
|
||||||
static int forward_sccp_to_bts(struct msgb *msg)
|
static int forward_sccp_to_bts(struct msgb *msg)
|
||||||
{
|
{
|
||||||
struct bsc_connection *bsc = NULL;
|
struct sccp_connections *con;
|
||||||
|
struct bsc_connection *bsc;
|
||||||
struct bsc_nat_parsed *parsed;
|
struct bsc_nat_parsed *parsed;
|
||||||
|
|
||||||
/* filter, drop, patch the message? */
|
/* filter, drop, patch the message? */
|
||||||
|
@ -191,12 +192,12 @@ static int forward_sccp_to_bts(struct msgb *msg)
|
||||||
case SCCP_MSG_TYPE_RLSD:
|
case SCCP_MSG_TYPE_RLSD:
|
||||||
case SCCP_MSG_TYPE_CREF:
|
case SCCP_MSG_TYPE_CREF:
|
||||||
case SCCP_MSG_TYPE_DT1:
|
case SCCP_MSG_TYPE_DT1:
|
||||||
bsc = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
|
con = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
|
||||||
break;
|
break;
|
||||||
case SCCP_MSG_TYPE_CC:
|
case SCCP_MSG_TYPE_CC:
|
||||||
if (update_sccp_src_ref(bsc, msg, parsed) != 0)
|
con = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
|
||||||
|
if (!con || update_sccp_src_ref(con, parsed) != 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
bsc = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
|
|
||||||
break;
|
break;
|
||||||
case SCCP_MSG_TYPE_RLC:
|
case SCCP_MSG_TYPE_RLC:
|
||||||
LOGP(DNAT, LOGL_ERROR, "Unexpected release complete from MSC.\n");
|
LOGP(DNAT, LOGL_ERROR, "Unexpected release complete from MSC.\n");
|
||||||
|
@ -210,14 +211,14 @@ static int forward_sccp_to_bts(struct msgb *msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
talloc_free(parsed);
|
talloc_free(parsed);
|
||||||
if (!bsc)
|
if (!con)
|
||||||
return -1;
|
return -1;
|
||||||
if (!bsc->authenticated) {
|
if (!con->bsc->authenticated) {
|
||||||
LOGP(DNAT, LOGL_ERROR, "Selected BSC not authenticated.\n");
|
LOGP(DNAT, LOGL_ERROR, "Selected BSC not authenticated.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bsc_write(bsc, msg->data, msg->len);
|
bsc_write(con->bsc, msg->data, msg->len);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
send_to_all:
|
send_to_all:
|
||||||
|
@ -365,7 +366,7 @@ static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc
|
||||||
|
|
||||||
static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
|
static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
|
||||||
{
|
{
|
||||||
struct bsc_connection *found_bsc = NULL;
|
struct sccp_connections *con;
|
||||||
struct bsc_nat_parsed *parsed;
|
struct bsc_nat_parsed *parsed;
|
||||||
|
|
||||||
if (!bsc->authenticated) {
|
if (!bsc->authenticated) {
|
||||||
|
@ -391,29 +392,34 @@ static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
|
||||||
case SCCP_MSG_TYPE_CR:
|
case SCCP_MSG_TYPE_CR:
|
||||||
if (create_sccp_src_ref(bsc, msg, parsed) != 0)
|
if (create_sccp_src_ref(bsc, msg, parsed) != 0)
|
||||||
goto exit2;
|
goto exit2;
|
||||||
found_bsc = patch_sccp_src_ref_to_msc(msg, parsed, nat);
|
con = patch_sccp_src_ref_to_msc(msg, parsed, nat);
|
||||||
break;
|
break;
|
||||||
case SCCP_MSG_TYPE_RLSD:
|
case SCCP_MSG_TYPE_RLSD:
|
||||||
case SCCP_MSG_TYPE_CREF:
|
case SCCP_MSG_TYPE_CREF:
|
||||||
case SCCP_MSG_TYPE_DT1:
|
case SCCP_MSG_TYPE_DT1:
|
||||||
case SCCP_MSG_TYPE_CC:
|
case SCCP_MSG_TYPE_CC:
|
||||||
found_bsc = patch_sccp_src_ref_to_msc(msg, parsed, nat);
|
con = patch_sccp_src_ref_to_msc(msg, parsed, nat);
|
||||||
break;
|
break;
|
||||||
case SCCP_MSG_TYPE_RLC:
|
case SCCP_MSG_TYPE_RLC:
|
||||||
found_bsc = patch_sccp_src_ref_to_msc(msg, parsed, nat);
|
con = patch_sccp_src_ref_to_msc(msg, parsed, nat);
|
||||||
remove_sccp_src_ref(bsc, msg, parsed);
|
remove_sccp_src_ref(bsc, msg, parsed);
|
||||||
break;
|
break;
|
||||||
case SCCP_MSG_TYPE_UDT:
|
case SCCP_MSG_TYPE_UDT:
|
||||||
/* simply forward everything */
|
/* simply forward everything */
|
||||||
|
con = NULL;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOGP(DNAT, LOGL_ERROR, "Not forwarding to msc sccp type: 0x%x\n", parsed->sccp_type);
|
LOGP(DNAT, LOGL_ERROR, "Not forwarding to msc sccp type: 0x%x\n", parsed->sccp_type);
|
||||||
|
con = NULL;
|
||||||
goto exit2;
|
goto exit2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
LOGP(DNAT, LOGL_ERROR, "Not forwarding unknown stream id: 0x%x\n", parsed->ipa_proto);
|
||||||
|
goto exit2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found_bsc != bsc) {
|
if (con && con->bsc != bsc) {
|
||||||
LOGP(DNAT, LOGL_ERROR, "Found the wrong entry.\n");
|
LOGP(DNAT, LOGL_ERROR, "Found the wrong entry.\n");
|
||||||
goto exit2;
|
goto exit2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,32 +108,19 @@ int create_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int update_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed)
|
int update_sccp_src_ref(struct sccp_connections *sccp, struct bsc_nat_parsed *parsed)
|
||||||
{
|
{
|
||||||
struct sccp_connections *conn;
|
|
||||||
|
|
||||||
if (!parsed->dest_local_ref || !parsed->src_local_ref) {
|
if (!parsed->dest_local_ref || !parsed->src_local_ref) {
|
||||||
LOGP(DNAT, LOGL_ERROR, "CC MSG should contain both local and dest address.\n");
|
LOGP(DNAT, LOGL_ERROR, "CC MSG should contain both local and dest address.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
llist_for_each_entry(conn, &bsc->nat->sccp_connections, list_entry) {
|
sccp->remote_ref = *parsed->src_local_ref;
|
||||||
if (conn->bsc != bsc)
|
LOGP(DNAT, LOGL_DEBUG, "Updating 0x%x to remote 0x%x on %p\n",
|
||||||
continue;
|
sccp_src_ref_to_int(&sccp->patched_ref),
|
||||||
|
sccp_src_ref_to_int(&sccp->remote_ref), sccp->bsc);
|
||||||
|
|
||||||
if (memcmp(parsed->dest_local_ref,
|
return 0;
|
||||||
&conn->patched_ref, sizeof(conn->patched_ref)) != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
conn->remote_ref = *parsed->src_local_ref;
|
|
||||||
LOGP(DNAT, LOGL_DEBUG, "Updating 0x%x to remote 0x%x on %p\n",
|
|
||||||
sccp_src_ref_to_int(&conn->patched_ref),
|
|
||||||
sccp_src_ref_to_int(&conn->remote_ref), bsc);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGP(DNAT, LOGL_ERROR, "Referenced connection not found on BSC: %p\n", bsc);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed)
|
void remove_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed)
|
||||||
|
@ -165,9 +152,9 @@ void remove_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bs
|
||||||
* an address that was assigned by the MUX, we need to update the
|
* an address that was assigned by the MUX, we need to update the
|
||||||
* dest reference to the real network.
|
* dest reference to the real network.
|
||||||
*/
|
*/
|
||||||
struct bsc_connection *patch_sccp_src_ref_to_bsc(struct msgb *msg,
|
struct sccp_connections *patch_sccp_src_ref_to_bsc(struct msgb *msg,
|
||||||
struct bsc_nat_parsed *parsed,
|
struct bsc_nat_parsed *parsed,
|
||||||
struct bsc_nat *nat)
|
struct bsc_nat *nat)
|
||||||
{
|
{
|
||||||
struct sccp_connections *conn;
|
struct sccp_connections *conn;
|
||||||
|
|
||||||
|
@ -183,7 +170,7 @@ struct bsc_connection *patch_sccp_src_ref_to_bsc(struct msgb *msg,
|
||||||
|
|
||||||
/* Change the dest address to the real one */
|
/* Change the dest address to the real one */
|
||||||
*parsed->dest_local_ref = conn->real_ref;
|
*parsed->dest_local_ref = conn->real_ref;
|
||||||
return conn->bsc;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -197,9 +184,9 @@ struct bsc_connection *patch_sccp_src_ref_to_bsc(struct msgb *msg,
|
||||||
* in all other cases we need to work by the destination local
|
* in all other cases we need to work by the destination local
|
||||||
* reference..
|
* reference..
|
||||||
*/
|
*/
|
||||||
struct bsc_connection *patch_sccp_src_ref_to_msc(struct msgb *msg,
|
struct sccp_connections *patch_sccp_src_ref_to_msc(struct msgb *msg,
|
||||||
struct bsc_nat_parsed *parsed,
|
struct bsc_nat_parsed *parsed,
|
||||||
struct bsc_nat *nat)
|
struct bsc_nat *nat)
|
||||||
{
|
{
|
||||||
struct sccp_connections *conn;
|
struct sccp_connections *conn;
|
||||||
|
|
||||||
|
@ -207,11 +194,11 @@ struct bsc_connection *patch_sccp_src_ref_to_msc(struct msgb *msg,
|
||||||
if (parsed->src_local_ref) {
|
if (parsed->src_local_ref) {
|
||||||
if (equal(parsed->src_local_ref, &conn->real_ref)) {
|
if (equal(parsed->src_local_ref, &conn->real_ref)) {
|
||||||
*parsed->src_local_ref = conn->patched_ref;
|
*parsed->src_local_ref = conn->patched_ref;
|
||||||
return conn->bsc;
|
return conn;
|
||||||
}
|
}
|
||||||
} else if (parsed->dest_local_ref) {
|
} else if (parsed->dest_local_ref) {
|
||||||
if (equal(parsed->dest_local_ref, &conn->remote_ref))
|
if (equal(parsed->dest_local_ref, &conn->remote_ref))
|
||||||
return conn->bsc;
|
return conn;
|
||||||
} else {
|
} else {
|
||||||
LOGP(DNAT, LOGL_ERROR, "Header has neither loc/dst ref.\n");
|
LOGP(DNAT, LOGL_ERROR, "Header has neither loc/dst ref.\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -189,7 +189,7 @@ static void copy_to_msg(struct msgb *msg, const u_int8_t *data, unsigned int len
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VERIFY(con_found, con, msg, ver, str) \
|
#define VERIFY(con_found, con, msg, ver, str) \
|
||||||
if (con_found != con) { \
|
if (!con_found || con_found->bsc != con) { \
|
||||||
fprintf(stderr, "Failed to find the con: %p\n", con_found); \
|
fprintf(stderr, "Failed to find the con: %p\n", con_found); \
|
||||||
abort(); \
|
abort(); \
|
||||||
} \
|
} \
|
||||||
|
@ -203,7 +203,8 @@ static void test_contrack()
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct bsc_nat *nat;
|
struct bsc_nat *nat;
|
||||||
struct bsc_connection *con, *con_found;
|
struct bsc_connection *con;
|
||||||
|
struct sccp_connections *con_found;
|
||||||
struct bsc_nat_parsed *parsed;
|
struct bsc_nat_parsed *parsed;
|
||||||
struct msgb *msg;
|
struct msgb *msg;
|
||||||
|
|
||||||
|
@ -226,7 +227,7 @@ static void test_contrack()
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
con_found = patch_sccp_src_ref_to_msc(msg, parsed, nat);
|
con_found = patch_sccp_src_ref_to_msc(msg, parsed, nat);
|
||||||
if (con_found != con) {
|
if (!con_found || con_found->bsc != con) {
|
||||||
fprintf(stderr, "Failed to find the con: %p\n", con_found);
|
fprintf(stderr, "Failed to find the con: %p\n", con_found);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
@ -239,12 +240,12 @@ static void test_contrack()
|
||||||
/* 2.) get the cc */
|
/* 2.) get the cc */
|
||||||
copy_to_msg(msg, msc_cc, sizeof(msc_cc));
|
copy_to_msg(msg, msc_cc, sizeof(msc_cc));
|
||||||
parsed = bsc_nat_parse(msg);
|
parsed = bsc_nat_parse(msg);
|
||||||
if (update_sccp_src_ref(con, msg, parsed) != 0) {
|
con_found = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
|
||||||
|
VERIFY(con_found, con, msg, msc_cc_patched, "MSC CC");
|
||||||
|
if (update_sccp_src_ref(con_found, parsed) != 0) {
|
||||||
fprintf(stderr, "Failed to update the SCCP con.\n");
|
fprintf(stderr, "Failed to update the SCCP con.\n");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
con_found = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
|
|
||||||
VERIFY(con_found, con, msg, msc_cc_patched, "MSC CC");
|
|
||||||
|
|
||||||
/* 3.) send some data */
|
/* 3.) send some data */
|
||||||
copy_to_msg(msg, bsc_dtap, sizeof(bsc_dtap));
|
copy_to_msg(msg, bsc_dtap, sizeof(bsc_dtap));
|
||||||
|
@ -268,7 +269,7 @@ static void test_contrack()
|
||||||
copy_to_msg(msg, bsc_rlc, sizeof(bsc_rlc));
|
copy_to_msg(msg, bsc_rlc, sizeof(bsc_rlc));
|
||||||
parsed = bsc_nat_parse(msg);
|
parsed = bsc_nat_parse(msg);
|
||||||
con_found = patch_sccp_src_ref_to_msc(msg, parsed, nat);
|
con_found = patch_sccp_src_ref_to_msc(msg, parsed, nat);
|
||||||
if (con_found != con) {
|
if (!con_found || con_found->bsc != con) {
|
||||||
fprintf(stderr, "Failed to find the con: %p\n", con_found);
|
fprintf(stderr, "Failed to find the con: %p\n", con_found);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue