⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sip_utils.c

📁 sip proxy
💻 C
📖 第 1 页 / 共 3 页
字号:
      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", &param);   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, &param);      if (param && param->gvalue) {         MD5Update(&Md5Ctx, param->gvalue, strlen(param->gvalue));      }      /* Tag in From header */      osip_from_get_tag(sip_msg->from, &param);      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 + -