nat: Make rewrite work on string, read to a string first, copy to msgb

The MGCP protocol parsing is adding '\0' to make sure we do not
parse beyond where we should parse. This does not mix with strtok
or similiar routines.
For now we will read the msg into a global array first, then copy
it to the msgb for mgcp protocol handling and if we are required
to forward it to the MGCP we have a untouched copy we will modify
into our own msgb.
This commit is contained in:
Holger Hans Peter Freyther 2010-04-04 18:09:10 +02:00
parent bbb9d398e1
commit 8d20065c4b
3 changed files with 27 additions and 26 deletions

View File

@ -153,7 +153,8 @@ struct bsc_nat {
/* MGCP config */
struct mgcp_config *mgcp_cfg;
struct write_queue mgcp_queue;
struct msgb *mgcp_msg;
u_int8_t mgcp_msg[4096];
int mgcp_length;
struct bsc_endpoint *bsc_endpoints;
};
@ -199,7 +200,7 @@ void bsc_mgcp_free_endpoints(struct bsc_nat *nat);
int bsc_mgcp_init(struct bsc_nat *nat);
struct bsc_connection *bsc_mgcp_find_con(struct bsc_nat *, int endpoint_number);
struct msgb *bsc_mgcp_rewrite(struct msgb *msg, const char *ip, int port);
struct msgb *bsc_mgcp_rewrite(char *input, int length, const char *ip, int port);
void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg);
int bsc_mgcp_parse_response(const char *str, int *code, char transaction[60]);

View File

@ -163,7 +163,8 @@ int bsc_mgcp_policy_cb(struct mgcp_config *cfg, int endpoint, int state, const c
}
/* we need to generate a new and patched message */
bsc_msg = bsc_mgcp_rewrite(nat->mgcp_msg, nat->mgcp_cfg->source_addr, mgcp_endp->rtp_port);
bsc_msg = bsc_mgcp_rewrite((char *) nat->mgcp_msg, nat->mgcp_length,
nat->mgcp_cfg->source_addr, mgcp_endp->rtp_port);
if (!bsc_msg) {
LOGP(DMGCP, LOGL_ERROR, "Failed to patch the msg.\n");
return MGCP_POLICY_CONT;
@ -222,7 +223,8 @@ void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg)
/* make it point to our endpoint */
endp->ci = bsc_mgcp_extract_ci((const char *) msg->l2h);
output = bsc_mgcp_rewrite(msg, bsc->nat->mgcp_cfg->source_addr, endp->rtp_port);
output = bsc_mgcp_rewrite((char * ) msg->l2h, msgb_l2len(msg),
bsc->nat->mgcp_cfg->source_addr, endp->rtp_port);
if (!output) {
LOGP(DMGCP, LOGL_ERROR, "Failed to rewrite MGCP msg.\n");
return;
@ -253,7 +255,7 @@ int bsc_mgcp_extract_ci(const char *str)
}
/* we need to replace some strings... */
struct msgb *bsc_mgcp_rewrite(struct msgb *input, const char *ip, int port)
struct msgb *bsc_mgcp_rewrite(char *input, int length, const char *ip, int port)
{
static const char *ip_str = "c=IN IP4 ";
static const char *aud_str = "m=audio ";
@ -262,7 +264,7 @@ struct msgb *bsc_mgcp_rewrite(struct msgb *input, const char *ip, int port)
char *running, *token;
struct msgb *output;
if (msgb_l2len(input) > 4096 - 128) {
if (length > 4096 - 128) {
LOGP(DMGCP, LOGL_ERROR, "Input is too long.\n");
return NULL;
}
@ -273,7 +275,7 @@ struct msgb *bsc_mgcp_rewrite(struct msgb *input, const char *ip, int port)
return NULL;
}
running = (char *) input->l2h;
running = input;
output->l2h = output->data;
for (token = strsep(&running, "\n"); token; token = strsep(&running, "\n")) {
int len = strlen(token);
@ -319,26 +321,27 @@ static int mgcp_do_read(struct bsc_fd *fd)
struct msgb *msg, *resp;
int rc;
msg = msgb_alloc(4096, "MGCP GW Read");
nat = fd->data;
rc = read(fd->fd, nat->mgcp_msg, sizeof(nat->mgcp_msg) - 1);
if (rc <= 0) {
LOGP(DMGCP, LOGL_ERROR, "Failed to read errno: %d\n", errno);
return -1;
}
nat->mgcp_msg[rc] = '\0';
nat->mgcp_length = rc;
msg = msgb_alloc(sizeof(nat->mgcp_msg), "MGCP GW Read");
if (!msg) {
LOGP(DMGCP, LOGL_ERROR, "Failed to create buffer.\n");
return -1;
}
rc = read(fd->fd, msg->data, msg->data_len);
if (rc <= 0) {
LOGP(DMGCP, LOGL_ERROR, "Failed to read errno: %d\n", errno);
msgb_free(msg);
return -1;
}
nat = fd->data;
nat->mgcp_msg = msg;
msg->l2h = msgb_put(msg, rc);
memcpy(msg->l2h, nat->mgcp_msg, msgb_l2len(msg));
resp = mgcp_handle_message(nat->mgcp_cfg, msg);
msgb_free(msg);
nat->mgcp_msg = NULL;
/* we do have a direct answer... e.g. AUEP */
if (resp) {

View File

@ -425,20 +425,18 @@ static void test_mgcp_find(void)
static void test_mgcp_rewrite(void)
{
int i;
struct msgb *input, *output;
struct msgb *output;
fprintf(stderr, "Test rewriting MGCP messages.\n");
input = msgb_alloc(4096, "input");
for (i = 0; i < ARRAY_SIZE(mgcp_messages); ++i) {
const char *orig = mgcp_messages[i].orig;
const char *patc = mgcp_messages[i].patch;
const char *ip = mgcp_messages[i].ip;
const int port = mgcp_messages[i].port;
copy_to_msg(input, (const u_int8_t *) orig, strlen(orig) + 1);
char *input = strdup(orig);
output = bsc_mgcp_rewrite(input, ip, port);
output = bsc_mgcp_rewrite(input, strlen(input), ip, port);
if (msgb_l2len(output) != strlen(patc)) {
fprintf(stderr, "Wrong sizes for test: %d %d != %d != %d\n", i, msgb_l2len(output), strlen(patc), strlen(orig));
fprintf(stderr, "String '%s' vs '%s'\n", (const char *) output->l2h, patc);
@ -451,9 +449,8 @@ static void test_mgcp_rewrite(void)
}
msgb_free(output);
free(input);
}
msgb_free(input);
}
static void test_mgcp_parse(void)