4 * Copyright (C) 2001-2003 FhG Fokus
6 * This file is part of Kamailio, a free SIP server.
8 * Kamailio is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version
13 * Kamailio is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include <sys/types.h>
29 #include "sdp_mangler.h"
30 #include "ip_helper.h"
33 #include "../../core/mem/mem.h"
34 #include "../../core/data_lump.h"
35 #include "../../core/parser/hf.h"
36 #include "../../core/parser/parse_content.h"
37 #include "../../core/parser/parse_uri.h"
38 #include "../../core/parser/contact/parse_contact.h"
39 #include "../../core/ut.h"
40 #include "../../core/parser/msg_parser.h" /* struct sip_msg */
42 regex_t *portExpression;
43 regex_t *ipExpression;
48 sdp_mangle_port (struct sip_msg *msg, char *offset, char *unused)
50 int oldContentLength, newContentLength, oldlen, err, oldPort, newPort,
51 diff, offsetValue,len,off,ret,needToDealocate;
55 char *s, *pos,*begin,*key;
62 * Checking if msg has a payload
66 LOG(L_ERR,"ERROR: sdp_mangle_port: Received NULL for msg \n");
70 if ((msg->content_length==0) &&
71 ((parse_headers(msg,HDR_CONTENTLENGTH_F,0)==-1) ||
72 (msg->content_length==0) )){
73 LOG(L_ERR,"ERROR: sdp_mangle_port: bad or missing "
78 oldContentLength = get_content_length(msg);
80 if (oldContentLength <= 0)
82 LOG(L_ERR,"ERROR: sdp_mangle_port: Received <= 0 for Content-Length \n");
88 if (sscanf (offset, "%d", &offsetValue) != 1)
90 LOG(L_ERR,"ERROR: sdp_mangle_port: Invalid value for offset \n");
94 //offsetValue = (int)offset;
96 fprintf (stdout,"---START--------MANGLE PORT-----------------\n");
97 fprintf(stdout,"===============OFFSET = %d\n",offsetValue);
100 if ((offsetValue < MIN_OFFSET_VALUE) || (offsetValue > MAX_OFFSET_VALUE))
102 LOG(L_ERR,"ERROR: sdp_mangle_port: Invalid value %d for offset \n",offsetValue);
105 begin = get_body(msg); //msg->buf + msg->first_line.len; // inlocuiesc cu begin = getbody */
108 /* try to use pre-compiled expressions */
110 if (portExpression != NULL)
114 fprintf(stdout,"Using PRECOMPILED expression for port ...\n");
117 else /* we are not using pre-compiled expressions */
119 re = pkg_malloc(sizeof(regex_t));
122 LOG(L_ERR,"ERROR: sdp_mangle_port: Unable to allocate re\n");
126 if ((regcomp (re, key, REG_EXTENDED)) != 0)
128 LOG(L_ERR,"ERROR: sdp_mangle_port: Unable to compile %s \n",key);
132 fprintf(stdout,"Using ALLOCATED expression for port ...\n");
138 while ((begin < msg->buf + msg->len) && (regexec (re, begin, 1, &pmatch, 0) == 0))
140 off = begin - msg->buf;
141 if (pmatch.rm_so == -1)
143 LOG (L_ERR, "ERROR: sdp_mangle_port: offset unknown\n");
148 pmatch.rm_eo --; /* return with one space */
152 for BSD and Solaris we avoid memrchr
153 pos = (char *) memrchr (begin + pmatch.rm_so, ' ',pmatch.rm_eo - pmatch.rm_so);
155 pos = begin+pmatch.rm_eo;
157 printf("begin=%c pos=%c rm_so=%d rm_eo=%d\n",*begin,*pos,pmatch.rm_so,pmatch.rm_eo);
159 do pos--; while (*pos != ' '); /* we should find ' ' because we matched m=audio port */
161 pos++; /* jumping over space */
162 oldlen = (pmatch.rm_eo - pmatch.rm_so) - (pos - (begin + pmatch.rm_so)); /* port length */
164 /* convert port to int */
165 oldPort = str2s (pos, oldlen, &err);
167 printf("port to convert [%.*s] to int\n",oldlen,pos);
171 LOG(L_ERR,"ERROR: sdp_mangle_port: Error converting [%.*s] to int\n",oldlen,pos);
178 if ((oldPort < MIN_ORIGINAL_PORT) || (oldPort > MAX_ORIGINAL_PORT)) /* we silently fail,we ignore this match or return -11 */
181 printf("WARNING: sdp_mangle_port: Silent fail for not matching old port %d\n",oldPort);
184 LOG(L_WARN,"WARNING: sdp_mangle_port: Silent fail for not matching old port %d\n",oldPort);
191 if ((offset[0] != '+')&&(offset[0] != '-')) newPort = offsetValue;//fix value
192 else newPort = oldPort + offsetValue;
193 /* new port is between 1 and 65536, or so should be */
194 if ((newPort < MIN_MANGLED_PORT) || (newPort > MAX_MANGLED_PORT)) /* we silently fail,we ignore this match */
197 printf("WARNING: sdp_mangle_port: Silent fail for not matching new port %d\n",newPort);
200 LOG(L_WARN,"WARNING: sdp_mangle_port: Silent fail for not matching new port %d\n",newPort);
209 fprintf(stdout,"Extracted port is %d and mangling to %d\n",oldPort,newPort);
214 while ((newPort = (newPort / 10)) != 0) len++;
215 newPort = oldPort + offsetValue;
217 if (newPort >= 10000) len = 5;
219 if (newPort >= 1000) len = 4;
221 if (newPort >= 100) len = 3;
223 if (newPort >= 10) len = 2;
226 /* replaced five div's + 1 add with most probably 1 comparison or 2 */
228 /* deleting old port */
229 if ((l = del_lump (msg, pmatch.rm_so + off +
230 (pos -(begin + pmatch.rm_so)),oldlen, 0)) == 0)
232 LOG (L_ERR,"ERROR: sdp_mangle_port: del_lump failed\n");
235 s = pkg_malloc (len);
238 LOG (L_ERR,"ERROR: sdp_mangle_port : memory allocation failure\n");
241 snprintf (buf, len + 1, "%u", newPort); /* converting to string */
242 memcpy (s, buf, len);
244 if (insert_new_lump_after (l, s, len, 0) == 0)
246 LOG (L_ERR, "ERROR: sdp_mangle_port: could not insert new lump\n");
250 diff = diff + len /*new length */ - oldlen;
256 begin = begin + pmatch.rm_eo;
264 fprintf(stdout,"Deallocating expression for port ...\n");
270 newContentLength = oldContentLength + diff;
271 patch_content_length (msg, newContentLength);
275 fprintf (stdout,"---END--------MANGLE PORT-----------------\n");
282 int sdp_mangle_ip(struct sip_msg *msg, char *oldip, char *newip)
284 int i, oldContentLength, newContentLength, diff, oldlen, len, off, ret,
286 unsigned int mask, address, locatedIp;
290 char *s, *pos, *begin, *key;
291 char buffer[16]; /* 123.456.789.123\0 */
294 fprintf(stdout, "---START--------MANGLE IP-----------------\n");
301 * Checking if msg has a payload
304 LOG(L_ERR, "ERROR: sdp_mangle_ip: Received NULL for msg\n");
307 if((msg->content_length == 0)
308 && ((parse_headers(msg, HDR_CONTENTLENGTH_F, 0) == -1)
309 || (msg->content_length == 0))) {
310 LOG(L_ERR, "ERROR: sdp_mangle_port: bad or missing "
311 "Content-Length \n");
314 oldContentLength = get_content_length(msg);
316 if(oldContentLength <= 0) {
317 LOG(L_ERR, "ERROR: sdp_mangle_ip: Received <= for Content-Length\n");
323 LOG(L_ERR, "ERROR: sdp_mangle_ip: Received NULL for oldip\n");
328 LOG(L_ERR, "ERROR: sdp_mangle_ip: Received NULL for newip\n");
331 i = parse_ip_netmask(oldip, &pos, &mask);
333 if(i == -1 || pos == NULL) {
334 /* invalid value for the netmask specified in oldip */
335 LOG(L_ERR, "ERROR: sdp_mangle_ip: invalid value for the netmask "
336 "specified in oldip\n");
341 i = parse_ip_address(pos, &address);
344 LOG(L_ERR, "ERROR: sdp_mangle_ip: invalid value for the ip "
345 "specified in oldip\n");
346 return -6; /* parse error in ip */
350 /* now we have in address/netmask binary values */
353 msg); //msg->buf + msg->first_line.len; // inlocuiesc cu begin = getbody */
357 /* try to use pre-compiled expressions */
359 if(ipExpression != NULL) {
362 fprintf(stdout, "Using PRECOMPILED expression for ip ...\n");
365 } else /* we are not using pre-compiled expressions */
367 re = pkg_malloc(sizeof(regex_t));
369 LOG(L_ERR, "ERROR: sdp_mangle_ip: Unable to allocate re\n");
373 if((regcomp(re, key, REG_EXTENDED)) != 0) {
374 LOG(L_ERR, "ERROR: sdp_mangle_ip: Unable to compile %s \n", key);
379 fprintf(stdout, "Using ALLOCATED expression for ip ...\n");
384 while((begin < msg->buf + msg->len)
385 && (regexec(re, begin, 1, &pmatch, 0) == 0)) {
386 off = begin - msg->buf;
387 if(pmatch.rm_so == -1) {
388 LOG(L_ERR, "ERROR: sdp_mangler_ip: offset unknown\n");
394 pmatch.rm_eo--; /* return with one space,\n,\r */
398 for BSD and Solaris we avoid memrchr
399 pos = (char *) memrchr (begin + pmatch.rm_so, ' ',pmatch.rm_eo - pmatch.rm_so);
401 pos = begin + pmatch.rm_eo;
405 != ' '); /* we should find ' ' because we matched c=IN IP4 ip */
407 pos++; /* jumping over space */
408 oldlen = (pmatch.rm_eo - pmatch.rm_so)
409 - (pos - (begin + pmatch.rm_so)); /* ip length */
411 LOG(L_WARN, "WARNING: sdp_mangle_ip: Silent fail because oldlen > "
417 goto continue2; /* silent fail return -10; invalid ip format ,probably like 1000.3.12341.2 */
421 strncat((char *)buffer, pos, oldlen);
422 buffer[oldlen] = '\0';
423 i = parse_ip_address(buffer, &locatedIp);
425 LOG(L_WARN, "WARNING: sdp_mangle_ip: Silent fail on parsing "
426 "matched address \n");
435 if(same_net(locatedIp, address, mask) == 0) {
436 LOG(L_WARN, "WARNING: sdp_mangle_ip: Silent fail because matched "
437 "address is not in network\n");
439 fprintf(stdout, "Extracted ip is %s and not mangling \n", buffer);
441 goto continue2; /* not in the same net, skipping */
444 fprintf(stdout, "Extracted ip is %s and mangling to %s\n", buffer,
450 /* deleting old ip */
451 if((l = del_lump(msg,
452 pmatch.rm_so + off + (pos - (begin + pmatch.rm_so)), oldlen,
455 LOG(L_ERR, "ERROR: sdp_mangle_ip: del_lump failed\n");
461 LOG(L_ERR, "ERROR: sdp_mangle_ip: mem. allocation failure\n");
465 memcpy(s, newip, len);
467 if(insert_new_lump_after(l, s, len, 0) == 0) {
468 LOG(L_ERR, "ERROR: sdp_mangle_ip: could not insert new lump\n");
473 diff = diff + len /*new length */ - oldlen;
477 begin = begin + pmatch.rm_eo;
480 if(needToDealocate) {
481 regfree(re); /* if I am going to use pre-compiled expressions to be removed */
484 fprintf(stdout, "Deallocating expression for ip ...\n");
489 newContentLength = oldContentLength + diff;
490 patch_content_length(msg, newContentLength);
494 fprintf(stdout, "---END--------MANGLE IP-----------------\n");
500 int compile_expresions(char *port,char *ip)
502 portExpression = NULL;
503 portExpression = pkg_malloc(sizeof(regex_t));
504 if (portExpression != NULL)
506 if ((regcomp (portExpression,port, REG_EXTENDED)) != 0)
508 LOG(L_ERR,"ERROR: compile_expresions: Unable to compile portExpression [%s]\n",port);
509 pkg_free(portExpression);
510 portExpression = NULL;
515 LOG(L_ERR,"ERROR: compile_expresions: Unable to alloc portExpression \n");
519 ipExpression = pkg_malloc(sizeof(regex_t));
520 if (ipExpression != NULL)
522 if ((regcomp (ipExpression,ip, REG_EXTENDED)) != 0)
524 LOG(L_ERR,"ERROR: compile_expresions: Unable to compile ipExpression [%s]\n",ip);
525 pkg_free(ipExpression);
531 LOG(L_ERR,"ERROR: compile_expresions: Unable to alloc ipExpression \n");
537 int free_compiled_expresions()
539 if (portExpression != NULL)
541 regfree(portExpression);
542 pkg_free(portExpression);
543 portExpression = NULL;
545 if (ipExpression != NULL)
547 regfree(ipExpression);
548 pkg_free(ipExpression);