void linphone_proxy_config_register_again_with_updated_contact(LinphoneProxyConfig *obj, osip_message_t *orig_request, osip_message_t *last_answer){ osip_message_t *msg; const char *rport,*received; osip_via_t *via=NULL; osip_generic_param_t *param=NULL; osip_contact_t *ctt=NULL; osip_message_get_via(last_answer,0,&via); if (!via) return; osip_via_param_get_byname(via,"rport",¶m); if (param) rport=param->gvalue; else return; param=NULL; osip_via_param_get_byname(via,"received",¶m); if (param) received=param->gvalue; else return; osip_message_get_contact(orig_request,0,&ctt); if (strcmp(ctt->url->host,received)==0 && (ctt->url->port!=0 && strcmp(ctt->url->port,rport)==0)){ ms_message("Register has up to date contact, doing nothing."); return; } eXosip_lock(); eXosip_register_build_register(obj->rid,obj->expires,&msg); osip_message_get_contact(msg,0,&ctt); if (ctt->url->host!=NULL){ osip_free(ctt->url->host); } ctt->url->host=osip_strdup(received); if (ctt->url->port!=NULL){ osip_free(ctt->url->port); } ctt->url->port=osip_strdup(rport); eXosip_register_send_register(obj->rid,msg); eXosip_unlock(); ms_message("Resending new register with updated contact %s:%i",received,rport); }
int eXosip_update_top_via (osip_message_t * sip) { unsigned int number; char tmp[40]; osip_generic_param_t *br=NULL; osip_via_t *via = (osip_via_t *) osip_list_get (&sip->vias, 0); if (via==NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "missing via in SIP message\n")); return -1; } /* browse parameter and replace "branch" */ osip_via_param_get_byname (via, "branch", &br); if (br==NULL || br->gvalue==NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "missing branch parameter via in SIP message\n")); return -1; } osip_free(br->gvalue); number = osip_build_random_number (); sprintf (tmp, "z9hG4bK%u", number); br->gvalue = osip_strdup(tmp); return 0; }
void udp_tl_learn_port_from_via (osip_message_t * sip) { /* EXOSIP_OPT_UDP_LEARN_PORT option set */ if (eXosip.learn_port > 0) { osip_via_t *via = NULL; osip_generic_param_t *br; osip_message_get_via (sip, 0, &via); if (via != NULL && via->protocol != NULL && (osip_strcasecmp (via->protocol, "udp") == 0 || osip_strcasecmp (via->protocol, "dtls-udp") == 0)) { osip_via_param_get_byname (via, "rport", &br); if (br != NULL && br->gvalue != NULL) { struct eXosip_account_info ainfo; memset (&ainfo, 0, sizeof (struct eXosip_account_info)); snprintf (udp_firewall_port, 20, "%s", br->gvalue); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "SIP port modified from rport in SIP answer\r\n")); osip_via_param_get_byname (via, "received", &br); if (br != NULL && br->gvalue != NULL && sip->from != NULL && sip->from->url != NULL && sip->from->url->host != NULL) { snprintf (ainfo.proxy, sizeof (ainfo.proxy), "%s", sip->from->url->host); ainfo.nat_port = atoi (udp_firewall_port); snprintf (ainfo.nat_ip, sizeof (ainfo.nat_ip), "%s", br->gvalue); eXosip_set_option (EXOSIP_OPT_ADD_ACCOUNT_INFO, &ainfo); } } } } return; }
int sip_gateway_find_invite_transaction(osip_message_t* osip_msg) { osip_via_t* via = osip_list_get (&osip_msg->vias, 0); if (NULL != via) { osip_uri_param_t* branch = NULL; osip_via_param_get_byname(via, "branch", &branch); if (NULL != branch) { osip_uri_header_free(branch); } } return RC_ERR; }
/* This method just add a received parameter in the Via as requested by rfc3261 */ int osip_message_fix_last_via_header(osip_message_t * request, const char *ip_addr, int port) { osip_generic_param_t *rport; osip_via_t *via; /* get Top most Via header: */ if (request == NULL) return OSIP_BADPARAMETER; if (MSG_IS_RESPONSE(request)) return OSIP_SUCCESS; /* Don't fix Via header */ via = osip_list_get(&request->vias, 0); if (via == NULL || via->host == NULL) /* Hey, we could build it? */ return OSIP_BADPARAMETER; osip_via_param_get_byname(via, "rport", &rport); if (rport != NULL) { if (rport->gvalue == NULL) { rport->gvalue = (char *) osip_malloc(9); if (rport->gvalue == NULL) return OSIP_NOMEM; #if !defined __PALMOS__ && (defined WIN32 || defined _WIN32_WCE) _snprintf(rport->gvalue, 8, "%i", port); #else snprintf(rport->gvalue, 8, "%i", port); #endif } /* else bug? */ } /* only add the received parameter if the 'sent-by' value does not contains this ip address */ if (0 == strcmp(via->host, ip_addr)) /* don't need the received parameter */ return OSIP_SUCCESS; osip_via_set_received(via, osip_strdup(ip_addr)); return OSIP_SUCCESS; }
void udp_tl_learn_port_from_via(CSipMessage* sip) { /* EXOSIP_OPT_UDP_LEARN_PORT option set */ CVia* via = NULL; CUrlParam* br; sip->GetVia(0,&via); if (via != NULL && via->m_pcProtocol != NULL && (zstr_strcasecmp(via->m_pcProtocol, "udp") == 0 || zstr_strcasecmp(via->m_pcProtocol, "dtls-udp") == 0)) { osip_via_param_get_byname(via, "rport", &br); if (br != NULL && br->gvalue != NULL) { //_snprintf(udp_firewall_port, 20, "%s", br->gvalue); } } return; }
void nist_snd_23456xx (osip_transaction_t * nist, osip_event_t * evt) { int i; osip_via_t *via; osip_t *osip = (osip_t *) nist->config; if (nist->last_response != NULL) { osip_message_free (nist->last_response); } nist->last_response = evt->sip; via = (osip_via_t *) osip_list_get (nist->last_response->vias, 0); if (via) { char *host; int port; osip_generic_param_t *maddr; osip_generic_param_t *received; osip_generic_param_t *rport; osip_via_param_get_byname (via, "maddr", &maddr); osip_via_param_get_byname (via, "received", &received); osip_via_param_get_byname (via, "rport", &rport); /* 1: user should not use the provided information (host and port) if they are using a reliable transport. Instead, they should use the already open socket attached to this transaction. */ /* 2: check maddr and multicast usage */ if (maddr != NULL) host = maddr->gvalue; /* we should check if this is a multicast address and use set the "ttl" in this case. (this must be done in the UDP message (not at the SIP layer) */ else if (received != NULL) host = received->gvalue; else host = via->host; if (rport == NULL || rport->gvalue == NULL) { if (via->port != NULL) port = osip_atoi (via->port); else port = 5060; } else port = osip_atoi (rport->gvalue); i = osip->cb_send_message (nist, nist->last_response, host, port, nist->out_socket); } else i = -1; if (i != 0) { nist_handle_transport_error (nist, i); return; } else { if (EVT_IS_SND_STATUS_2XX (evt)) __osip_message_callback (OSIP_NIST_STATUS_2XX_SENT, nist, nist->last_response); else if (MSG_IS_STATUS_3XX (nist->last_response)) __osip_message_callback (OSIP_NIST_STATUS_3XX_SENT, nist, nist->last_response); else if (MSG_IS_STATUS_4XX (nist->last_response)) __osip_message_callback (OSIP_NIST_STATUS_4XX_SENT, nist, nist->last_response); else if (MSG_IS_STATUS_5XX (nist->last_response)) __osip_message_callback (OSIP_NIST_STATUS_5XX_SENT, nist, nist->last_response); else __osip_message_callback (OSIP_NIST_STATUS_6XX_SENT, nist, nist->last_response); } if (nist->state != NIST_COMPLETED) /* start J timer */ nist->nist_context->timer_j_start = time (NULL); __osip_transaction_set_state (nist, NIST_COMPLETED); }
void nist_rcv_request (osip_transaction_t * nist, osip_event_t * evt) { int i; osip_t *osip = (osip_t *) nist->config; if (nist->state == NIST_PRE_TRYING) /* announce new REQUEST */ { /* Here we have ist->orig_request == NULL */ nist->orig_request = evt->sip; if (MSG_IS_REGISTER (evt->sip)) __osip_message_callback (OSIP_NIST_REGISTER_RECEIVED, nist, nist->orig_request); else if (MSG_IS_BYE (evt->sip)) __osip_message_callback (OSIP_NIST_BYE_RECEIVED, nist, nist->orig_request); else if (MSG_IS_OPTIONS (evt->sip)) __osip_message_callback (OSIP_NIST_OPTIONS_RECEIVED, nist, nist->orig_request); else if (MSG_IS_INFO (evt->sip)) __osip_message_callback (OSIP_NIST_INFO_RECEIVED, nist, nist->orig_request); else if (MSG_IS_CANCEL (evt->sip)) __osip_message_callback (OSIP_NIST_CANCEL_RECEIVED, nist, nist->orig_request); else if (MSG_IS_NOTIFY (evt->sip)) __osip_message_callback (OSIP_NIST_NOTIFY_RECEIVED, nist, nist->orig_request); else if (MSG_IS_SUBSCRIBE (evt->sip)) __osip_message_callback (OSIP_NIST_SUBSCRIBE_RECEIVED, nist, nist->orig_request); else __osip_message_callback (OSIP_NIST_UNKNOWN_REQUEST_RECEIVED, nist, nist->orig_request); } else /* NIST_PROCEEDING or NIST_COMPLETED */ { /* delete retransmission */ osip_message_free (evt->sip); __osip_message_callback (OSIP_NIST_REQUEST_RECEIVED_AGAIN, nist, nist->orig_request); if (nist->last_response != NULL) /* retransmit last response */ { osip_via_t *via; via = (osip_via_t *) osip_list_get (nist->last_response->vias, 0); if (via) { char *host; int port; osip_generic_param_t *maddr; osip_generic_param_t *received; osip_generic_param_t *rport; osip_via_param_get_byname (via, "maddr", &maddr); osip_via_param_get_byname (via, "received", &received); osip_via_param_get_byname (via, "rport", &rport); /* 1: user should not use the provided information (host and port) if they are using a reliable transport. Instead, they should use the already open socket attached to this transaction. */ /* 2: check maddr and multicast usage */ if (maddr != NULL) host = maddr->gvalue; /* we should check if this is a multicast address and use set the "ttl" in this case. (this must be done in the UDP message (not at the SIP layer) */ else if (received != NULL) host = received->gvalue; else host = via->host; if (rport == NULL || rport->gvalue == NULL) { if (via->port != NULL) port = osip_atoi (via->port); else port = 5060; } else port = osip_atoi (rport->gvalue); i = osip->cb_send_message (nist, nist->last_response, host, port, nist->out_socket); } else i = -1; if (i != 0) { nist_handle_transport_error (nist, i); return; } else { if (MSG_IS_STATUS_1XX (nist->last_response)) __osip_message_callback (OSIP_NIST_STATUS_1XX_SENT, nist, nist->last_response); else if (MSG_IS_STATUS_2XX (nist->last_response)) __osip_message_callback (OSIP_NIST_STATUS_2XX_SENT_AGAIN, nist, nist->last_response); else __osip_message_callback (OSIP_NIST_STATUS_3456XX_SENT_AGAIN, nist, nist->last_response); return; } } /* we are already in the proper state */ return; } /* we come here only if it was the first REQUEST received */ __osip_transaction_set_state (nist, NIST_TRYING); }
/* * 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; }
int _eXosip_srv_lookup(osip_transaction_t * tr, osip_message_t * sip, struct osip_srv_record *record) { int use_srv = 1; int port; char *host; osip_via_t *via; via = (osip_via_t *) osip_list_get(&sip->vias, 0); if (via == NULL || via->protocol == NULL) return OSIP_BADPARAMETER; if (MSG_IS_REQUEST(sip)) { osip_route_t *route; osip_message_get_route(sip, 0, &route); if (route != NULL) { osip_uri_param_t *lr_param = NULL; osip_uri_uparam_get_byname(route->url, "lr", &lr_param); if (lr_param == NULL) route = NULL; } if (route != NULL) { port = 5060; if (route->url->port != NULL) { port = osip_atoi(route->url->port); use_srv = 0; } host = route->url->host; } else { /* search for maddr parameter */ osip_uri_param_t *maddr_param = NULL; osip_uri_uparam_get_byname(sip->req_uri, "maddr", &maddr_param); host = NULL; if (maddr_param != NULL && maddr_param->gvalue != NULL) host = maddr_param->gvalue; port = 5060; if (sip->req_uri->port != NULL) { use_srv = 0; port = osip_atoi(sip->req_uri->port); } if (host == NULL) host = sip->req_uri->host; } } else { osip_generic_param_t *maddr; osip_generic_param_t *received; osip_generic_param_t *rport; osip_via_param_get_byname(via, "maddr", &maddr); osip_via_param_get_byname(via, "received", &received); osip_via_param_get_byname(via, "rport", &rport); if (maddr != NULL) host = maddr->gvalue; else if (received != NULL) host = received->gvalue; else host = via->host; if (via->port == NULL) use_srv = 0; if (rport == NULL || rport->gvalue == NULL) { if (via->port != NULL) port = osip_atoi(via->port); else port = 5060; } else port = osip_atoi(rport->gvalue); } if (host == NULL) { return OSIP_UNKNOWN_HOST; } /* check if we have an IPv4 or IPv6 address */ if (strchr(host, ':') || (INADDR_NONE != inet_addr(host))) { return OSIP_UNKNOWN_HOST; } if (use_srv == 1) { int i; i = eXosip_get_srv_record(record, host, via->protocol); return i; } return OSIP_SUCCESS; }