📄 sip_utils.c
字号:
if (sip->req_uri->port) { port=atoi(sip->req_uri->port); if ((port<=0) || (port>65535)) port=SIP_PORT; } else { port=SIP_PORT; } if ( (memcmp(&addr_myself, &addr_uri, sizeof(addr_myself))==0) && (port == configuration.sip_listen_port) ) { DEBUG("address match [%s]", utils_inet_ntoa(addr_uri)); found=1; break; } } DEBUGC(DBCLASS_DNS, "SIP URI is %slocal", found? "":"not "); return (found)? STS_TRUE : STS_FALSE;}/* * SIP_GEN_RESPONSE * * send an proxy generated response back to the client. * Only errors are reported from the proxy itself. * code = SIP result code to deliver * * RETURNS * STS_SUCCESS on success * STS_FAILURE on error */int sip_gen_response(sip_ticket_t *ticket, int code) { osip_message_t *response; int sts; osip_via_t *via; int port; char *buffer; size_t buflen; struct in_addr addr; /* create the response template */ if ((response=msg_make_template_reply(ticket, code))==NULL) { ERROR("sip_gen_response: error in msg_make_template_reply"); return STS_FAILURE; } /* we must check if first via has x.x.x.x address. If not, we must resolve it */ osip_message_get_via (response, 0, &via); if (via == NULL) { ERROR("sip_gen_response: Cannot send response - no via field"); osip_message_free(response); return STS_FAILURE; } /* name resolution */ if (utils_inet_aton(via->host, &addr) == 0) { /* need name resolution */ DEBUGC(DBCLASS_DNS,"resolving name:%s",via->host); sts = get_ip_by_host(via->host, &addr); if (sts == STS_FAILURE) { DEBUGC(DBCLASS_PROXY, "sip_gen_response: cannot resolve via [%s]", via->host); osip_message_free(response); return STS_FAILURE; } } sts = sip_message_to_str(response, &buffer, &buflen); if (sts != 0) { ERROR("sip_gen_response: msg_2char failed"); osip_message_free(response); return STS_FAILURE; } if (via->port) { port=atoi(via->port); if ((port<=0) || (port>65535)) port=SIP_PORT; } else { port=SIP_PORT; } /* send to destination */ sipsock_send(addr, port, ticket->protocol, buffer, buflen); /* free the resources */ osip_message_free(response); osip_free(buffer); return STS_SUCCESS;}/* * SIP_ADD_MYVIA * * interface == IF_OUTBOUND, IF_INBOUND * * RETURNS * STS_SUCCESS on success * STS_FAILURE on error */int sip_add_myvia (sip_ticket_t *ticket, int interface) { struct in_addr addr; char tmp[URL_STRING_SIZE]; osip_via_t *via; int sts; char branch_id[VIA_BRANCH_SIZE]; char *myaddr; int add_rport=0; if (get_interface_ip(interface, &addr) != STS_SUCCESS) { return STS_FAILURE; } /* evaluate if we need to include an ;rport */ /* incoming */ if ((configuration.use_rport & 1) && ((ticket->direction==REQTYP_INCOMING) || (ticket->direction==RESTYP_INCOMING)) ) { add_rport=1; } else if ((configuration.use_rport & 2) && ((ticket->direction==REQTYP_OUTGOING) || (ticket->direction==RESTYP_OUTGOING)) ) { add_rport=1; } sts = sip_calculate_branch_id(ticket, branch_id); myaddr=utils_inet_ntoa(addr); sprintf(tmp, "SIP/2.0/UDP %s:%i;branch=%s%s", myaddr, configuration.sip_listen_port, branch_id, (add_rport)? ";rport":""); DEBUGC(DBCLASS_BABBLE,"adding VIA:%s",tmp); sts = osip_via_init(&via); if (sts!=0) return STS_FAILURE; /* allocation failed */ sts = osip_via_parse(via, tmp); if (sts!=0) return STS_FAILURE; osip_list_add(ticket->sipmsg->vias,via,0); return STS_SUCCESS;}/* * SIP_DEL_MYVIA * * RETURNS * STS_SUCCESS on success * STS_FAILURE on error */int sip_del_myvia (sip_ticket_t *ticket) { osip_via_t *via; int sts; DEBUGC(DBCLASS_PROXY,"deleting topmost VIA"); via = osip_list_get (ticket->sipmsg->vias, 0); if ( via == NULL ) { ERROR("Got empty VIA list - is your UA configured properly?"); return STS_FAILURE; } if ( is_via_local(via) == STS_FALSE ) { ERROR("I'm trying to delete a VIA but it's not mine! host=%s",via->host); return STS_FAILURE; } sts = osip_list_remove(ticket->sipmsg->vias, 0); osip_via_free (via); return STS_SUCCESS;}/* * SIP_REWRITE_CONTACT * * rewrite the Contact header * * RETURNS * STS_SUCCESS on success * STS_FAILURE on error */int sip_rewrite_contact (sip_ticket_t *ticket, int direction) { osip_message_t *sip_msg=ticket->sipmsg; osip_contact_t *contact; int i, j; int replaced=0; if (sip_msg == NULL) return STS_FAILURE; /* at least one contact header present? */ osip_message_get_contact(sip_msg, 0, &contact); if (contact == NULL) return STS_FAILURE; /* loop for all existing contact headers in message */ for (j=0; contact != NULL; j++) { osip_message_get_contact(sip_msg, j, &contact); if (contact == NULL) break; if (contact->url == NULL) continue; /* search for an entry */ for (i=0;i<URLMAP_SIZE;i++){ if (urlmap[i].active == 0) continue; if ((direction == DIR_OUTGOING) && (compare_url(contact->url, urlmap[i].true_url)==STS_SUCCESS)) break; if ((direction == DIR_INCOMING) && (compare_url(contact->url, urlmap[i].masq_url)==STS_SUCCESS)) break; } /* found a mapping entry */ if (i<URLMAP_SIZE) { char *tmp; if (direction == DIR_OUTGOING) { DEBUGC(DBCLASS_PROXY, "rewriting Contact header %s@%s -> %s@%s", (contact->url->username)? contact->url->username : "*NULL*", (contact->url->host)? contact->url->host : "*NULL*", urlmap[i].masq_url->username, urlmap[i].masq_url->host); } else { DEBUGC(DBCLASS_PROXY, "rewriting Contact header %s@%s -> %s@%s", (contact->url->username)? contact->url->username : "*NULL*", (contact->url->host)? contact->url->host : "*NULL*", urlmap[i].true_url->username, urlmap[i].true_url->host); } /* remove old entry */ osip_list_remove(sip_msg->contacts,j); osip_contact_to_str(contact, &tmp); osip_contact_free(contact); /* clone the url from urlmap*/ osip_contact_init(&contact); osip_contact_parse(contact,tmp); osip_free(tmp); osip_uri_free(contact->url); if (direction == DIR_OUTGOING) { /* outgoing, use masqueraded url */ osip_uri_clone(urlmap[i].masq_url, &contact->url); } else { /* incoming, use true url */ osip_uri_clone(urlmap[i].true_url, &contact->url); } osip_list_add(sip_msg->contacts,contact,j); replaced=1; } } /* for j */ if (replaced == 0) { DEBUGC(DBCLASS_PROXY, "no Contact header rewritten!"); return STS_FAILURE; } return STS_SUCCESS;}/* * SIP_CALCULATE_BRANCH * * Calculates a branch parameter according to RFC3261 section 16.11 * * The returned 'id' will be HASHHEXLEN + strlen(magic_cookie) * characters (32 + 7) long. The caller must supply at least this * amount of space in 'id'. * * RETURNS * STS_SUCCESS on success * STS_FAILURE on error */int sip_calculate_branch_id (sip_ticket_t *ticket, char *id) {/* RFC3261 section 16.11 recommends the following procedure: * The stateless proxy MAY use any technique it likes to guarantee * uniqueness of its branch IDs across transactions. However, the * following procedure is RECOMMENDED. The proxy examines the * branch ID in the topmost Via header field of the received * request. If it begins with the magic cookie, the first * component of the branch ID of the outgoing request is computed * as a hash of the received branch ID. Otherwise, the first * component of the branch ID is computed as a hash of the topmost * Via, the tag in the To header field, the tag in the From header * field, the Call-ID header field, the CSeq number (but not * method), and the Request-URI from the received request. One of * these fields will always vary across two different * transactions. * * The branch value will consist of: * - magic cookie "z9hG4bK" * - 1st part (unique calculated ID * - 2nd part (value for loop detection) <<- not yet used by siproxd */ osip_message_t *sip_msg=ticket->sipmsg; static char *magic_cookie="z9hG4bK"; osip_via_t *via; osip_uri_param_t *param=NULL; osip_call_id_t *call_id=NULL; HASHHEX hashstring; hashstring[0]='\0'; /* * Examine topmost via and look for a magic cookie. * If it is there, I use THIS branch parameter as input for * our hash calculation */ via = osip_list_get (sip_msg->vias, 0); if (via == NULL) { ERROR("have a SIP message without any via header"); return STS_FAILURE; } param=NULL; osip_via_param_get_byname(via, "branch", ¶m); if (param && param->gvalue) { DEBUGC(DBCLASS_BABBLE, "looking for magic cookie [%s]",param->gvalue); if (strncmp(param->gvalue, magic_cookie, strlen(magic_cookie))==0) { /* calculate MD5 hash */ MD5_CTX Md5Ctx; HASH HA1; MD5Init(&Md5Ctx); MD5Update(&Md5Ctx, param->gvalue, strlen(param->gvalue)); MD5Final(HA1, &Md5Ctx); CvtHex(HA1, hashstring); DEBUGC(DBCLASS_BABBLE, "existing branch -> branch hash [%s]", hashstring); } } /* * If I don't have a branch parameter in the existing topmost via, * then I need: * - the topmost via * - the tag in the To header field * - the tag in the From header field * - the Call-ID header field * - the CSeq number (but not method) * - the Request-URI from the received request */ if (hashstring[0] == '\0') { /* calculate MD5 hash */ MD5_CTX Md5Ctx; HASH HA1; char *tmp; MD5Init(&Md5Ctx); /* topmost via */ osip_via_to_str(via, &tmp); if (tmp) { MD5Update(&Md5Ctx, tmp, strlen(tmp)); osip_free(tmp); } /* Tag in To header */ osip_to_get_tag(sip_msg->to, ¶m); if (param && param->gvalue) { MD5Update(&Md5Ctx, param->gvalue, strlen(param->gvalue)); } /* Tag in From header */ osip_from_get_tag(sip_msg->from, ¶m); if (param && param->gvalue) { MD5Update(&Md5Ctx, param->gvalue, strlen(param->gvalue)); } /* Call-ID */ call_id = osip_message_get_call_id(sip_msg); osip_call_id_to_str(call_id, &tmp); if (tmp) { MD5Update(&Md5Ctx, tmp, strlen(tmp)); osip_free(tmp); } /* CSeq number (but not method) */ tmp = osip_cseq_get_number(sip_msg->cseq); if (tmp) { MD5Update(&Md5Ctx, tmp, strlen(tmp)); } /* Request URI */ osip_uri_to_str(sip_msg->req_uri, &tmp); if (tmp) { MD5Update(&Md5Ctx, tmp, strlen(tmp)); osip_free(tmp); } MD5Final(HA1, &Md5Ctx); CvtHex(HA1, hashstring); DEBUGC(DBCLASS_BABBLE, "non-existing branch -> branch hash [%s]", hashstring); } /* include the magic cookie */ sprintf(id, "%s%s", magic_cookie, hashstring); return STS_SUCCESS;}/* * SIP_FIND_OUTBOUND_PROXY * * performs the lookup for an apropriate outbound proxy * * RETURNS * STS_SUCCESS on successful lookup * STS_FAILURE if no outbound proxy to be used */int sip_find_outbound_proxy(sip_ticket_t *ticket, struct in_addr *addr, int *port) { int i, sts; char *domain=NULL; osip_message_t *sipmsg; sipmsg=ticket->sipmsg; if (!addr ||!port) { ERROR("sip_find_outbound_proxy called with NULL addr or port"); return STS_FAILURE; } if (sipmsg && sipmsg->from && sipmsg->from->url) { domain=sipmsg->from->url->host; } if (domain == NULL) { WARN("sip_find_outbound_proxy called with NULL from->url->host"); return STS_FAILURE; } /* * check consistency of configuration: * outbound_domain_name, outbound_domain_host, outbound_domain_port * must match up
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -