00001 #include <stdlib.h>
00002 #include <stdio.h>
00003 #include <string.h>
00004 #include <unistd.h>
00005 #include <errno.h>
00006 #include <sys/un.h>
00007 #include <sys/poll.h>
00008 #include <sys/uio.h>
00009 #include <sys/types.h>
00010 #include <sys/socket.h>
00011 #include <arpa/inet.h>
00012
00013
00014 #include "../../timer.h"
00015 #include "../../dprint.h"
00016 #include "../../mem/mem.h"
00017 #include "../../str.h"
00018 #include "../../trim.h"
00019 #include "../../parser/msg_parser.h"
00020 #include "../../parser/parser_f.h"
00021 #include "../../parser/parse_from.h"
00022 #include "../../parser/parse_uri.h"
00023 #include "../../parser/contact/parse_contact.h"
00024 #include "../../data_lump.h"
00025 #include "sdp_util.h"
00026 #include "mod.h"
00027 #include "nat_helper.h"
00028 #include "sip.h"
00029
00030 extern int pcscf_nat_enable;
00031 extern struct rtpp_head rtpp_list;
00032 extern int rtpp_node_count ;
00033 extern char *rtpproxy_sock ;
00034 extern int rtpproxy_enable;
00035 extern int rtpproxy_disable_tout ;
00036 extern int rtpproxy_retr ;
00037 extern int rtpproxy_tout ;
00038 unsigned int myseqn ;
00039
00040 static str sup_ptypes[] = {
00041 {.s = "udp", .len = 3},
00042 {.s = "udptl", .len = 5},
00043 {.s = "rtp/avp", .len = 7},
00044 {.s = NULL, .len = 0}
00045 };
00046
00047 extern network_t nets_1918[];
00048
00049
00050 int check_content_type(struct sip_msg *msg)
00051 {
00052 static unsigned int appl[16] = {
00053 0x6c707061,0x6c707041,0x6c705061,
00054 0x6c705041,0x6c507061,0x6c507041,
00055 0x6c505061,0x6c505041,0x4c707061,
00056 0x4c707041,0x4c705061,0x4c705041,
00057 0x4c507061,0x4c507041,0x4c505061,
00058 0x4c505041};
00059 static unsigned int icat[16] = {
00060 0x74616369,0x74616349,0x74614369,
00061 0x74614349,0x74416369,0x74416349,
00062 0x74414369,0x74414349,0x54616369,
00063 0x54616349,0x54614369,0x54614349,
00064 0x54416369,0x54416349,0x54414369,
00065 0x54414349};
00066 static unsigned int ion_[8] = {
00067 0x006e6f69,0x006e6f49,0x006e4f69,
00068 0x006e4f49,0x004e6f69,0x004e6f49,
00069 0x004e4f69,0x004e4f49};
00070 static unsigned int sdp_[8] = {
00071 0x00706473,0x00706453,0x00704473,
00072 0x00704453,0x00506473,0x00506453,
00073 0x00504473,0x00504453};
00074 str str_type;
00075 unsigned int x;
00076 char *p;
00077
00078 if (!msg->content_type){
00079 if (parse_headers(msg, HDR_CONTENTTYPE_F, 0)<0){
00080 LOG(L_ERR,"ERR:"M_NAME":check_content_type: error parsing headers\n");
00081 return 1;
00082 }
00083 }
00084 if (!msg->content_type)
00085 {
00086 LOG(L_WARN,"WARNING: check_content_type: Content-TYPE header absent!"
00087 "let's assume the content is text/plain ;-)\n");
00088 return 1;
00089 }
00090
00091 trim_len(str_type.len,str_type.s,msg->content_type->body);
00092 p = str_type.s;
00093 advance(p,4,str_type,error_1);
00094 x = READ(p-4);
00095 if (!one_of_16(x,appl))
00096 goto other;
00097 advance(p,4,str_type,error_1);
00098 x = READ(p-4);
00099 if (!one_of_16(x,icat))
00100 goto other;
00101 advance(p,3,str_type,error_1);
00102 x = READ(p-3) & 0x00ffffff;
00103 if (!one_of_8(x,ion_))
00104 goto other;
00105
00106
00107 while (*p==' ' || *p=='\t')
00108 advance(p,1,str_type,error_1);
00109 if (*p!='/')
00110 {
00111 LOG(L_ERR, "ERROR:check_content_type: parse error:"
00112 "no / found after primary type\n");
00113 goto error;
00114 }
00115 advance(p,1,str_type,error_1);
00116 while ((*p==' ' || *p=='\t') && p+1<str_type.s+str_type.len)
00117 advance(p,1,str_type,error_1);
00118
00119 advance(p,3,str_type,error_1);
00120 x = READ(p-3) & 0x00ffffff;
00121 if (!one_of_8(x,sdp_))
00122 goto other;
00123
00124 if (*p==';'||*p==' '||*p=='\t'||*p=='\n'||*p=='\r'||*p==0) {
00125 DBG("DEBUG:check_content_type: type <%.*s> found valid\n",
00126 (int)(p-str_type.s), str_type.s);
00127 return 1;
00128 } else {
00129 LOG(L_ERR,"ERROR:check_content_type: bad end for type!\n");
00130 return -1;
00131 }
00132
00133 error_1:
00134 LOG(L_ERR,"ERROR:check_content_type: parse error: body ended :-(!\n");
00135 error:
00136 return -1;
00137 other:
00138 LOG(L_ERR,"ERROR:check_content_type: invalid type for a message\n");
00139 return -1;
00140 }
00141
00142 int extract_body(struct sip_msg *msg, str *body )
00143 {
00144
00145 body->s = get_body(msg);
00146 if (body->s==0) {
00147 LOG(L_ERR, "ERROR: extract_body: failed to get the message body\n");
00148 goto error;
00149 }
00150 body->len = msg->len -(int)(body->s-msg->buf);
00151 if (body->len==0) {
00152 LOG(L_ERR, "ERROR: extract_body: message body has length zero\n");
00153 goto error;
00154 }
00155
00156
00157
00158
00159 if (check_content_type(msg)==-1)
00160 {
00161 LOG(L_ERR,"ERROR: extract_body: content type mismatching\n");
00162 goto error;
00163 }
00164
00165
00166
00167 return 1;
00168 error:
00169 return -1;
00170 }
00171
00172
00173
00174 static int isnulladdr(str *sx, int pf)
00175 {
00176 char *cp;
00177
00178 if (pf == AF_INET6) {
00179 for(cp = sx->s; cp < sx->s + sx->len; cp++)
00180 if (*cp != '0' && *cp != ':')
00181 return 0;
00182 return 1;
00183 }
00184 return (sx->len == 7 && memcmp("0.0.0.0", sx->s, 7) == 0);
00185 }
00186
00187 static int extract_mediaport(str *body, str *mediaport)
00188 {
00189 char *cp, *cp1;
00190 int len, i;
00191 str ptype;
00192
00193 cp1 = NULL;
00194 for (cp = body->s; (len = body->s + body->len - cp) > 0;) {
00195 cp1 = ser_memmem(cp, "m=", len, 2);
00196 if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
00197 break;
00198 cp = cp1 + 2;
00199 }
00200 if (cp1 == NULL) {
00201 LOG(L_ERR, "ERROR: extract_mediaport: no `m=' in SDP\n");
00202 return -1;
00203 }
00204 mediaport->s = cp1 + 2;
00205 mediaport->len = eat_line(mediaport->s, body->s + body->len -
00206 mediaport->s) - mediaport->s;
00207 trim_len(mediaport->len, mediaport->s, *mediaport);
00208
00209
00210 cp = eat_token_end(mediaport->s, mediaport->s + mediaport->len);
00211 mediaport->len -= cp - mediaport->s;
00212 if (mediaport->len <= 0 || cp == mediaport->s) {
00213 LOG(L_ERR, "ERROR: extract_mediaport: no port in `m='\n");
00214 return -1;
00215 }
00216 mediaport->s = cp;
00217 cp = eat_space_end(mediaport->s, mediaport->s + mediaport->len);
00218 mediaport->len -= cp - mediaport->s;
00219 if (mediaport->len <= 0 || cp == mediaport->s) {
00220 LOG(L_ERR, "ERROR: extract_mediaport: no port in `m='\n");
00221 return -1;
00222 }
00223
00224 mediaport->s = cp;
00225 cp = eat_token_end(mediaport->s, mediaport->s + mediaport->len);
00226 ptype.len = mediaport->len - (cp - mediaport->s);
00227 if (ptype.len <= 0 || cp == mediaport->s) {
00228 LOG(L_ERR, "ERROR: extract_mediaport: no port in `m='\n");
00229 return -1;
00230 }
00231 ptype.s = cp;
00232 mediaport->len = cp - mediaport->s;
00233
00234 cp = eat_space_end(ptype.s, ptype.s + ptype.len);
00235 ptype.len -= cp - ptype.s;
00236 if (ptype.len <= 0 || cp == ptype.s) {
00237 LOG(L_ERR, "ERROR: extract_mediaport: no protocol type in `m='\n");
00238 return -1;
00239 }
00240
00241 ptype.s = cp;
00242 cp = eat_token_end(ptype.s, ptype.s + ptype.len);
00243 if (cp == ptype.s) {
00244 LOG(L_ERR, "ERROR: extract_mediaport: no protocol type in `m='\n");
00245 return -1;
00246 }
00247 ptype.len = cp - ptype.s;
00248
00249 for (i = 0; sup_ptypes[i].s != NULL; i++)
00250 if (ptype.len == sup_ptypes[i].len &&
00251 strncasecmp(ptype.s, sup_ptypes[i].s, ptype.len) == 0)
00252 return 0;
00253
00254 return -1;
00255 }
00256
00257
00258 static int extract_mediaip(str *body, str *mediaip, int *pf)
00259 {
00260 char *cp, *cp1;
00261 int len, nextisip;
00262
00263 cp1 = NULL;
00264 for (cp = body->s; (len = body->s + body->len - cp) > 0;) {
00265 cp1 = ser_memmem(cp, "c=", len, 2);
00266 if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
00267 break;
00268 cp = cp1 + 2;
00269 }
00270 if (cp1 == NULL) {
00271 LOG(L_ERR, "ERROR: extract_mediaip: no `c=' in SDP\n");
00272 return -1;
00273 }
00274 mediaip->s = cp1 + 2;
00275 mediaip->len = eat_line(mediaip->s, body->s + body->len - mediaip->s) - mediaip->s;
00276 trim_len(mediaip->len, mediaip->s, *mediaip);
00277
00278 nextisip = 0;
00279 for (cp = mediaip->s; cp < mediaip->s + mediaip->len;) {
00280 len = eat_token_end(cp, mediaip->s + mediaip->len) - cp;
00281 if (nextisip == 1) {
00282 mediaip->s = cp;
00283 mediaip->len = len;
00284 nextisip++;
00285 break;
00286 }
00287 if (len == 3 && memcmp(cp, "IP", 2) == 0) {
00288 switch (cp[2]) {
00289 case '4':
00290 nextisip = 1;
00291 *pf = AF_INET;
00292 break;
00293
00294 case '6':
00295 nextisip = 1;
00296 *pf = AF_INET6;
00297 break;
00298
00299 default:
00300 break;
00301 }
00302 }
00303 cp = eat_space_end(cp + len, mediaip->s + mediaip->len);
00304 }
00305 if (nextisip != 2 || mediaip->len == 0) {
00306 LOG(L_ERR, "ERROR: extract_mediaip: "
00307 "no `IP[4|6]' in `c=' field\n");
00308 return -1;
00309 }
00310 return 1;
00311 }
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 static int alter_mediaip(struct sip_msg *msg, str *body, str *oldip, int oldpf,
00335 str *newip, int newpf, int preserve)
00336 {
00337 char *buf;
00338 int offset;
00339 struct lump* anchor;
00340 str omip, nip, oip;
00341
00342
00343 if (oldpf == newpf && isnulladdr(oldip, oldpf))
00344 return 0;
00345 if (newip->len == oldip->len && memcmp(newip->s, oldip->s, newip->len) == 0)
00346 return 0;
00347
00348
00349
00350
00351
00352
00353
00354 #if 0
00355
00356
00357
00358
00359
00360
00361
00362
00363 if (msg->msg_flags & FL_SDP_IP_AFS) {
00364 LOG(L_ERR, "ERROR: alter_mediaip: you can't rewrite the same "
00365 "SDP twice, check your config!\n");
00366 return -1;
00367 }
00368 #endif
00369
00370 if (preserve != 0) {
00371 anchor = anchor_lump(msg, body->s + body->len - msg->buf , 0, 0);
00372 if (anchor == NULL)
00373 {
00374 LOG(L_ERR, "ERROR: alter_mediaip: anchor_lump failed\n");
00375 return -1;
00376 }
00377 if (oldpf == AF_INET6)
00378 {
00379 omip.s = AOLDMEDIP6 ;
00380 omip.len = AOLDMEDIP6_LEN;
00381 } else {
00382 omip.s = AOLDMEDIP;
00383 omip.len = AOLDMEDIP_LEN;
00384 }
00385 buf = pkg_malloc(omip.len + oldip->len + CRLF_LEN);
00386 if (buf == NULL)
00387 {
00388 LOG(L_ERR, "ERROR: alter_mediaip: out of memory\n");
00389 return -1;
00390 }
00391 memcpy(buf, omip.s, omip.len);
00392 memcpy(buf + omip.len, oldip->s, oldip->len);
00393 memcpy(buf + omip.len + oldip->len, CRLF, CRLF_LEN);
00394 if (insert_new_lump_after(anchor, buf,
00395 omip.len + oldip->len + CRLF_LEN, 0) == NULL) {
00396 LOG(L_ERR, "ERROR: alter_mediaip: insert_new_lump_after failed\n");
00397 pkg_free(buf);
00398 return -1;
00399 }
00400 }
00401
00402 if (oldpf == newpf) {
00403 nip.len = newip->len;
00404 nip.s = pkg_malloc(nip.len);
00405 if (nip.s == NULL) {
00406 LOG(L_ERR, "ERROR: alter_mediaip: out of memory\n");
00407 return -1;
00408 }
00409 memcpy(nip.s, newip->s, newip->len);
00410 } else {
00411 nip.len = newip->len + 2;
00412 nip.s = pkg_malloc(nip.len);
00413 if (nip.s == NULL) {
00414 LOG(L_ERR, "ERROR: alter_mediaip: out of memory\n");
00415 return -1;
00416 }
00417 memcpy(nip.s + 2, newip->s, newip->len);
00418 nip.s[0] = (newpf == AF_INET6) ? '6' : '4';
00419 nip.s[1] = ' ';
00420 }
00421
00422 oip = *oldip;
00423 if (oldpf != newpf) {
00424 do {
00425 oip.s--;
00426 oip.len++;
00427 } while (*oip.s != '6' && *oip.s != '4');
00428 }
00429 offset = oip.s - msg->buf;
00430 anchor = del_lump(msg, offset, oip.len, 0);
00431 if (anchor == NULL) {
00432 LOG(L_ERR, "ERROR: alter_mediaip: del_lump failed\n");
00433 pkg_free(nip.s);
00434 return -1;
00435 }
00436
00437 #if 0
00438 msg->msg_flags |= FL_SDP_IP_AFS;
00439 #endif
00440
00441 if (insert_new_lump_after(anchor, nip.s, nip.len, 0) == 0) {
00442 LOG(L_ERR, "ERROR: alter_mediaip: insert_new_lump_after failed\n");
00443 pkg_free(nip.s);
00444 return -1;
00445 }
00446 return 0;
00447 }
00448
00449
00450
00451
00452 static int alter_mediaport(struct sip_msg *msg, str *body, str *oldport, str *newport,
00453 int preserve)
00454 {
00455 char *buf;
00456 int offset;
00457 struct lump* anchor;
00458
00459
00460 if (newport->len == oldport->len &&
00461 memcmp(newport->s, oldport->s, newport->len) == 0)
00462 return 0;
00463
00464
00465
00466
00467
00468
00469
00470 #if 0
00471
00472
00473 if (msg->msg_flags & FL_SDP_PORT_AFS) {
00474 LOG(L_ERR, "ERROR: alter_mediaip: you can't rewrite the same "
00475 "SDP twice, check your config!\n");
00476 return -1;
00477 }
00478 #endif
00479
00480 if (preserve != 0) {
00481 anchor = anchor_lump(msg, body->s + body->len - msg->buf, 0, 0);
00482 if (anchor == NULL) {
00483 LOG(L_ERR, "ERROR: alter_mediaport: anchor_lump failed\n");
00484 return -1;
00485 }
00486 buf = pkg_malloc(AOLDMEDPRT_LEN + oldport->len + CRLF_LEN);
00487 if (buf == NULL) {
00488 LOG(L_ERR, "ERROR: alter_mediaport: out of memory\n");
00489 return -1;
00490 }
00491 memcpy(buf, AOLDMEDPRT, AOLDMEDPRT_LEN);
00492 memcpy(buf + AOLDMEDPRT_LEN, oldport->s, oldport->len);
00493 memcpy(buf + AOLDMEDPRT_LEN + oldport->len, CRLF, CRLF_LEN);
00494 if (insert_new_lump_after(anchor, buf,
00495 AOLDMEDPRT_LEN + oldport->len + CRLF_LEN, 0) == NULL) {
00496 LOG(L_ERR, "ERROR: alter_mediaport: insert_new_lump_after failed\n");
00497 pkg_free(buf);
00498 return -1;
00499 }
00500 }
00501
00502 buf = pkg_malloc(newport->len);
00503 if (buf == NULL) {
00504 LOG(L_ERR, "ERROR: alter_mediaport: out of memory\n");
00505 return -1;
00506 }
00507 offset = oldport->s - msg->buf;
00508 anchor = del_lump(msg, offset, oldport->len, 0);
00509 if (anchor == NULL) {
00510 LOG(L_ERR, "ERROR: alter_mediaport: del_lump failed\n");
00511 pkg_free(buf);
00512 return -1;
00513 }
00514 memcpy(buf, newport->s, newport->len);
00515 if (insert_new_lump_after(anchor, buf, newport->len, 0) == 0) {
00516 LOG(L_ERR, "ERROR: alter_mediaport: insert_new_lump_after failed\n");
00517 pkg_free(buf);
00518 return -1;
00519 }
00520
00521 #if 0
00522 msg->msg_flags |= FL_SDP_PORT_AFS;
00523 #endif
00524 return 0;
00525 }
00526
00527 static char * find_sdp_line(char* p, char* plimit, char linechar)
00528 {
00529 static char linehead[3] = "x=";
00530 char *cp, *cp1;
00531 linehead[0] = linechar;
00532
00533 cp = p;
00534 for (;;) {
00535 if (cp >= plimit)
00536 return NULL;
00537 cp1 = ser_memmem(cp, linehead, plimit-cp, 2);
00538 if (cp1 == NULL)
00539 return NULL;
00540
00541
00542
00543
00544 if (cp1[-1] == '\n' || cp1[-1] == '\r')
00545 return cp1;
00546
00547
00548
00549
00550
00551 if (plimit - cp1 < 2)
00552 return NULL;
00553 cp = cp1 + 2;
00554 }
00555
00556 return NULL;
00557 }
00558
00559 static char * find_next_sdp_line(char* p, char* plimit, char linechar, char* defptr)
00560 {
00561 char *t;
00562 if (p >= plimit || plimit - p < 3)
00563 return defptr;
00564 t = find_sdp_line(p + 2, plimit, linechar);
00565 return t ? t : defptr;
00566 }
00567
00568 static inline int rfc1918address(str *address)
00569 {
00570 struct in_addr inaddr;
00571 uint32_t netaddr;
00572 int i, result;
00573 char c;
00574
00575 c = address->s[address->len];
00576 address->s[address->len] = 0;
00577
00578 result = inet_aton(address->s, &inaddr);
00579
00580 address->s[address->len] = c;
00581
00582 if (result==0)
00583 return -1;
00584
00585 netaddr = ntohl(inaddr.s_addr);
00586
00587 for (i=0; nets_1918[i].cnetaddr!=NULL; i++) {
00588 if ((netaddr & nets_1918[i].mask)==nets_1918[i].netaddr) {
00589 return 1;
00590 }
00591 }
00592
00593 return 0;
00594 }
00595
00596
00597
00598
00599 static inline int get_to_tag(struct sip_msg* _m, str* _tag)
00600 {
00601 if (!_m->to) {
00602 LOG(L_ERR, "get_to_tag(): To header field missing\n");
00603 return -1;
00604 }
00605
00606 if (get_to(_m)->tag_value.len) {
00607 _tag->s = get_to(_m)->tag_value.s;
00608 _tag->len = get_to(_m)->tag_value.len;
00609 } else {
00610 _tag->s = 0;
00611 _tag->len = 0;
00612 }
00613
00614 return 0;
00615 }
00616
00617
00618
00619
00620 static inline int get_from_tag(struct sip_msg* _m, str* _tag)
00621 {
00622
00623 if (parse_from_header(_m) == -1) {
00624 LOG(L_ERR, "get_from_tag(): Error while parsing From header\n");
00625 return -1;
00626 }
00627
00628 if (get_from(_m)->tag_value.len) {
00629 _tag->s = get_from(_m)->tag_value.s;
00630 _tag->len = get_from(_m)->tag_value.len;
00631 } else {
00632 _tag->len = 0;
00633 }
00634
00635 return 0;
00636 }
00637
00638 static inline int get_callid(struct sip_msg* _m, str* _cid)
00639 {
00640
00641 if ((parse_headers(_m, HDR_CALLID_F, 0) == -1)) {
00642 LOG(L_ERR, "get_callid(): parse_headers() failed\n");
00643 return -1;
00644 }
00645
00646 if (_m->callid == NULL) {
00647 LOG(L_ERR, "get_callid(): Call-ID not found\n");
00648 return -1;
00649 }
00650
00651 _cid->s = _m->callid->body.s;
00652 _cid->len = _m->callid->body.len;
00653 trim(_cid);
00654 return 0;
00655 }
00656
00657 static char * gencookie()
00658 {
00659 static char cook[34];
00660
00661 sprintf(cook, "%d_%u ", (int)getpid(), myseqn);
00662 myseqn++;
00663 return cook;
00664 }
00665
00666 static char * send_rtpp_command(struct rtpp_node *node, struct iovec *v, int vcnt)
00667 {
00668 struct sockaddr_un addr;
00669 int fd, len, i;
00670 char *cp;
00671 static char buf[256];
00672 struct pollfd fds[1];
00673
00674 len = 0;
00675 cp = buf;
00676 if (node->rn_umode == 0) {
00677 memset(&addr, 0, sizeof(addr));
00678 addr.sun_family = AF_LOCAL;
00679 strncpy(addr.sun_path, node->rn_address,
00680 sizeof(addr.sun_path) - 1);
00681 #ifdef HAVE_SOCKADDR_SA_LEN
00682 addr.sun_len = strlen(addr.sun_path);
00683 #endif
00684
00685 fd = socket(AF_LOCAL, SOCK_STREAM, 0);
00686 if (fd < 0) {
00687 LOG(L_ERR, "ERROR: send_rtpp_command: can't create socket\n");
00688 goto badproxy;
00689 }
00690 if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
00691 close(fd);
00692 LOG(L_ERR, "ERROR: send_rtpp_command: can't connect to RTP proxy\n");
00693 goto badproxy;
00694 }
00695
00696 do {
00697 len = writev(fd, v + 1, vcnt - 1);
00698 } while (len == -1 && errno == EINTR);
00699 if (len <= 0) {
00700 close(fd);
00701 LOG(L_ERR, "ERROR: send_rtpp_command: can't send command to a RTP proxy\n");
00702 goto badproxy;
00703 }
00704 do {
00705 len = read(fd, buf, sizeof(buf) - 1);
00706 } while (len == -1 && errno == EINTR);
00707 close(fd);
00708 if (len <= 0) {
00709 LOG(L_ERR, "ERROR: send_rtpp_command: can't read reply from a RTP proxy\n");
00710 goto badproxy;
00711 }
00712 } else {
00713 fds[0].fd = node->rn_fd;
00714 fds[0].events = POLLIN;
00715 fds[0].revents = 0;
00716
00717 while ((poll(fds, 1, 0) == 1) &&
00718 ((fds[0].revents & POLLIN) != 0)) {
00719 recv(node->rn_fd, buf, sizeof(buf) - 1, 0);
00720 fds[0].revents = 0;
00721 }
00722 v[0].iov_base = gencookie();
00723 v[0].iov_len = strlen(v[0].iov_base);
00724 for (i = 0; i < rtpproxy_retr; i++) {
00725 do {
00726 len = writev(node->rn_fd, v, vcnt);
00727 } while (len == -1 && (errno == EINTR || errno == ENOBUFS));
00728 if (len <= 0) {
00729 LOG(L_ERR, "ERROR: send_rtpp_command: "
00730 "can't send command to a RTP proxy\n");
00731 goto badproxy;
00732 }
00733 while ((poll(fds, 1, rtpproxy_tout * 1000) == 1) &&
00734 (fds[0].revents & POLLIN) != 0) {
00735 do {
00736 len = recv(node->rn_fd, buf, sizeof(buf) - 1, 0);
00737 } while (len == -1 && errno == EINTR);
00738 if (len <= 0) {
00739 LOG(L_ERR, "ERROR: send_rtpp_command: "
00740 "can't read reply from a RTP proxy\n");
00741 goto badproxy;
00742 }
00743 if (len >= (v[0].iov_len - 1) &&
00744 memcmp(buf, v[0].iov_base, (v[0].iov_len - 1)) == 0) {
00745 len -= (v[0].iov_len - 1);
00746 cp += (v[0].iov_len - 1);
00747 if (len != 0) {
00748 len--;
00749 cp++;
00750 }
00751 goto out;
00752 }
00753 fds[0].revents = 0;
00754 }
00755 }
00756 if (i == rtpproxy_retr) {
00757 LOG(L_ERR, "ERROR: send_rtpp_command: "
00758 "timeout waiting reply from a RTP proxy\n");
00759 goto badproxy;
00760 }
00761 }
00762
00763 out:
00764 cp[len] = '\0';
00765 return cp;
00766 badproxy:
00767 LOG(L_ERR, "send_rtpp_command(): proxy <%s> does not responding, disable it\n", node->rn_url);
00768 node->rn_disabled = 1;
00769 node->rn_recheck_ticks = get_ticks() + rtpproxy_disable_tout;
00770 return NULL;
00771 }
00772
00773
00774 int rtpp_test(struct rtpp_node *node, int isdisabled, int force)
00775 {
00776 int rtpp_ver;
00777 char *cp;
00778 struct iovec v[2] = {{NULL, 0}, {"V", 1}};
00779 struct iovec vf[4] = {{NULL, 0}, {"VF", 2}, {" ", 1},
00780 {REQ_CPROTOVER, 8}};
00781
00782 if (force == 0) {
00783 if (isdisabled == 0)
00784 return 0;
00785 if (node->rn_recheck_ticks > get_ticks())
00786 return 1;
00787 }
00788 do {
00789 cp = send_rtpp_command(node, v, 2);
00790 if (cp == NULL) {
00791 LOG(L_WARN,"WARNING: rtpp_test: can't get version of "
00792 "the RTP proxy\n");
00793 break;
00794 }
00795 rtpp_ver = atoi(cp);
00796 if (rtpp_ver != SUP_CPROTOVER) {
00797 LOG(L_WARN, "WARNING: rtpp_test: unsupported "
00798 "version of RTP proxy <%s> found: %d supported, "
00799 "%d present\n", node->rn_url,
00800 SUP_CPROTOVER, rtpp_ver);
00801 break;
00802 }
00803 cp = send_rtpp_command(node, vf, 4);
00804 if (cp == NULL) {
00805 LOG(L_WARN,"WARNING: rtpp_test: RTP proxy went down during "
00806 "version query\n");
00807 break;
00808 }
00809 if (cp[0] == 'E' || atoi(cp) != 1) {
00810 LOG(L_WARN, "WARNING: rtpp_test: of RTP proxy <%s>"
00811 "doesn't support required protocol version %s\n",
00812 node->rn_url, REQ_CPROTOVER);
00813 break;
00814 }
00815 LOG(L_INFO, "rtpp_test: RTP proxy <%s> found, support for "
00816 "it %senabled\n",
00817 node->rn_url, force == 0 ? "re-" : "");
00818 return 0;
00819 } while(0);
00820 LOG(L_WARN, "WARNING: rtpp_test: support for RTP proxy <%s>"
00821 "has been disabled%s\n", node->rn_url,
00822 rtpproxy_disable_tout < 0 ? "" : " temporarily");
00823 if (rtpproxy_disable_tout >= 0)
00824 node->rn_recheck_ticks = get_ticks() + rtpproxy_disable_tout;
00825
00826 return 1;
00827 }
00828
00829 static struct rtpp_node * select_rtpp_node(str callid, int do_test, int node_idx)
00830 {
00831 unsigned sum, sumcut, weight_sum;
00832 struct rtpp_node* node;
00833 int was_forced;
00834
00835
00836 if (rtpp_node_count == 1) {
00837 if (node_idx > 0) {
00838 LOG(L_ERR, "ERROR: select_rtpp_node: node index out or range\n");
00839 return NULL;
00840 }
00841 node = rtpp_list.rn_first;
00842 if (node->rn_disabled && node->rn_recheck_ticks <= get_ticks()) {
00843
00844 node->rn_disabled = rtpp_test(node, 1, 0);
00845 }
00846 return node->rn_disabled ? NULL : node;
00847 }
00848
00849 if (node_idx != -1) {
00850 for (node = rtpp_list.rn_first; node != NULL; node = node->rn_next) {
00851 if (node_idx > 0) {
00852 node_idx--;
00853 continue;
00854 }
00855 if (node->rn_disabled && node->rn_recheck_ticks <= get_ticks()) {
00856
00857 node->rn_disabled = rtpp_test(node, 1, 0);
00858 }
00859 return node->rn_disabled ? NULL : node;
00860 }
00861 LOG(L_ERR, "ERROR: select_rtpp_node: node index out or range\n");
00862 return NULL;
00863 }
00864
00865
00866 for(sum = 0; callid.len > 0; callid.len--)
00867 sum += callid.s[callid.len - 1];
00868 sum &= 0xff;
00869
00870 was_forced = 0;
00871 retry:
00872 weight_sum = 0;
00873 for (node = rtpp_list.rn_first; node != NULL; node = node->rn_next) {
00874 if (node->rn_disabled && node->rn_recheck_ticks <= get_ticks()) {
00875
00876 node->rn_disabled = rtpp_test(node, 1, 0);
00877 }
00878 if (!node->rn_disabled)
00879 weight_sum += node->rn_weight;
00880 }
00881 if (weight_sum == 0) {
00882
00883 if (was_forced)
00884 return NULL;
00885 was_forced = 1;
00886 for (node = rtpp_list.rn_first; node != NULL; node = node->rn_next) {
00887 node->rn_disabled = rtpp_test(node, 1, 1);
00888 }
00889 goto retry;
00890 }
00891 sumcut = sum % weight_sum;
00892
00893
00894
00895
00896 for (node = rtpp_list.rn_first; node != NULL; node = node->rn_next) {
00897 if (node->rn_disabled)
00898 continue;
00899 if (sumcut < node->rn_weight)
00900 goto found;
00901 sumcut -= node->rn_weight;
00902 }
00903
00904 return NULL;
00905 found:
00906 if (do_test) {
00907 node->rn_disabled = rtpp_test(node, node->rn_disabled, 0);
00908 if (node->rn_disabled)
00909 goto retry;
00910 }
00911 return node;
00912 }
00913
00914
00915 static int
00916 force_rtp_proxy2_f(struct sip_msg* msg, char* str1, char* str2,int had_sdp_in_invite)
00917 {
00918 str body, body1, oldport, oldip, newport, newip;
00919 str callid, from_tag, to_tag, tmp;
00920 int create, port, len, asymmetric, flookup, argc, proxied, real;
00921 int oidx, pf=0, pf1, force, node_idx;
00922 char opts[16];
00923 char *cp, *cp1;
00924 char *cpend, *next;
00925 char **ap, *argv[10];
00926 struct lump* anchor;
00927 struct rtpp_node *node;
00928 struct iovec v[14] = {
00929 {NULL, 0},
00930 {NULL, 0},
00931 {" ", 1},
00932 {NULL, 0},
00933 {" ", 1},
00934 {NULL, 7},
00935 {" ", 1},
00936 {NULL, 1},
00937 {" ", 1},
00938 {NULL, 0},
00939 {";", 1},
00940 {NULL, 0},
00941 {" ", 1},
00942 {NULL, 0}
00943 };
00944 char *v1p, *v2p, *c1p, *c2p, *m1p, *m2p, *bodylimit;
00945 char medianum_buf[20];
00946 int medianum, media_multi;
00947 str medianum_str, tmpstr1;
00948 int c1p_altered;
00949
00950 v[1].iov_base=opts;
00951 asymmetric = flookup = force = real = 0;
00952 oidx = 1;
00953 node_idx = -1;
00954 for (cp = str1; *cp != '\0'; cp++) {
00955 switch (*cp) {
00956 case ' ':
00957 case '\t':
00958 break;
00959
00960 case 'a':
00961 case 'A':
00962 opts[oidx++] = 'A';
00963 asymmetric = 1;
00964 real = 1;
00965 break;
00966
00967 case 'i':
00968 case 'I':
00969 opts[oidx++] = 'I';
00970 break;
00971
00972 case 'e':
00973 case 'E':
00974 opts[oidx++] = 'E';
00975 break;
00976
00977 case 'l':
00978 case 'L':
00979 flookup = 1;
00980 break;
00981
00982 case 'f':
00983 case 'F':
00984 force = 1;
00985 break;
00986
00987 case 'r':
00988 case 'R':
00989 real = 1;
00990 break;
00991
00992 case 'n':
00993 case 'N':
00994 cp++;
00995 for (len = 0; isdigit(cp[len]); len++)
00996 continue;
00997 if (len == 0) {
00998 LOG(L_ERR, "ERROR: force_rtp_proxy2: non-negative integer"
00999 "should follow N option\n");
01000 return -1;
01001 }
01002 node_idx = strtoul(cp, NULL, 10);
01003 cp += len - 1;
01004 break;
01005
01006 default:
01007 LOG(L_ERR, "ERROR: force_rtp_proxy2: unknown option `%c'\n", *cp);
01008 return -1;
01009 }
01010 }
01011
01012 if (msg->first_line.type == SIP_REQUEST &&
01013 msg->first_line.u.request.method_value == METHOD_INVITE) {
01014 create = 1;
01015 } else if (msg->first_line.type == SIP_REPLY) {
01016 if (had_sdp_in_invite) create = 0;
01017 else create = 1;
01018 } else if (msg->first_line.type == SIP_REQUEST &&
01019 msg->first_line.u.request.method_value == METHOD_ACK) {
01020 create = 0;
01021 } else {
01022 return -1;
01023 }
01024
01025
01026
01027 if (extract_body(msg, &body) == -1) {
01028 LOG(L_ERR, "ERROR: force_rtp_proxy2: can't extract body "
01029 "from the message\n");
01030 return -1;
01031 }
01032 if (get_callid(msg, &callid) == -1 || callid.len == 0) {
01033 LOG(L_ERR, "ERROR: force_rtp_proxy2: can't get Call-Id field\n");
01034 return -1;
01035 }
01036 if (get_to_tag(msg, &to_tag) == -1) {
01037 LOG(L_ERR, "ERROR: force_rtp_proxy2: can't get To tag\n");
01038 return -1;
01039 }
01040 if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {
01041 LOG(L_ERR, "ERROR: force_rtp_proxy2: can't get From tag\n");
01042 return -1;
01043 }
01044 if (flookup != 0) {
01045 if (create == 0 || to_tag.len == 0)
01046 return -1;
01047 create = 0;
01048 tmp = from_tag;
01049 from_tag = to_tag;
01050 to_tag = tmp;
01051 }
01052 proxied = 0;
01053 for (cp = body.s; (len = body.s + body.len - cp) >= ANORTPPROXY_LEN;) {
01054 cp1 = ser_memmem(cp, ANORTPPROXY, len, ANORTPPROXY_LEN);
01055 if (cp1 == NULL)
01056 break;
01057 if (cp1[-1] == '\n' || cp1[-1] == '\r') {
01058 proxied = 1;
01059 break;
01060 }
01061 cp = cp1 + ANORTPPROXY_LEN;
01062 }
01063 if (proxied != 0 && force == 0)
01064 return -1;
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077 bodylimit = body.s + body.len;
01078 v1p = find_sdp_line(body.s, bodylimit, 'v');
01079 if (v1p == NULL) {
01080 LOG(L_ERR, "ERROR: force_rtp_proxy2: no sessions in SDP\n");
01081 return -1;
01082 }
01083 v2p = find_next_sdp_line(v1p, bodylimit, 'v', bodylimit);
01084 media_multi = (v2p != bodylimit);
01085 v2p = v1p;
01086 medianum = 0;
01087 for(;;) {
01088
01089 v1p = v2p;
01090 if (v1p == NULL || v1p >= bodylimit)
01091 break;
01092 v2p = find_next_sdp_line(v1p, bodylimit, 'v', bodylimit);
01093
01094 m1p = find_sdp_line(v1p, v2p, 'm');
01095
01096 if (m1p == NULL) {
01097 LOG(L_ERR, "ERROR: force_rtp_proxy2: no m= in session\n");
01098 return -1;
01099 }
01100
01101
01102
01103
01104 c1p = find_sdp_line(v1p, m1p, 'c');
01105 c1p_altered = 0;
01106
01107 m2p = m1p;
01108 for (;;) {
01109 m1p = m2p;
01110 if (m1p == NULL || m1p >= v2p)
01111 break;
01112 m2p = find_next_sdp_line(m1p, v2p, 'm', v2p);
01113
01114 c2p = find_sdp_line(m1p, m2p, 'c');
01115
01116 tmpstr1.s = c2p ? c2p : c1p;
01117 if (tmpstr1.s == NULL) {
01118
01119 LOG(L_ERR, "ERROR: force_rtp_proxy2: can't"
01120 " find media IP in the message\n");
01121 return -1;
01122 }
01123 tmpstr1.len = v2p - tmpstr1.s;
01124 if (extract_mediaip(&tmpstr1, &oldip, &pf) == -1) {
01125 LOG(L_ERR, "ERROR: force_rtp_proxy2: can't"
01126 " extract media IP from the message\n");
01127 return -1;
01128 }
01129 tmpstr1.s = m1p;
01130 tmpstr1.len = m2p - m1p;
01131 if (extract_mediaport(&tmpstr1, &oldport) == -1) {
01132 LOG(L_ERR, "ERROR: force_rtp_proxy2: can't"
01133 " extract media port from the message\n");
01134 return -1;
01135 }
01136 ++medianum;
01137 if (asymmetric != 0 || real != 0) {
01138 newip = oldip;
01139 } else {
01140 newip.s = ip_addr2a(&msg->rcv.src_ip);
01141 newip.len = strlen(newip.s);
01142 }
01143
01144 if (pf == AF_INET6) {
01145 opts[oidx] = '6';
01146 oidx++;
01147 }
01148 snprintf(medianum_buf, sizeof medianum_buf, "%d", medianum);
01149 medianum_str.s = medianum_buf;
01150 medianum_str.len = strlen(medianum_buf);
01151 opts[0] = (create == 0) ? 'L' : 'U';
01152 v[1].iov_len = oidx;
01153 STR2IOVEC(callid, v[3]);
01154 STR2IOVEC(newip, v[5]);
01155 STR2IOVEC(oldport, v[7]);
01156 STR2IOVEC(from_tag, v[9]);
01157 if (1 || media_multi)
01158 {
01159 STR2IOVEC(medianum_str, v[11]);
01160 } else {
01161 v[10].iov_len = v[11].iov_len = 0;
01162 }
01163 STR2IOVEC(to_tag, v[13]);
01164 do {
01165 node = select_rtpp_node(callid, 1, node_idx);
01166 if (!node) {
01167 LOG(L_ERR, "ERROR: force_rtp_proxy2: no available proxies\n");
01168 return -1;
01169 }
01170 cp = send_rtpp_command(node, v, (to_tag.len > 0) ? 14 : 12);
01171 } while (cp == NULL);
01172
01173 argc = 0;
01174 memset(argv, 0, sizeof(argv));
01175 cpend=cp+strlen(cp);
01176 next=eat_token_end(cp, cpend);
01177 for (ap = argv; cp<cpend; cp=next+1, next=eat_token_end(cp, cpend)){
01178 *next=0;
01179 if (*cp != '\0') {
01180 *ap=cp;
01181 argc++;
01182 if ((char*)++ap >= ((char*)argv+sizeof(argv)))
01183 break;
01184 }
01185 }
01186 if (argc < 1) {
01187 LOG(L_ERR, "force_rtp_proxy2: no reply from rtp proxy\n");
01188 return -1;
01189 }
01190 port = atoi(argv[0]);
01191 if (port <= 0 || port > 65535) {
01192 LOG(L_ERR, "force_rtp_proxy2: incorrect port in reply from rtp proxy\n");
01193 return -1;
01194 }
01195
01196 pf1 = (argc >= 3 && argv[2][0] == '6') ? AF_INET6 : AF_INET;
01197
01198 if (isnulladdr(&oldip, pf)) {
01199 if (pf1 == AF_INET6) {
01200 newip.s = "::";
01201 newip.len = 2;
01202 } else {
01203 newip.s = "0.0.0.0";
01204 newip.len = 7;
01205 }
01206 } else {
01207 newip.s = (argc < 2) ? str2 : argv[1];
01208 newip.len = strlen(newip.s);
01209 }
01210 newport.s = int2str(port, &newport.len);
01211
01212 body1.s = m1p;
01213 body1.len = bodylimit - body1.s;
01214 if (alter_mediaport(msg, &body1, &oldport, &newport, 0) == -1)
01215 return -1;
01216
01217
01218
01219
01220 if (c2p != NULL || !c1p_altered) {
01221 body1.s = c2p ? c2p : c1p;
01222 body1.len = bodylimit - body1.s;
01223 if (alter_mediaip(msg, &body1, &oldip, pf, &newip, pf1, 0) == -1)
01224 return -1;
01225 if (!c2p)
01226 c1p_altered = 1;
01227 }
01228 }
01229 }
01230
01231 if (proxied == 0) {
01232 cp = pkg_malloc(ANORTPPROXY_LEN * sizeof(char));
01233 if (cp == NULL) {
01234 LOG(L_ERR, "ERROR: force_rtp_proxy2: out of memory\n");
01235 return -1;
01236 }
01237 anchor = anchor_lump(msg, body.s + body.len - msg->buf, 0, 0);
01238 if (anchor == NULL) {
01239 LOG(L_ERR, "ERROR: force_rtp_proxy2: anchor_lump failed\n");
01240 pkg_free(cp);
01241 return -1;
01242 }
01243 memcpy(cp, ANORTPPROXY, ANORTPPROXY_LEN);
01244 if (insert_new_lump_after(anchor, cp, ANORTPPROXY_LEN, 0) == NULL) {
01245 LOG(L_ERR, "ERROR: force_rtp_proxy2: insert_new_lump_after failed\n");
01246 pkg_free(cp);
01247 return -1;
01248 }
01249 }
01250
01251 return 1;
01252 }
01253 static int unforce_rtp_proxy_f(struct sip_msg* msg, int node_idx)
01254 {
01255 str callid, from_tag, to_tag;
01256 struct rtpp_node *node;
01257 struct iovec v[1 + 4 + 3] = {{NULL, 0}, {"D", 1}, {" ", 1}, {NULL, 0}, {" ", 1}, {NULL, 0}, {" ", 1}, {NULL, 0}};
01258
01259 if (get_callid(msg, &callid) == -1 || callid.len == 0) {
01260 LOG(L_ERR, "ERROR: unforce_rtp_proxy: can't get Call-Id field\n");
01261 return -1;
01262 }
01263 if (get_to_tag(msg, &to_tag) == -1) {
01264 LOG(L_ERR, "ERROR: unforce_rtp_proxy: can't get To tag\n");
01265 return -1;
01266 }
01267 if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {
01268 LOG(L_ERR, "ERROR: unforce_rtp_proxy: can't get From tag\n");
01269 return -1;
01270 }
01271 STR2IOVEC(callid, v[3]);
01272 STR2IOVEC(from_tag, v[5]);
01273 STR2IOVEC(to_tag, v[7]);
01274 node = select_rtpp_node(callid, 1, node_idx);
01275 if (!node) {
01276 LOG(L_ERR, "ERROR: unforce_rtp_proxy: no available proxies\n");
01277 return -1;
01278 }
01279 send_rtpp_command(node, v, (to_tag.len > 0) ? 8 : 6);
01280
01281 return 1;
01282 }
01283
01284
01285