core, lib, modules: updated include paths for header files
[sip-router] / src / modules / mangler / sdp_mangler.c
1 /*
2  * mangler module
3  *
4  * Copyright (C) 2001-2003 FhG Fokus
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
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
12  *
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.
17  *
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
21  */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/types.h>
27 #include <regex.h>
28
29 #include "sdp_mangler.h"
30 #include "ip_helper.h"
31 #include "utils.h"
32 #include "common.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 */
41
42 regex_t *portExpression;
43 regex_t *ipExpression;
44
45
46
47 int
48 sdp_mangle_port (struct sip_msg *msg, char *offset, char *unused)
49 {
50         int oldContentLength, newContentLength, oldlen, err, oldPort, newPort,
51                 diff, offsetValue,len,off,ret,needToDealocate;
52         struct lump *l;
53         regmatch_t pmatch;
54         regex_t *re;
55         char *s, *pos,*begin,*key;
56         char buf[6];
57         
58         
59         
60         key = PORT_REGEX;
61         /*
62          * Checking if msg has a payload
63          */
64         if (msg == NULL)
65                 {
66                 LOG(L_ERR,"ERROR: sdp_mangle_port: Received NULL for msg \n");
67                 return -1;
68                 }
69                 
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 "
74                                 "Content-Length \n");
75                 return -2;
76         }
77
78         oldContentLength = get_content_length(msg);
79         
80         if (oldContentLength <= 0)
81                 {
82                 LOG(L_ERR,"ERROR: sdp_mangle_port: Received <= 0 for Content-Length \n");
83                 return -2;
84                 }
85         
86         if (offset == NULL)
87                 return -14;
88         if (sscanf (offset, "%d", &offsetValue) != 1)
89         {
90                 LOG(L_ERR,"ERROR: sdp_mangle_port: Invalid value for offset \n");
91                 return -13;
92         }
93         
94         //offsetValue = (int)offset;
95 #ifdef EXTRA_DEBUG
96         fprintf (stdout,"---START--------MANGLE PORT-----------------\n");
97         fprintf(stdout,"===============OFFSET = %d\n",offsetValue);
98 #endif
99         
100         if ((offsetValue < MIN_OFFSET_VALUE) || (offsetValue > MAX_OFFSET_VALUE))
101         {
102                 LOG(L_ERR,"ERROR: sdp_mangle_port: Invalid value %d for offset \n",offsetValue);
103                 return -3;
104         }
105         begin = get_body(msg); //msg->buf + msg->first_line.len;        // inlocuiesc cu begin = getbody */
106         ret = -1;
107
108         /* try to use pre-compiled expressions */
109         needToDealocate = 0;
110         if (portExpression != NULL) 
111                 {
112                 re = portExpression;
113 #ifdef EXTRA_DEBUG
114                 fprintf(stdout,"Using PRECOMPILED expression for port ...\n");
115 #endif
116                 }
117                 else /* we are not using pre-compiled expressions */
118                         {
119                         re = pkg_malloc(sizeof(regex_t));
120                         if (re == NULL)
121                                 {
122                                 LOG(L_ERR,"ERROR: sdp_mangle_port: Unable to allocate re\n");
123                                 return -4;
124                                 }
125                         needToDealocate = 1;
126                         if ((regcomp (re, key, REG_EXTENDED)) != 0)
127                                 {
128                                 LOG(L_ERR,"ERROR: sdp_mangle_port: Unable to compile %s \n",key);
129                                 return -5;
130                                 }
131 #ifdef EXTRA_DEBUG
132                 fprintf(stdout,"Using ALLOCATED expression for port ...\n");
133 #endif
134
135                         }
136         
137         diff = 0;
138         while ((begin < msg->buf + msg->len) && (regexec (re, begin, 1, &pmatch, 0) == 0))
139         {
140                 off = begin - msg->buf;
141                 if (pmatch.rm_so == -1)
142                 {
143                         LOG (L_ERR, "ERROR: sdp_mangle_port: offset unknown\n");
144                         return -6;
145                 }
146         
147 #ifdef STRICT_CHECK
148                 pmatch.rm_eo --; /* return with one space */
149 #endif
150         
151                 /* 
152                 for BSD and Solaris we avoid memrchr
153                 pos = (char *) memrchr (begin + pmatch.rm_so, ' ',pmatch.rm_eo - pmatch.rm_so); 
154                 */
155                 pos = begin+pmatch.rm_eo;
156 #ifdef EXTRA_DEBUG
157                 printf("begin=%c pos=%c rm_so=%d rm_eo=%d\n",*begin,*pos,pmatch.rm_so,pmatch.rm_eo);
158 #endif
159                 do pos--; while (*pos != ' '); /* we should find ' ' because we matched m=audio port */
160                 
161                 pos++;          /* jumping over space */
162                 oldlen = (pmatch.rm_eo - pmatch.rm_so) - (pos - (begin + pmatch.rm_so));        /* port length */
163
164                 /* convert port to int */
165                 oldPort = str2s (pos, oldlen, &err);
166 #ifdef EXTRA_DEBUG
167                 printf("port to convert [%.*s] to int\n",oldlen,pos);
168 #endif
169                 if (err)
170                         {
171                         LOG(L_ERR,"ERROR: sdp_mangle_port: Error converting [%.*s] to int\n",oldlen,pos);
172 #ifdef STRICT_CHECK
173                         return -7;
174 #else
175                         goto continue1;
176 #endif
177                         }
178                 if ((oldPort < MIN_ORIGINAL_PORT) || (oldPort > MAX_ORIGINAL_PORT))     /* we silently fail,we ignore this match or return -11 */
179                 {
180 #ifdef EXTRA_DEBUG
181                 printf("WARNING: sdp_mangle_port: Silent fail for not matching old port %d\n",oldPort);
182 #endif
183
184                         LOG(L_WARN,"WARNING: sdp_mangle_port: Silent fail for not matching old port %d\n",oldPort);
185 #ifdef STRICT_CHECK
186                         return -8;
187 #else
188                         goto continue1;
189 #endif
190                 }
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 */
195                 {
196 #ifdef EXTRA_DEBUG
197                 printf("WARNING: sdp_mangle_port: Silent fail for not matching new port %d\n",newPort);
198 #endif
199                 
200                         LOG(L_WARN,"WARNING: sdp_mangle_port: Silent fail for not matching new port %d\n",newPort);
201 #ifdef STRICT_CHECK
202                         return -9;
203 #else
204                         goto continue1;
205 #endif
206                 }
207
208 #ifdef EXTRA_DEBUG
209                 fprintf(stdout,"Extracted port is %d and mangling to %d\n",oldPort,newPort);
210 #endif
211
212                 /*
213                 len = 1;
214                 while ((newPort = (newPort / 10)) != 0) len++;
215                 newPort = oldPort + offsetValue;
216                 */
217                 if (newPort >= 10000) len = 5;
218                         else
219                                 if (newPort >= 1000) len = 4;
220                                         else
221                                                 if (newPort >= 100) len = 3;
222                                                         else
223                                                                 if (newPort >= 10) len = 2;
224                                                                         else len = 1;
225
226                 /* replaced five div's + 1 add with most probably 1 comparison or 2 */                                                  
227                 
228                 /* deleting old port */
229                 if ((l = del_lump (msg, pmatch.rm_so + off + 
230                                                 (pos -(begin + pmatch.rm_so)),oldlen, 0)) == 0)
231                 {
232                         LOG (L_ERR,"ERROR: sdp_mangle_port: del_lump failed\n");
233                         return -10;
234                 }
235                 s = pkg_malloc (len);
236                 if (s == 0)
237                 {
238                         LOG (L_ERR,"ERROR: sdp_mangle_port : memory allocation failure\n");
239                         return -11;
240                 }
241                 snprintf (buf, len + 1, "%u", newPort); /* converting to string */
242                 memcpy (s, buf, len);
243
244                 if (insert_new_lump_after (l, s, len, 0) == 0)
245                 {
246                         LOG (L_ERR, "ERROR: sdp_mangle_port: could not insert new lump\n");
247                         pkg_free (s);
248                         return -12;
249                 }
250                 diff = diff + len /*new length */  - oldlen;
251                 /* new cycle */
252                 ret++;
253 #ifndef STRICT_CHECK
254 continue1:
255 #endif
256                 begin = begin + pmatch.rm_eo;
257
258         }                       /* while  */
259         if (needToDealocate)
260                 {
261                 regfree (re);
262                 pkg_free(re);
263 #ifdef EXTRA_DEBUG
264                 fprintf(stdout,"Deallocating expression for port ...\n");
265 #endif
266                 }
267         
268         if (diff != 0)
269         {
270                 newContentLength = oldContentLength + diff;
271                 patch_content_length (msg, newContentLength);
272         }
273
274 #ifdef EXTRA_DEBUG
275         fprintf (stdout,"---END--------MANGLE PORT-----------------\n");
276 #endif
277
278         return ret+2;
279 }
280
281
282 int
283 sdp_mangle_ip (struct sip_msg *msg, char *oldip, char *newip)
284 {
285         int i, oldContentLength, newContentLength, diff, oldlen,len,off,ret,needToDealocate;
286         unsigned int mask, address, locatedIp;
287         struct lump *l;
288         regmatch_t pmatch;
289         regex_t *re;
290         char *s, *pos,*begin,*key;
291         char buffer[16];        /* 123.456.789.123\0 */
292
293 #ifdef EXTRA_DEBUG
294         fprintf (stdout,"---START--------MANGLE IP-----------------\n");
295 #endif
296
297         
298         key = IP_REGEX;
299
300         /*
301          * Checking if msg has a payload
302          */
303         if (msg == NULL)
304                 {
305                 LOG(L_ERR,"ERROR: sdp_mangle_ip: Received NULL for msg\n");
306                 return -1;
307                 }
308         if ((msg->content_length==0) &&
309                                 ((parse_headers(msg,HDR_CONTENTLENGTH_F,0)==-1) ||
310                                  (msg->content_length==0) )){
311                         LOG(L_ERR,"ERROR: sdp_mangle_port: bad or missing "
312                                         "Content-Length \n");
313                         return -2;
314                 }
315         oldContentLength = get_content_length(msg);
316         
317         if (oldContentLength <= 0)
318                 {
319                 LOG(L_ERR,"ERROR: sdp_mangle_ip: Received <= for Content-Length\n");
320                 return -2;
321                 }
322
323         /* checking oldip */
324         if (oldip == NULL)
325                 {
326                 LOG(L_ERR,"ERROR: sdp_mangle_ip: Received NULL for oldip\n");
327                 return -3;
328                 }
329         /* checking newip */
330         if (newip == NULL)
331                 {
332                 LOG(L_ERR,"ERROR: sdp_mangle_ip: Received NULL for newip\n");
333                 return -4;
334                 }
335         i = parse_ip_netmask (oldip, &pos, &mask);
336
337         if (i == -1)
338         {
339                 /* invalid value for the netmask specified in oldip */
340                 LOG(L_ERR,"ERROR: sdp_mangle_ip: invalid value for the netmask specified in oldip\n");
341                 return -5;
342         }
343         else
344         {
345                 i = parse_ip_address (pos, &address);
346                 if (pos != NULL) free (pos);
347                 if (i == 0)
348                         {
349                         LOG(L_ERR,"ERROR: sdp_mangle_ip: invalid value for the ip specified in oldip\n");
350                         return -6;      /* parse error in ip */
351                         }
352         }
353
354         /* now we have in address/netmask binary values */
355
356         begin = get_body(msg);//msg->buf + msg->first_line.len; // inlocuiesc cu begin = getbody */
357         ret = -1;
358         len = strlen (newip);
359
360         /* try to use pre-compiled expressions */
361         needToDealocate = 0;
362         if (ipExpression != NULL) 
363                 {
364                 re = ipExpression;
365 #ifdef EXTRA_DEBUG
366                 fprintf(stdout,"Using PRECOMPILED expression for ip ...\n");
367 #endif
368
369                 }
370                 else /* we are not using pre-compiled expressions */
371                         {
372                         re = pkg_malloc(sizeof(regex_t));
373                         if (re == NULL)
374                                 {
375                                 LOG(L_ERR,"ERROR: sdp_mangle_ip: Unable to allocate re\n");
376                                 return -7;
377                                 }
378                         needToDealocate = 1;
379                         if ((regcomp (re, key, REG_EXTENDED)) != 0)
380                                 {
381                                 LOG(L_ERR,"ERROR: sdp_mangle_ip: Unable to compile %s \n",key);
382                                 return -8;
383                                 }
384 #ifdef EXTRA_DEBUG
385                 fprintf(stdout,"Using ALLOCATED expression for ip ...\n");
386 #endif
387                         }
388
389         diff = 0;
390         while ((begin < msg->buf + msg->len) && (regexec (re, begin, 1, &pmatch, 0) == 0))
391         {
392                 off = begin - msg->buf;
393                 if (pmatch.rm_so == -1)
394                 {
395                         LOG (L_ERR,"ERROR: sdp_mangler_ip: offset unknown\n");
396                         return -9;
397                 }
398         
399 #ifdef STRICT_CHECK
400                 pmatch.rm_eo --; /* return with one space,\n,\r */
401 #endif
402         
403                 /* 
404                 for BSD and Solaris we avoid memrchr
405                 pos = (char *) memrchr (begin + pmatch.rm_so, ' ',pmatch.rm_eo - pmatch.rm_so); 
406                 */
407                 pos = begin+pmatch.rm_eo;
408                 do pos--; while (*pos != ' '); /* we should find ' ' because we matched c=IN IP4 ip */
409
410                 pos++;          /* jumping over space */
411                 oldlen = (pmatch.rm_eo - pmatch.rm_so) - (pos - (begin + pmatch.rm_so));        /* ip length */
412                 if (oldlen > 15)
413                 {
414                         LOG(L_WARN,"WARNING: sdp_mangle_ip: Silent fail because oldlen > 15\n");
415 #ifdef STRICT_CHECK
416                         return -10;
417 #else 
418                         goto continue2; /* silent fail return -10; invalid ip format ,probably like 1000.3.12341.2 */
419 #endif
420
421                         
422                 }
423                 buffer[0] = '\0';
424                 strncat ((char *) buffer, pos, oldlen); 
425                 buffer[oldlen] = '\0';
426                 i = parse_ip_address (buffer, &locatedIp);
427                 if (i == 0)
428                 {
429                         LOG(L_WARN,"WARNING: sdp_mangle_ip: Silent fail on parsing matched address \n");
430                         
431 #ifdef STRICT_CHECK
432                         return -11;
433 #else 
434                         goto continue2; 
435 #endif
436                 }
437                 if (same_net (locatedIp, address, mask) == 0)
438                 {
439                         LOG(L_WARN,"WARNING: sdp_mangle_ip: Silent fail because matched address is not in network\n");
440 #ifdef EXTRA_DEBUG
441                 fprintf(stdout,"Extracted ip is %s and not mangling \n",buffer);
442 #endif
443                         goto continue2; /* not in the same net, skipping */
444                 }
445 #ifdef EXTRA_DEBUG
446                 fprintf(stdout,"Extracted ip is %s and mangling to %s\n",buffer,newip);
447 #endif
448
449
450                 /* replacing ip */
451
452                 /* deleting old ip */
453                 if ((l = del_lump (msg,pmatch.rm_so + off + 
454                                                 (pos - (begin + pmatch.rm_so)),oldlen, 0)) == 0)
455                 {
456                         LOG (L_ERR,"ERROR: sdp_mangle_ip: del_lump failed\n");
457                         return -12;
458                 }
459                 s = pkg_malloc (len);
460                 if (s == 0)
461                 {
462                         LOG (L_ERR,"ERROR: sdp_mangle_ip: mem. allocation failure\n");
463                         return -13;
464                 }
465                 memcpy (s, newip, len);
466
467                 if (insert_new_lump_after (l, s, len, 0) == 0)
468                 {
469                         LOG (L_ERR, "ERROR: sdp_mangle_ip: could not insert new lump\n");
470                         pkg_free (s);
471                         return -14;
472                 }
473                 diff = diff + len /*new length */  - oldlen;
474                 /* new cycle */
475                 ret++;
476 continue2:
477                 begin = begin + pmatch.rm_eo;
478
479         }                       /* while */
480         if (needToDealocate)
481         {
482         regfree (re);           /* if I am going to use pre-compiled expressions to be removed */
483         pkg_free(re);
484 #ifdef EXTRA_DEBUG
485                 fprintf(stdout,"Deallocating expression for ip ...\n");
486 #endif
487         }
488         
489         if (diff != 0)
490         {
491                 newContentLength = oldContentLength + diff;
492                 patch_content_length (msg, newContentLength);
493         }
494
495 #ifdef EXTRA_DEBUG
496         fprintf (stdout,"---END--------MANGLE IP-----------------\n");
497 #endif
498
499         return ret+2;
500
501 }
502
503 int compile_expresions(char *port,char *ip)
504 {
505         portExpression = NULL;
506         portExpression = pkg_malloc(sizeof(regex_t));
507         if (portExpression != NULL)
508                 {
509                 if ((regcomp (portExpression,port, REG_EXTENDED)) != 0)
510                         {
511                         LOG(L_ERR,"ERROR: compile_expresions: Unable to compile portExpression [%s]\n",port);
512                         pkg_free(portExpression);
513                         portExpression = NULL;
514                         }
515                 }
516         else
517                 {
518                         LOG(L_ERR,"ERROR: compile_expresions: Unable to alloc portExpression \n");
519                 }
520         
521         ipExpression = NULL;
522         ipExpression = pkg_malloc(sizeof(regex_t));
523         if (ipExpression != NULL)
524                 {
525                 if ((regcomp (ipExpression,ip, REG_EXTENDED)) != 0)
526                         {
527                         LOG(L_ERR,"ERROR: compile_expresions: Unable to compile ipExpression [%s]\n",ip);
528                         pkg_free(ipExpression);
529                         ipExpression = NULL;
530                         }
531                 }
532         else
533                 {
534                         LOG(L_ERR,"ERROR: compile_expresions: Unable to alloc ipExpression \n");
535                 }
536         
537         return 0;
538 }
539
540 int free_compiled_expresions()
541 {
542         if (portExpression != NULL) 
543                 {
544                 regfree(portExpression);
545                 pkg_free(portExpression);
546                 portExpression = NULL;
547                 }
548         if (ipExpression != NULL) 
549                 {
550                 regfree(ipExpression);
551                 pkg_free(ipExpression);
552                 ipExpression = NULL;
553                 }
554         return 0;
555 }
556