mirror of https://github.com/sipwise/kamailio.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
568 lines
14 KiB
568 lines
14 KiB
/*
|
|
* mangler module
|
|
*
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2001-2003 FhG Fokus
|
|
*
|
|
* This file is part of ser, a free SIP server.
|
|
*
|
|
* ser is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version
|
|
*
|
|
* For a license to use the ser software under conditions
|
|
* other than those described here, or to purchase support for this
|
|
* software, please contact iptel.org by e-mail at the following addresses:
|
|
* info@iptel.org
|
|
*
|
|
* ser is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
/* History:
|
|
* --------
|
|
* 2003-04-07 first version.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <regex.h>
|
|
|
|
#include "sdp_mangler.h"
|
|
#include "ip_helper.h"
|
|
#include "utils.h"
|
|
#include "common.h"
|
|
#include "../../mem/mem.h"
|
|
#include "../../data_lump.h"
|
|
#include "../../parser/hf.h"
|
|
#include "../../parser/parse_content.h"
|
|
#include "../../parser/parse_uri.h"
|
|
#include "../../parser/contact/parse_contact.h"
|
|
#include "../../ut.h"
|
|
#include "../../parser/msg_parser.h" /* struct sip_msg */
|
|
|
|
regex_t *portExpression;
|
|
regex_t *ipExpression;
|
|
|
|
|
|
|
|
int
|
|
sdp_mangle_port (struct sip_msg *msg, char *offset, char *unused)
|
|
{
|
|
int oldContentLength, newContentLength, oldlen, err, oldPort, newPort,
|
|
diff, offsetValue,len,off,ret,needToDealocate;
|
|
struct lump *l;
|
|
regmatch_t pmatch;
|
|
regex_t *re;
|
|
char *s, *pos,*begin,*key;
|
|
char buf[6];
|
|
|
|
|
|
|
|
key = PORT_REGEX;
|
|
/*
|
|
* Checking if msg has a payload
|
|
*/
|
|
if (msg == NULL)
|
|
{
|
|
LOG(L_ERR,"ERROR: sdp_mangle_port: Received NULL for msg \n");
|
|
return -1;
|
|
}
|
|
|
|
if ((msg->content_length==0) &&
|
|
((parse_headers(msg,HDR_CONTENTLENGTH_F,0)==-1) ||
|
|
(msg->content_length==0) )){
|
|
LOG(L_ERR,"ERROR: sdp_mangle_port: bad or missing "
|
|
"Content-Length \n");
|
|
return -2;
|
|
}
|
|
|
|
oldContentLength = get_content_length(msg);
|
|
|
|
if (oldContentLength <= 0)
|
|
{
|
|
LOG(L_ERR,"ERROR: sdp_mangle_port: Received <= 0 for Content-Length \n");
|
|
return -2;
|
|
}
|
|
|
|
if (offset == NULL)
|
|
return -14;
|
|
if (sscanf (offset, "%d", &offsetValue) != 1)
|
|
{
|
|
LOG(L_ERR,"ERROR: sdp_mangle_port: Invalid value for offset \n");
|
|
return -13;
|
|
}
|
|
|
|
//offsetValue = (int)offset;
|
|
#ifdef EXTRA_DEBUG
|
|
fprintf (stdout,"---START--------MANGLE PORT-----------------\n");
|
|
fprintf(stdout,"===============OFFSET = %d\n",offsetValue);
|
|
#endif
|
|
|
|
if ((offsetValue < MIN_OFFSET_VALUE) || (offsetValue > MAX_OFFSET_VALUE))
|
|
{
|
|
LOG(L_ERR,"ERROR: sdp_mangle_port: Invalid value %d for offset \n",offsetValue);
|
|
return -3;
|
|
}
|
|
begin = get_body(msg); //msg->buf + msg->first_line.len; // inlocuiesc cu begin = getbody */
|
|
ret = -1;
|
|
|
|
/* try to use pre-compiled expressions */
|
|
needToDealocate = 0;
|
|
if (portExpression != NULL)
|
|
{
|
|
re = portExpression;
|
|
#ifdef EXTRA_DEBUG
|
|
fprintf(stdout,"Using PRECOMPILED expression for port ...\n");
|
|
#endif
|
|
}
|
|
else /* we are not using pre-compiled expressions */
|
|
{
|
|
re = pkg_malloc(sizeof(regex_t));
|
|
if (re == NULL)
|
|
{
|
|
LOG(L_ERR,"ERROR: sdp_mangle_port: Unable to allocate re\n");
|
|
return -4;
|
|
}
|
|
needToDealocate = 1;
|
|
if ((regcomp (re, key, REG_EXTENDED)) != 0)
|
|
{
|
|
LOG(L_ERR,"ERROR: sdp_mangle_port: Unable to compile %s \n",key);
|
|
return -5;
|
|
}
|
|
#ifdef EXTRA_DEBUG
|
|
fprintf(stdout,"Using ALLOCATED expression for port ...\n");
|
|
#endif
|
|
|
|
}
|
|
|
|
diff = 0;
|
|
while ((begin < msg->buf + msg->len) && (regexec (re, begin, 1, &pmatch, 0) == 0))
|
|
{
|
|
off = begin - msg->buf;
|
|
if (pmatch.rm_so == -1)
|
|
{
|
|
LOG (L_ERR, "ERROR: sdp_mangle_port: offset unknown\n");
|
|
return -6;
|
|
}
|
|
|
|
#ifdef STRICT_CHECK
|
|
pmatch.rm_eo --; /* return with one space */
|
|
#endif
|
|
|
|
/*
|
|
for BSD and Solaris we avoid memrchr
|
|
pos = (char *) memrchr (begin + pmatch.rm_so, ' ',pmatch.rm_eo - pmatch.rm_so);
|
|
*/
|
|
pos = begin+pmatch.rm_eo;
|
|
#ifdef EXTRA_DEBUG
|
|
printf("begin=%c pos=%c rm_so=%d rm_eo=%d\n",*begin,*pos,pmatch.rm_so,pmatch.rm_eo);
|
|
#endif
|
|
do pos--; while (*pos != ' '); /* we should find ' ' because we matched m=audio port */
|
|
|
|
pos++; /* jumping over space */
|
|
oldlen = (pmatch.rm_eo - pmatch.rm_so) - (pos - (begin + pmatch.rm_so)); /* port length */
|
|
|
|
/* convert port to int */
|
|
oldPort = str2s (pos, oldlen, &err);
|
|
#ifdef EXTRA_DEBUG
|
|
printf("port to convert [%.*s] to int\n",oldlen,pos);
|
|
#endif
|
|
if (err)
|
|
{
|
|
LOG(L_ERR,"ERROR: sdp_mangle_port: Error converting [%.*s] to int\n",oldlen,pos);
|
|
#ifdef STRICT_CHECK
|
|
return -7;
|
|
#else
|
|
goto continue1;
|
|
#endif
|
|
}
|
|
if ((oldPort < MIN_ORIGINAL_PORT) || (oldPort > MAX_ORIGINAL_PORT)) /* we silently fail,we ignore this match or return -11 */
|
|
{
|
|
#ifdef EXTRA_DEBUG
|
|
printf("WARNING: sdp_mangle_port: Silent fail for not matching old port %d\n",oldPort);
|
|
#endif
|
|
|
|
LOG(L_WARN,"WARNING: sdp_mangle_port: Silent fail for not matching old port %d\n",oldPort);
|
|
#ifdef STRICT_CHECK
|
|
return -8;
|
|
#else
|
|
goto continue1;
|
|
#endif
|
|
}
|
|
if ((offset[0] != '+')&&(offset[0] != '-')) newPort = offsetValue;//fix value
|
|
else newPort = oldPort + offsetValue;
|
|
/* new port is between 1 and 65536, or so should be */
|
|
if ((newPort < MIN_MANGLED_PORT) || (newPort > MAX_MANGLED_PORT)) /* we silently fail,we ignore this match */
|
|
{
|
|
#ifdef EXTRA_DEBUG
|
|
printf("WARNING: sdp_mangle_port: Silent fail for not matching new port %d\n",newPort);
|
|
#endif
|
|
|
|
LOG(L_WARN,"WARNING: sdp_mangle_port: Silent fail for not matching new port %d\n",newPort);
|
|
#ifdef STRICT_CHECK
|
|
return -9;
|
|
#else
|
|
goto continue1;
|
|
#endif
|
|
}
|
|
|
|
#ifdef EXTRA_DEBUG
|
|
fprintf(stdout,"Extracted port is %d and mangling to %d\n",oldPort,newPort);
|
|
#endif
|
|
|
|
/*
|
|
len = 1;
|
|
while ((newPort = (newPort / 10)) != 0) len++;
|
|
newPort = oldPort + offsetValue;
|
|
*/
|
|
if (newPort >= 10000) len = 5;
|
|
else
|
|
if (newPort >= 1000) len = 4;
|
|
else
|
|
if (newPort >= 100) len = 3;
|
|
else
|
|
if (newPort >= 10) len = 2;
|
|
else len = 1;
|
|
|
|
/* replaced five div's + 1 add with most probably 1 comparison or 2 */
|
|
|
|
/* deleting old port */
|
|
if ((l = del_lump (msg, pmatch.rm_so + off +
|
|
(pos -(begin + pmatch.rm_so)),oldlen, 0)) == 0)
|
|
{
|
|
LOG (L_ERR,"ERROR: sdp_mangle_port: del_lump failed\n");
|
|
return -10;
|
|
}
|
|
s = pkg_malloc (len);
|
|
if (s == 0)
|
|
{
|
|
LOG (L_ERR,"ERROR: sdp_mangle_port : memory allocation failure\n");
|
|
return -11;
|
|
}
|
|
snprintf (buf, len + 1, "%u", newPort); /* converting to string */
|
|
memcpy (s, buf, len);
|
|
|
|
if (insert_new_lump_after (l, s, len, 0) == 0)
|
|
{
|
|
LOG (L_ERR, "ERROR: sdp_mangle_port: could not insert new lump\n");
|
|
pkg_free (s);
|
|
return -12;
|
|
}
|
|
diff = diff + len /*new length */ - oldlen;
|
|
/* new cycle */
|
|
ret++;
|
|
#ifndef STRICT_CHECK
|
|
continue1:
|
|
#endif
|
|
begin = begin + pmatch.rm_eo;
|
|
|
|
} /* while */
|
|
if (needToDealocate)
|
|
{
|
|
regfree (re);
|
|
pkg_free(re);
|
|
#ifdef EXTRA_DEBUG
|
|
fprintf(stdout,"Deallocating expression for port ...\n");
|
|
#endif
|
|
}
|
|
|
|
if (diff != 0)
|
|
{
|
|
newContentLength = oldContentLength + diff;
|
|
patch_content_length (msg, newContentLength);
|
|
}
|
|
|
|
#ifdef EXTRA_DEBUG
|
|
fprintf (stdout,"---END--------MANGLE PORT-----------------\n");
|
|
#endif
|
|
|
|
return ret+2;
|
|
}
|
|
|
|
|
|
int
|
|
sdp_mangle_ip (struct sip_msg *msg, char *oldip, char *newip)
|
|
{
|
|
int i, oldContentLength, newContentLength, diff, oldlen,len,off,ret,needToDealocate;
|
|
unsigned int mask, address, locatedIp;
|
|
struct lump *l;
|
|
regmatch_t pmatch;
|
|
regex_t *re;
|
|
char *s, *pos,*begin,*key;
|
|
char buffer[16]; /* 123.456.789.123\0 */
|
|
|
|
#ifdef EXTRA_DEBUG
|
|
fprintf (stdout,"---START--------MANGLE IP-----------------\n");
|
|
#endif
|
|
|
|
|
|
key = IP_REGEX;
|
|
|
|
/*
|
|
* Checking if msg has a payload
|
|
*/
|
|
if (msg == NULL)
|
|
{
|
|
LOG(L_ERR,"ERROR: sdp_mangle_ip: Received NULL for msg\n");
|
|
return -1;
|
|
}
|
|
if ((msg->content_length==0) &&
|
|
((parse_headers(msg,HDR_CONTENTLENGTH_F,0)==-1) ||
|
|
(msg->content_length==0) )){
|
|
LOG(L_ERR,"ERROR: sdp_mangle_port: bad or missing "
|
|
"Content-Length \n");
|
|
return -2;
|
|
}
|
|
oldContentLength = get_content_length(msg);
|
|
|
|
if (oldContentLength <= 0)
|
|
{
|
|
LOG(L_ERR,"ERROR: sdp_mangle_ip: Received <= for Content-Length\n");
|
|
return -2;
|
|
}
|
|
|
|
/* checking oldip */
|
|
if (oldip == NULL)
|
|
{
|
|
LOG(L_ERR,"ERROR: sdp_mangle_ip: Received NULL for oldip\n");
|
|
return -3;
|
|
}
|
|
/* checking newip */
|
|
if (newip == NULL)
|
|
{
|
|
LOG(L_ERR,"ERROR: sdp_mangle_ip: Received NULL for newip\n");
|
|
return -4;
|
|
}
|
|
i = parse_ip_netmask (oldip, &pos, &mask);
|
|
|
|
if (i == -1)
|
|
{
|
|
/* invalid value for the netmask specified in oldip */
|
|
LOG(L_ERR,"ERROR: sdp_mangle_ip: invalid value for the netmask specified in oldip\n");
|
|
return -5;
|
|
}
|
|
else
|
|
{
|
|
i = parse_ip_address (pos, &address);
|
|
if (pos != NULL) free (pos);
|
|
if (i == 0)
|
|
{
|
|
LOG(L_ERR,"ERROR: sdp_mangle_ip: invalid value for the ip specified in oldip\n");
|
|
return -6; /* parse error in ip */
|
|
}
|
|
}
|
|
|
|
/* now we have in address/netmask binary values */
|
|
|
|
begin = get_body(msg);//msg->buf + msg->first_line.len; // inlocuiesc cu begin = getbody */
|
|
ret = -1;
|
|
len = strlen (newip);
|
|
|
|
/* try to use pre-compiled expressions */
|
|
needToDealocate = 0;
|
|
if (ipExpression != NULL)
|
|
{
|
|
re = ipExpression;
|
|
#ifdef EXTRA_DEBUG
|
|
fprintf(stdout,"Using PRECOMPILED expression for ip ...\n");
|
|
#endif
|
|
|
|
}
|
|
else /* we are not using pre-compiled expressions */
|
|
{
|
|
re = pkg_malloc(sizeof(regex_t));
|
|
if (re == NULL)
|
|
{
|
|
LOG(L_ERR,"ERROR: sdp_mangle_ip: Unable to allocate re\n");
|
|
return -7;
|
|
}
|
|
needToDealocate = 1;
|
|
if ((regcomp (re, key, REG_EXTENDED)) != 0)
|
|
{
|
|
LOG(L_ERR,"ERROR: sdp_mangle_ip: Unable to compile %s \n",key);
|
|
return -8;
|
|
}
|
|
#ifdef EXTRA_DEBUG
|
|
fprintf(stdout,"Using ALLOCATED expression for ip ...\n");
|
|
#endif
|
|
}
|
|
|
|
diff = 0;
|
|
while ((begin < msg->buf + msg->len) && (regexec (re, begin, 1, &pmatch, 0) == 0))
|
|
{
|
|
off = begin - msg->buf;
|
|
if (pmatch.rm_so == -1)
|
|
{
|
|
LOG (L_ERR,"ERROR: sdp_mangler_ip: offset unknown\n");
|
|
return -9;
|
|
}
|
|
|
|
#ifdef STRICT_CHECK
|
|
pmatch.rm_eo --; /* return with one space,\n,\r */
|
|
#endif
|
|
|
|
/*
|
|
for BSD and Solaris we avoid memrchr
|
|
pos = (char *) memrchr (begin + pmatch.rm_so, ' ',pmatch.rm_eo - pmatch.rm_so);
|
|
*/
|
|
pos = begin+pmatch.rm_eo;
|
|
do pos--; while (*pos != ' '); /* we should find ' ' because we matched c=IN IP4 ip */
|
|
|
|
pos++; /* jumping over space */
|
|
oldlen = (pmatch.rm_eo - pmatch.rm_so) - (pos - (begin + pmatch.rm_so)); /* ip length */
|
|
if (oldlen > 15)
|
|
{
|
|
LOG(L_WARN,"WARNING: sdp_mangle_ip: Silent fail because oldlen > 15\n");
|
|
#ifdef STRICT_CHECK
|
|
return -10;
|
|
#else
|
|
goto continue2; /* silent fail return -10; invalid ip format ,probably like 1000.3.12341.2 */
|
|
#endif
|
|
|
|
|
|
}
|
|
buffer[0] = '\0';
|
|
strncat ((char *) buffer, pos, oldlen);
|
|
buffer[oldlen] = '\0';
|
|
i = parse_ip_address (buffer, &locatedIp);
|
|
if (i == 0)
|
|
{
|
|
LOG(L_WARN,"WARNING: sdp_mangle_ip: Silent fail on parsing matched address \n");
|
|
|
|
#ifdef STRICT_CHECK
|
|
return -11;
|
|
#else
|
|
goto continue2;
|
|
#endif
|
|
}
|
|
if (same_net (locatedIp, address, mask) == 0)
|
|
{
|
|
LOG(L_WARN,"WARNING: sdp_mangle_ip: Silent fail because matched address is not in network\n");
|
|
#ifdef EXTRA_DEBUG
|
|
fprintf(stdout,"Extracted ip is %s and not mangling \n",buffer);
|
|
#endif
|
|
goto continue2; /* not in the same net, skipping */
|
|
}
|
|
#ifdef EXTRA_DEBUG
|
|
fprintf(stdout,"Extracted ip is %s and mangling to %s\n",buffer,newip);
|
|
#endif
|
|
|
|
|
|
/* replacing ip */
|
|
|
|
/* deleting old ip */
|
|
if ((l = del_lump (msg,pmatch.rm_so + off +
|
|
(pos - (begin + pmatch.rm_so)),oldlen, 0)) == 0)
|
|
{
|
|
LOG (L_ERR,"ERROR: sdp_mangle_ip: del_lump failed\n");
|
|
return -12;
|
|
}
|
|
s = pkg_malloc (len);
|
|
if (s == 0)
|
|
{
|
|
LOG (L_ERR,"ERROR: sdp_mangle_ip: mem. allocation failure\n");
|
|
return -13;
|
|
}
|
|
memcpy (s, newip, len);
|
|
|
|
if (insert_new_lump_after (l, s, len, 0) == 0)
|
|
{
|
|
LOG (L_ERR, "ERROR: sdp_mangle_ip: could not insert new lump\n");
|
|
pkg_free (s);
|
|
return -14;
|
|
}
|
|
diff = diff + len /*new length */ - oldlen;
|
|
/* new cycle */
|
|
ret++;
|
|
continue2:
|
|
begin = begin + pmatch.rm_eo;
|
|
|
|
} /* while */
|
|
if (needToDealocate)
|
|
{
|
|
regfree (re); /* if I am going to use pre-compiled expressions to be removed */
|
|
pkg_free(re);
|
|
#ifdef EXTRA_DEBUG
|
|
fprintf(stdout,"Deallocating expression for ip ...\n");
|
|
#endif
|
|
}
|
|
|
|
if (diff != 0)
|
|
{
|
|
newContentLength = oldContentLength + diff;
|
|
patch_content_length (msg, newContentLength);
|
|
}
|
|
|
|
#ifdef EXTRA_DEBUG
|
|
fprintf (stdout,"---END--------MANGLE IP-----------------\n");
|
|
#endif
|
|
|
|
return ret+2;
|
|
|
|
}
|
|
|
|
int compile_expresions(char *port,char *ip)
|
|
{
|
|
portExpression = NULL;
|
|
portExpression = pkg_malloc(sizeof(regex_t));
|
|
if (portExpression != NULL)
|
|
{
|
|
if ((regcomp (portExpression,port, REG_EXTENDED)) != 0)
|
|
{
|
|
LOG(L_ERR,"ERROR: compile_expresions: Unable to compile portExpression [%s]\n",port);
|
|
pkg_free(portExpression);
|
|
portExpression = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LOG(L_ERR,"ERROR: compile_expresions: Unable to alloc portExpression \n");
|
|
}
|
|
|
|
ipExpression = NULL;
|
|
ipExpression = pkg_malloc(sizeof(regex_t));
|
|
if (ipExpression != NULL)
|
|
{
|
|
if ((regcomp (ipExpression,ip, REG_EXTENDED)) != 0)
|
|
{
|
|
LOG(L_ERR,"ERROR: compile_expresions: Unable to compile ipExpression [%s]\n",ip);
|
|
pkg_free(ipExpression);
|
|
ipExpression = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LOG(L_ERR,"ERROR: compile_expresions: Unable to alloc ipExpression \n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int free_compiled_expresions()
|
|
{
|
|
if (portExpression != NULL)
|
|
{
|
|
regfree(portExpression);
|
|
pkg_free(portExpression);
|
|
portExpression = NULL;
|
|
}
|
|
if (ipExpression != NULL)
|
|
{
|
|
regfree(ipExpression);
|
|
pkg_free(ipExpression);
|
|
ipExpression = NULL;
|
|
}
|
|
return 0;
|
|
}
|
|
|