📄 sip_utils.c
字号:
*/ if ((configuration.outbound_proxy_domain_name.used != configuration.outbound_proxy_domain_host.used) || (configuration.outbound_proxy_domain_name.used != configuration.outbound_proxy_domain_port.used)) { ERROR("configuration of outbound_domain_ inconsistent, check config"); } else { /* * perform the lookup for domain specific proxies * first match wins */ for (i=0; i<configuration.outbound_proxy_domain_name.used; i++) { if (strcasecmp(configuration.outbound_proxy_domain_name.string[i], domain)==0) { sts = get_ip_by_host(configuration.outbound_proxy_domain_host.string[i], addr); if (sts == STS_FAILURE) { ERROR("sip_find_outbound_proxy: cannot resolve " "outbound proxy host [%s], check config", configuration.outbound_proxy_domain_host.string[i]); return STS_FAILURE; } *port=atoi(configuration.outbound_proxy_domain_port.string[i]); if ((*port<=0) || (*port>65535)) *port=SIP_PORT; return STS_SUCCESS; } /* strcmp */ } /* for i */ } /* * now check for a global outbound proxy */ if (configuration.outbound_proxy_host) { /* I have a global outbound proxy configured */ sts = get_ip_by_host(configuration.outbound_proxy_host, addr); if (sts == STS_FAILURE) { DEBUGC(DBCLASS_PROXY, "proxy_request: cannot resolve outbound " " proxy host [%s]", configuration.outbound_proxy_host); return STS_FAILURE; } if (configuration.outbound_proxy_port) { *port=configuration.outbound_proxy_port; } else { *port = SIP_PORT; } DEBUGC(DBCLASS_PROXY, "proxy_request: have outbound proxy %s:%i", configuration.outbound_proxy_host, *port); return STS_SUCCESS; } return STS_FAILURE; /* no proxy */}/* * SIP_IS_OUTGOING * * Figures out if this is an outgoing or incoming request/response. * The direction is stored in the ticket->direction property. * * RETURNS * STS_SUCCESS on success * STS_FAILURE if unable to determine */int sip_find_direction(sip_ticket_t *ticket, int *urlidx) { int type; int i, sts; struct sockaddr_in *from; osip_message_t *request; osip_message_t *response; struct in_addr tmp_addr; from=&ticket->from; request=ticket->sipmsg; response=ticket->sipmsg; type = 0; ticket->direction = 0; /* * did I receive the telegram from a REGISTERED host? * -> it must be an OUTGOING request */ for (i=0; i<URLMAP_SIZE; i++) { if (urlmap[i].active == 0) continue; if (get_ip_by_host(urlmap[i].true_url->host, &tmp_addr) == STS_FAILURE) { DEBUGC(DBCLASS_SIP, "sip_find_direction: cannot resolve host [%s]", urlmap[i].true_url->host); } else { DEBUGC(DBCLASS_SIP, "sip_find_direction: reghost:%s ip:%s", urlmap[i].true_url->host, utils_inet_ntoa(from->sin_addr)); if (memcmp(&tmp_addr, &from->sin_addr, sizeof(tmp_addr)) == 0) { if (MSG_IS_REQUEST(ticket->sipmsg)) { type=REQTYP_OUTGOING; } else { type=RESTYP_OUTGOING; } break; } } } /* * is the telegram directed to an internally registered host? * -> it must be an INCOMING request */ if (type == 0) { for (i=0; i<URLMAP_SIZE; i++) { if (urlmap[i].active == 0) continue; /* RFC3261: * 'To' contains a display name (Bob) and a SIP or SIPS URI * (sip:bob@biloxi.com) towards which the request was originally * directed. Display names are described in RFC 2822 [3]. */ /* So this means, that we must check the SIP URI supplied with the * INVITE method, as this points to the real wanted target. * Q: does there exist a situation where the SIP URI itself does * point to "somewhere" but the To: points to the correct UA? * So for now, we just look at both of them (SIP URI and To: header) */ if (MSG_IS_REQUEST(ticket->sipmsg)) { /* REQUEST */ /* incoming request (SIP URI == 'masq') || ((SIP URI == 'reg') && !REGISTER)*/ if ((compare_url(request->req_uri, urlmap[i].masq_url)==STS_SUCCESS) || (!MSG_IS_REGISTER(request) && (compare_url(request->req_uri, urlmap[i].reg_url)==STS_SUCCESS))) { type=REQTYP_INCOMING; break; } /* incoming request ('to' == 'masq') || (('to' == 'reg') && !REGISTER)*/ if ((compare_url(request->to->url, urlmap[i].masq_url)==STS_SUCCESS) || (!MSG_IS_REGISTER(request) && (compare_url(request->to->url, urlmap[i].reg_url)==STS_SUCCESS))) { type=REQTYP_INCOMING; break; } } else { /* RESPONSE */ /* incoming response ('from' == 'masq') || ('from' == 'reg') */ if ((compare_url(response->from->url, urlmap[i].reg_url)==STS_SUCCESS) || (compare_url(response->from->url, urlmap[i].masq_url)==STS_SUCCESS)) { type=RESTYP_INCOMING; break; } } /* is request */ } /* for i */ } /* if type == 0 */ if (MSG_IS_RESPONSE(ticket->sipmsg)) { /* &&&& Open Issue &&&& it has been seen with cross-provider calls that the FROM may be 'garbled' (e.g 1393xxx@proxy01.sipphone.com for calls made sipphone -> FWD) How can we deal with this? Should I take into consideration the 'Via' headers? This is the only clue I have, pointing to the *real* UA. Maybe I should put in a 'siproxd' ftag value to recognize it as a header inserted by myself */ if ((type == 0) && (!osip_list_eol(response->vias, 0))) { osip_via_t *via; struct in_addr addr_via, addr_myself; int port_via, port_ua; /* get the via address */ via = (osip_via_t *) osip_list_get (response->vias, 0); DEBUGC(DBCLASS_SIP, "sip_find_direction: check via [%s] for " "registered UA",via->host); sts=get_ip_by_host(via->host, &addr_via); if (sts == STS_FAILURE) { DEBUGC(DBCLASS_SIP, "sip_find_direction: cannot resolve VIA [%s]", via->host); } else { for (i=0; i<URLMAP_SIZE; i++) { if (urlmap[i].active == 0) continue; /* incoming response (1st via in list points to a registered UA) */ sts=get_ip_by_host(urlmap[i].true_url->host, &addr_myself); if (sts == STS_FAILURE) { DEBUGC(DBCLASS_SIP, "sip_find_direction: cannot resolve " "true_url [%s]", via->host); continue; } port_via=0; if (via->port) port_via=atoi(via->port); if ((port_via<=0) || (port_via>65535)) port_via=SIP_PORT; port_ua=0; if (urlmap[i].true_url->port) port_ua=atoi(urlmap[i].true_url->port); if ((port_ua<=0) || (port_ua>65535)) port_ua=SIP_PORT; DEBUGC(DBCLASS_SIP, "sip_find_direction: checking for registered " "host [%s:%i] <-> [%s:%i]", urlmap[i].true_url->host, port_ua, via->host, port_via); if ((memcmp(&addr_myself, &addr_via, sizeof(addr_myself))==0) && (port_via == port_ua)) { type=RESTYP_INCOMING; break; } } /* for i */ } } /* if type == 0 */ } /* is response */ /* * if the telegram is received from 127.0.0.1 of my inbound IP as sender, * this likely is a locally REDIRECTED/DNATed (by iptables) packet. * So it is a local UA. * Example Scenario: * Softphone(or PBX) running on the same host as siproxd is running. * Using iptables, you do a REDIRECT of outgoping SIP traffix of the * PBX to be passed to siproxd. */ sts=get_interface_ip(IF_INBOUND, &tmp_addr); if ((htonl(from->sin_addr.s_addr) == INADDR_LOOPBACK) || (from->sin_addr.s_addr == tmp_addr.s_addr)) { if (MSG_IS_REQUEST(ticket->sipmsg)) { type=REQTYP_OUTGOING; } else { type=RESTYP_OUTGOING; } } if (type == 0) { DEBUGC(DBCLASS_SIP, "sip_find_direction: unable to determine " "direction of SIP packet"); return STS_FAILURE; } ticket->direction=type; if (urlidx) *urlidx=i; return STS_SUCCESS;}/* * SIP_FIXUP_ALERT_INFO * * Asterisk Hack. * Asterisk seems to include broken Alert-Info headers (without <>) * that cause parsing to fail (libosip2). * This function does try to guess if we have such a broken SIP * message and does simply remove the offending Alert-Info header. * * RETURNS * STS_SUCCESS on success */int sip_fixup_asterisk(char *buff, int *buflen) { char *alert_info_ptr=NULL; /* * Check for Asterisk UA string * User-Agent: Asterisk PBX */ if (strstr(buff, "\r\nUser-Agent: Asterisk PBX\r\n")==NULL) return STS_SUCCESS; DEBUGC(DBCLASS_SIP, "sip_fixup_alert_info: SIP message is from Asterisk"); /* * Look form Alert-Info: header */ alert_info_ptr=strstr(buff, "\r\nAlert-Info: "); if (alert_info_ptr) { char *eol_ptr=NULL; DEBUGC(DBCLASS_SIP, "sip_fixup_alert_info: Asterisk message " "with Alert-Info found"); eol_ptr=strstr((alert_info_ptr+2), "\r\n"); if (eol_ptr) { int i; // cut the Alert-Info header from the message // (actually move the rest of the message up) DEBUGC(DBCLASS_SIP, "sip_fixup_alert_info: removed malformed " "Alert-Info header"); for (i=0; i<(*buflen - (eol_ptr - buff)); i++) { alert_info_ptr[i]=eol_ptr[i]; } /* for */ *buflen=strlen(buff); } /* if */ } return STS_SUCCESS;}/* * SIP_OBSCURE_CALLID * 27-May-2007: - new feature: "Obscure Loops" does modify the Call-IDs in outgoing requests and thus allows incoming calls forked off such an outgoing call (redirect, transfer, ...) back to the same UA where the initial call did originate. This even seems to fix some issues with Asterisks Loop detection... :-)Needs more thinking. The logic about call termination is quite tricky -calls can be terminated from either side... It is not stratigh forwardwhen and how to modify CIDs for call cancellation... * ... * * RETURNS * STS_SUCCESS on success */int sip_obscure_callid(sip_ticket_t *ticket) { static char myident[]="-siproxd"; int myidentlen=sizeof(myident)-1; /* a static strlen() of myident */ osip_message_t *sipmsg; osip_from_t *from; osip_to_t *to; osip_uri_param_t *fromtag, *totag; /* gname, gvalue */ osip_call_id_t *CID=NULL; char *tmp, *tmp2; /* feature enabled? */ if (!configuration.obscure_loops) return STS_SUCCESS; sipmsg=ticket->sipmsg; if (MSG_IS_REQUEST(sipmsg) && MSG_IS_REGISTER(sipmsg)) return STS_SUCCESS; if (MSG_IS_RESPONSE(sipmsg) && MSG_IS_RESPONSE_FOR(sipmsg,"REGISTER")) return STS_SUCCESS; from=sipmsg->from; osip_from_get_tag(from, &fromtag); to=sipmsg->to; osip_to_get_tag(to, &totag); /* at lest the From Tag must be present, otherwise out Logic does not work. Is MANDATORY according to RFC3261 */ if (!fromtag || !fromtag->gvalue || strlen(fromtag->gvalue)==0) { WARN("sip_obscure_callid: no From-Tag, not RFC3261 conform!"); return STS_FAILURE; } CID=osip_message_get_call_id(sipmsg); /* does CID->number exist? According to RFC3261, this part is mandatory */ if (!CID || !CID->number) { WARN("sip_obscure_callid: invalid Call-ID received, not RFC3261 conform!"); return STS_FAILURE; } DEBUGC(DBCLASS_PROXY, "sip_obscure_callid: current Callid#=%s Direction=%i", CID->number, ticket->direction); switch (ticket->direction) { /* Outgoing Request */ case REQTYP_OUTGOING: /* also need testing for "normal" incoming call that is present and now we SEND a cancel for this call */ tmp=strstr(CID->number, myident); if (tmp==NULL) { /* no obscuring present yet, must be a new call, modify it */ tmp=osip_malloc(strlen(CID->number) + myidentlen + strlen(fromtag->gvalue) + 1); sprintf(tmp,"%s%s%s",CID->number,myident,fromtag->gvalue); osip_free(CID->number); CID->number=tmp; } else { /* Obscuring is present, do nothing. */ } break; /* Incoming Response */ case RESTYP_INCOMING: tmp=strstr(CID->number,myident); /* modify it back if existing */ if (tmp) { /* make sure to cut only the last marker - in case of multiple siproxd instances... I dont know if this actually would work (multiple instances...)*/ for (;(tmp2=strstr(tmp+1, myident)) != NULL;) { tmp=tmp2; } tmp[0]='\0'; } break; /* Incoming Request */ case REQTYP_INCOMING: tmp=strstr(CID->number, myident); if (tmp==NULL) { /* no obscuring present yet, must be a new incoming call, do nothing */ } else { /* if BYE or CANCEL, check if obscuring present. * if From-Tag different than in CID stored, modify back CID */DEBUGC(DBCLASS_PROXY, "tmp+myidentlen=[%s], FromTag=[%s]", tmp+myidentlen, fromtag->gvalue); if (strcmp(tmp+myidentlen, fromtag->gvalue) != 0) { tmp[0]='\0'; } else { /* if From-Tag equal to in CID stored, do nothing */ } } break; /* Outgoing Response */ case RESTYP_OUTGOING: if (MSG_IS_RESPONSE_FOR(sipmsg,"BYE")) { tmp=strstr(CID->number, myident); if ((tmp==NULL)&& totag && totag->gvalue) { /* no obscuring present yet, must be a new call, modify it */ tmp=osip_malloc(strlen(CID->number) + myidentlen + strlen(fromtag->gvalue) + 1); sprintf(tmp,"%s%s%s",CID->number,myident,totag->gvalue); osip_free(CID->number); CID->number=tmp; } else { /* Obscuring is present, do nothing. */ }}// tmp=strstr(CID->number, myident);// /* modify it back if existing*/// if (tmp) {// /* make sure to cut only the last marker - in case// of multiple siproxd instances... */// for (;(tmp2=strstr(tmp+1, myident)) != NULL;) {// tmp=tmp2;// }// tmp[0]='\0';// } break; } DEBUGC(DBCLASS_PROXY, "sip_obscure_callid: new Callid#=%s",CID->number); return STS_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -