#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/un.h>
#include <sys/poll.h>
#include <sys/uio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "../../timer.h"
#include "../../dprint.h"
#include "../../mem/mem.h"
#include "../../str.h"
#include "../../trim.h"
#include "../../parser/msg_parser.h"
#include "../../parser/parser_f.h"
#include "../../parser/parse_from.h"
#include "../../parser/parse_uri.h"
#include "../../parser/contact/parse_contact.h"
#include "../../data_lump.h"
#include "sdp_util.h"
#include "mod.h"
#include "nat_helper.h"
#include "sip.h"
Go to the source code of this file.
Functions | |
| int | check_content_type (struct sip_msg *msg) |
| int | extract_body (struct sip_msg *msg, str *body) |
| static int | isnulladdr (str *sx, int pf) |
| static int | extract_mediaport (str *body, str *mediaport) |
| static int | extract_mediaip (str *body, str *mediaip, int *pf) |
| static int | alter_mediaip (struct sip_msg *msg, str *body, str *oldip, int oldpf, str *newip, int newpf, int preserve) |
| static int | alter_mediaport (struct sip_msg *msg, str *body, str *oldport, str *newport, int preserve) |
| static char * | find_sdp_line (char *p, char *plimit, char linechar) |
| static char * | find_next_sdp_line (char *p, char *plimit, char linechar, char *defptr) |
| static int | rfc1918address (str *address) |
| static int | get_to_tag (struct sip_msg *_m, str *_tag) |
| static int | get_from_tag (struct sip_msg *_m, str *_tag) |
| static int | get_callid (struct sip_msg *_m, str *_cid) |
| static char * | gencookie () |
| static char * | send_rtpp_command (struct rtpp_node *node, struct iovec *v, int vcnt) |
| int | rtpp_test (struct rtpp_node *node, int isdisabled, int force) |
| static struct rtpp_node * | select_rtpp_node (str callid, int do_test, int node_idx) |
| static int | force_rtp_proxy2_f (struct sip_msg *msg, char *str1, char *str2, int had_sdp_in_invite) |
| static int | unforce_rtp_proxy_f (struct sip_msg *msg, int node_idx) |
| int | rtpproxy_init () |
| int | rtpproxy_child_init (int rank) |
| int | P_SDP_manipulate (struct sip_msg *msg, char *str1, char *str2) |
Variables | |
| int | pcscf_nat_enable |
| whether to enable NAT | |
| rtpp_head | rtpp_list |
| RTPProxy list. | |
| int | rtpp_node_count |
| RTPProxy list count. | |
| char * | rtpproxy_sock |
| int | rtpproxy_enable |
| if the RTPProxy is enabled | |
| int | rtpproxy_disable_tout |
| disabling timeout for the RTPProxy | |
| int | rtpproxy_retr |
| Retry count. | |
| int | rtpproxy_tout |
| Timeout. | |
| unsigned int | myseqn |
| static str | sup_ptypes [] |
| network_t | nets_1918 [] |
| int check_content_type | ( | struct sip_msg * | msg | ) |
Definition at line 50 of file sdp_util.c.
References advance, M_NAME, one_of_16, one_of_8, and READ.
Referenced by extract_body(), and P_SDP_manipulate().
00051 { 00052 static unsigned int appl[16] = { 00053 0x6c707061/*appl*/,0x6c707041/*Appl*/,0x6c705061/*aPpl*/, 00054 0x6c705041/*APpl*/,0x6c507061/*apPl*/,0x6c507041/*ApPl*/, 00055 0x6c505061/*aPPl*/,0x6c505041/*APPl*/,0x4c707061/*appL*/, 00056 0x4c707041/*AppL*/,0x4c705061/*aPpL*/,0x4c705041/*APpL*/, 00057 0x4c507061/*apPL*/,0x4c507041/*ApPL*/,0x4c505061/*aPPL*/, 00058 0x4c505041/*APPL*/}; 00059 static unsigned int icat[16] = { 00060 0x74616369/*icat*/,0x74616349/*Icat*/,0x74614369/*iCat*/, 00061 0x74614349/*ICat*/,0x74416369/*icAt*/,0x74416349/*IcAt*/, 00062 0x74414369/*iCAt*/,0x74414349/*ICAt*/,0x54616369/*icaT*/, 00063 0x54616349/*IcaT*/,0x54614369/*iCaT*/,0x54614349/*ICaT*/, 00064 0x54416369/*icAT*/,0x54416349/*IcAT*/,0x54414369/*iCAT*/, 00065 0x54414349/*ICAT*/}; 00066 static unsigned int ion_[8] = { 00067 0x006e6f69/*ion_*/,0x006e6f49/*Ion_*/,0x006e4f69/*iOn_*/, 00068 0x006e4f49/*IOn_*/,0x004e6f69/*ioN_*/,0x004e6f49/*IoN_*/, 00069 0x004e4f69/*iON_*/,0x004e4f49/*ION_*/}; 00070 static unsigned int sdp_[8] = { 00071 0x00706473/*sdp_*/,0x00706453/*Sdp_*/,0x00704473/*sDp_*/, 00072 0x00704453/*SDp_*/,0x00506473/*sdP_*/,0x00506453/*SdP_*/, 00073 0x00504473/*sDP_*/,0x00504453/*SDP_*/}; 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 /* skip spaces and tabs if any */ 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 }
| int extract_body | ( | struct sip_msg * | msg, | |
| str * | body | |||
| ) |
Definition at line 142 of file sdp_util.c.
References check_content_type().
Referenced by force_rtp_proxy2_f(), and P_SDP_manipulate().
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 /* no need for parse_headers(msg, EOH), get_body will 00157 * parse everything */ 00158 /*is the content type correct?*/ 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 /*DBG("DEBUG:extract_body:=|%.*s|\n",body->len,body->s);*/ 00166 00167 return 1; 00168 error: 00169 return -1; 00170 }
| static int isnulladdr | ( | str * | sx, | |
| int | pf | |||
| ) | [static] |
Definition at line 174 of file sdp_util.c.
Referenced by alter_mediaip(), and force_rtp_proxy2_f().
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 }
| static int extract_mediaport | ( | str * | body, | |
| str * | mediaport | |||
| ) | [static] |
Definition at line 187 of file sdp_util.c.
References NULL, ser_memmem(), and sup_ptypes.
Referenced by force_rtp_proxy2_f().
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; /* skip `m=' */ 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 /* Skip media supertype and spaces after it */ 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 /* Extract port */ 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 /* Skip spaces after port */ 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 /* Extract protocol type */ 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 /* Unproxyable protocol type. Generally it isn't error. */ 00254 return -1; 00255 }
| static int extract_mediaip | ( | str * | body, | |
| str * | mediaip, | |||
| int * | pf | |||
| ) | [static] |
Definition at line 258 of file sdp_util.c.
References NULL, and ser_memmem().
Referenced by force_rtp_proxy2_f().
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 }
| static int alter_mediaip | ( | struct sip_msg * | msg, | |
| str * | body, | |||
| str * | oldip, | |||
| int | oldpf, | |||
| str * | newip, | |||
| int | newpf, | |||
| int | preserve | |||
| ) | [static] |
Definition at line 334 of file sdp_util.c.
References AOLDMEDIP, AOLDMEDIP6, AOLDMEDIP6_LEN, AOLDMEDIP_LEN, isnulladdr(), and NULL.
Referenced by force_rtp_proxy2_f().
00336 { 00337 char *buf; 00338 int offset; 00339 struct lump* anchor; 00340 str omip, nip, oip; 00341 00342 /* check that updating mediaip is really necessary */ 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 * Since rewriting the same info twice will mess SDP up, 00350 * apply simple anti foot shooting measure - put flag on 00351 * messages that have been altered and check it when 00352 * another request comes. 00353 */ 00354 #if 0 00355 /* disabled: 00356 * - alter_mediaip is called twice if 2 c= lines are present 00357 * in the sdp (and we want to allow it) 00358 * - the message flags are propagated in the on_reply_route 00359 * => if we set the flags for the request they will be seen for the 00360 * reply too, but we don't want that 00361 * --andrei 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 }
| static int alter_mediaport | ( | struct sip_msg * | msg, | |
| str * | body, | |||
| str * | oldport, | |||
| str * | newport, | |||
| int | preserve | |||
| ) | [static] |
Definition at line 452 of file sdp_util.c.
References AOLDMEDPRT, AOLDMEDPRT_LEN, and NULL.
Referenced by force_rtp_proxy2_f().
00454 { 00455 char *buf; 00456 int offset; 00457 struct lump* anchor; 00458 00459 /* check that updating mediaport is really necessary */ 00460 if (newport->len == oldport->len && 00461 memcmp(newport->s, oldport->s, newport->len) == 0) 00462 return 0; 00463 00464 /* 00465 * Since rewriting the same info twice will mess SDP up, 00466 * apply simple anti foot shooting measure - put flag on 00467 * messages that have been altered and check it when 00468 * another request comes. 00469 */ 00470 #if 0 00471 /* disabled: - it propagates to the reply and we don't want this 00472 * -- andrei */ 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 }
| static char* find_sdp_line | ( | char * | p, | |
| char * | plimit, | |||
| char | linechar | |||
| ) | [static] |
Definition at line 527 of file sdp_util.c.
References NULL, and ser_memmem().
Referenced by find_next_sdp_line(), and force_rtp_proxy2_f().
00528 { 00529 static char linehead[3] = "x="; 00530 char *cp, *cp1; 00531 linehead[0] = linechar; 00532 /* Iterate thru body */ 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 * As it is body, we assume it has previous line and we can 00542 * lookup previous character. 00543 */ 00544 if (cp1[-1] == '\n' || cp1[-1] == '\r') 00545 return cp1; 00546 /* 00547 * Having such data, but not at line beginning. 00548 * Skip them and reiterate. ser_memmem() will find next 00549 * occurence. 00550 */ 00551 if (plimit - cp1 < 2) 00552 return NULL; 00553 cp = cp1 + 2; 00554 } 00555 /*UNREACHED*/ 00556 return NULL; 00557 }
| static char* find_next_sdp_line | ( | char * | p, | |
| char * | plimit, | |||
| char | linechar, | |||
| char * | defptr | |||
| ) | [static] |
Definition at line 559 of file sdp_util.c.
References find_sdp_line().
Referenced by force_rtp_proxy2_f().
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 }
| static int rfc1918address | ( | str * | address | ) | [inline, static] |
Definition at line 568 of file sdp_util.c.
References network_t::cnetaddr, nets_1918, and NULL.
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; /* invalid address to test */ 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 }
| static int get_to_tag | ( | struct sip_msg * | _m, | |
| str * | _tag | |||
| ) | [inline, static] |
Definition at line 599 of file sdp_util.c.
Referenced by force_rtp_proxy2_f(), and unforce_rtp_proxy_f().
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; /* fixes gcc 4.0 warnings */ 00611 _tag->len = 0; 00612 } 00613 00614 return 0; 00615 }
| static int get_from_tag | ( | struct sip_msg * | _m, | |
| str * | _tag | |||
| ) | [inline, static] |
Definition at line 620 of file sdp_util.c.
Referenced by force_rtp_proxy2_f(), and unforce_rtp_proxy_f().
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 }
| static int get_callid | ( | struct sip_msg * | _m, | |
| str * | _cid | |||
| ) | [inline, static] |
Definition at line 638 of file sdp_util.c.
References NULL.
Referenced by force_rtp_proxy2_f(), and unforce_rtp_proxy_f().
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 }
| static char* gencookie | ( | ) | [static] |
Definition at line 657 of file sdp_util.c.
References myseqn.
Referenced by send_rtpp_command().
00658 { 00659 static char cook[34]; 00660 00661 sprintf(cook, "%d_%u ", (int)getpid(), myseqn); 00662 myseqn++; 00663 return cook; 00664 }
| static char* send_rtpp_command | ( | struct rtpp_node * | node, | |
| struct iovec * | v, | |||
| int | vcnt | |||
| ) | [static] |
Definition at line 666 of file sdp_util.c.
References AF_LOCAL, errno, gencookie(), NULL, out, rtpp_node::rn_address, rtpp_node::rn_disabled, rtpp_node::rn_fd, rtpp_node::rn_recheck_ticks, rtpp_node::rn_umode, rtpp_node::rn_url, rtpproxy_disable_tout, rtpproxy_retr, and rtpproxy_tout.
Referenced by force_rtp_proxy2_f(), rtpp_test(), and unforce_rtp_proxy_f().
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 /* Drain input buffer */ 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 }
| int rtpp_test | ( | struct rtpp_node * | node, | |
| int | isdisabled, | |||
| int | force | |||
| ) |
Definition at line 774 of file sdp_util.c.
References NULL, REQ_CPROTOVER, rtpp_node::rn_recheck_ticks, rtpp_node::rn_url, rtpproxy_disable_tout, send_rtpp_command(), and SUP_CPROTOVER.
Referenced by rtpproxy_child_init(), and select_rtpp_node().
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 }
| static struct rtpp_node* select_rtpp_node | ( | str | callid, | |
| int | do_test, | |||
| int | node_idx | |||
| ) | [static, read] |
Definition at line 829 of file sdp_util.c.
References if, NULL, rtpp_node::rn_disabled, rtpp_head::rn_first, rtpp_node::rn_next, rtpp_node::rn_recheck_ticks, rtpp_node::rn_weight, rtpp_list, rtpp_node_count, and rtpp_test().
Referenced by force_rtp_proxy2_f(), and unforce_rtp_proxy_f().
00830 { 00831 unsigned sum, sumcut, weight_sum; 00832 struct rtpp_node* node; 00833 int was_forced; 00834 00835 /* Most popular case: 1 proxy, nothing to calculate */ 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 /* Try to enable if it's time to try. */ 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 /* Try to enable if it's time to try. */ 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 /* XXX Use quick-and-dirty hashing algo */ 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 /* Try to enable if it's time to try. */ 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 /* No proxies? Force all to be redetected, if not yet */ 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 * sumcut here lays from 0 to weight_sum-1. 00894 * Scan proxy list and decrease until appropriate proxy is found. 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 /* No node list */ 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 }
| static int force_rtp_proxy2_f | ( | struct sip_msg * | msg, | |
| char * | str1, | |||
| char * | str2, | |||
| int | had_sdp_in_invite | |||
| ) | [static] |
Definition at line 916 of file sdp_util.c.
References alter_mediaip(), alter_mediaport(), ANORTPPROXY, ANORTPPROXY_LEN, extract_body(), extract_mediaip(), extract_mediaport(), find_next_sdp_line(), find_sdp_line(), get_callid(), get_from_tag(), get_to_tag(), isnulladdr(), NULL, select_rtpp_node(), send_rtpp_command(), ser_memmem(), and STR2IOVEC.
Referenced by P_SDP_manipulate().
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}, /* command */ 00930 {NULL, 0}, /* options */ 00931 {" ", 1}, /* separator */ 00932 {NULL, 0}, /* callid */ 00933 {" ", 1}, /* separator */ 00934 {NULL, 7}, /* newip */ 00935 {" ", 1}, /* separator */ 00936 {NULL, 1}, /* oldport */ 00937 {" ", 1}, /* separator */ 00938 {NULL, 0}, /* from_tag */ 00939 {";", 1}, /* separator */ 00940 {NULL, 0}, /* medianum */ 00941 {" ", 1}, /* separator */ 00942 {NULL, 0} /* to_tag */ 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; // this was actually the first SDP, so we need to create it; 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 /* extract_body will also parse all the headers in the message as 01025 * a side effect => don't move get_callid/get_to_tag in front of it 01026