Exemplo n.º 1
0
static int
ac_packetfilter_trust(ac_sip_t *asip, void *data)
{
	osip_message_t* sip = asip->req->evt->sip;

	LOG_DEBUG("Performing trust ac on %s->%s\n", asip->from, asip->to);

	/* filter only inbound, non-response sessions */
	if (asip->req->remote_msg && 
	    !MSG_IS_RESPONSE(sip) && 
	    (MSG_IS_INVITE(sip) || MSG_IS_MESSAGE(sip)) &&
	    asip->verdict == AC_VERDICT_NONE) {

		/* check max path */
		if (max_path > 0) {
			int pathlen = -1;

			/* the default unless proven otherwise.. */
			asip->verdict = AC_VERDICT_REJECT;
			pathlen = trustman_get_pathlen(asip->from, asip->to);
			
			LOG_DEBUG("Will check params, trust path data: %d, limit: %d\n", pathlen, max_path);
			if ((pathlen > -1) && (pathlen <= max_path)) {
				asip->verdict = AC_VERDICT_NONE;
			} else {
				LOG_DEBUG("No trust parameters got, skipping as we require max %d\n", max_path);
			}
		}
	}
	
	return 1;
}
Exemplo n.º 2
0
static int
ac_packetfilter_simple(ac_sip_t *asip, void *data)
{
	osip_message_t* sip = asip->req->evt->sip;
	int code = osip_message_get_status_code(sip);

	LOG_DEBUG("Performing simple ac on %s->%s, remote: %d\n", asip->from, asip->to, asip->req->remote_msg);
	/* filter only inbound */
	if (asip->req->remote_msg && !asip->req->internally_generated) {
		
		/* todo: we should check that the sip from == the aor
		   associated with the connection (on remote calls) */

		/* except that that would mess up the gateway things. */

		//ASSERT_ZERO(sipp_get_sip_aors_simple(sip, &local_aor, &remote_aor, 1), end);
		/*
		if ((!MSG_IS_RESPONSE(asip->evt->sip) &&
		     (strcmp(asip->from, asip->remote) || strcmp(asip->to, asip->local))) ||
		    (MSG_IS_RESPONSE(asip->evt->sip) &&
		     (strcmp(asip->to, asip->remote) || strcmp(asip->from, asip->local))))
			asip->verdict = AC_VERDICT_REJECT;
		else 
		*/
		if (MSG_IS_RESPONSE(sip)) {

			/* reject 482 merges, as server loops aren't of any interest to us */
			if (code == 482) {
				LOG_WARN("Skipping %d response\n", code);
				asip->verdict = AC_VERDICT_REJECT;
			}
		} else if (MSG_IS_ACK(sip) || MSG_IS_BYE(sip) || MSG_IS_CANCEL(sip) || MSG_IS_UPDATE(sip)) {
			
			/* this we should let through pretty much undisturbed */
		
		} else if (MSG_IS_SUBSCRIBE(sip) || MSG_IS_PUBLISH(sip)) {

			/* if this is remotely got, just reject */
			asip->verdict = AC_VERDICT_REJECT;

		} else if (MSG_IS_INVITE(sip) || MSG_IS_MESSAGE(sip)) {
			/* hm, nothing.. */
			// } else if (MSG_IS_NOTIFY(sip)) {
			
		} else {
			/* todo: what about OPTIONS? */
			LOG_WARN("Got unsupported request\n");
			asip->verdict = AC_VERDICT_UNSUPP;
		}
	} else {
		/* allow *all* outgoing! */
		asip->verdict = AC_VERDICT_ALLOW;
	}

	return 1;
}
Exemplo n.º 3
0
static int
ac_packetfilter_op(ac_sip_t *asip, void *data)
{
	osip_message_t* sip = asip->evt->sip;

	LOG_DEBUG("Performing op ac on %s->%s\n", asip->from, asip->to);

	/* filter only inbound, non-response sessions */
	if (asip->remotely_got && 
	    !MSG_IS_RESPONSE(sip) && 
	    (MSG_IS_INVITE(sip) || MSG_IS_MESSAGE(sip)) &&
	    asip->verdict == AC_VERDICT_NONE) {
		int is_known = 0;
		char* key = 0;
		reg_package_t *reg = 0;

		/* check identity key */
		if ((reg = ident_find_foreign_reg(asip->from))) {
			key = ident_data_get_pkey_base64(reg->cert);
			if (key) 
				opconn_known(key, &is_known);
			if (is_known)
				LOG_DEBUG("we know the user's key\n");
			freez(key);
			ship_unlock(reg);
		}

		/* check trustman info */
		if (!is_known) {
			key = trustman_op_get_verification_key(asip->from, asip->to);
			if (key)
				opconn_known(key, &is_known);
			if (is_known)
				LOG_DEBUG("we know the verificator of the user's key\n");
			freez(key);
		}
		
		switch (op_filtering) {
		case 0:
			/* block unknown */
			if (!is_known) //is_unknown)
				asip->verdict = AC_VERDICT_REJECT;
			break;
		case 2:
			/* allow known */
			if (is_known)
				asip->verdict = AC_VERDICT_ALLOW;
			break;
		default:
			/* nothing / unknkown */
			break;
		}
	}

	return 1;
}
Exemplo n.º 4
0
type_t
evt_set_type_incoming_sipmessage (osip_message_t * sip)
{
  if (MSG_IS_REQUEST (sip))
    {
      if (MSG_IS_INVITE (sip))
	return RCV_REQINVITE;
      else if (MSG_IS_ACK (sip))
	return RCV_REQACK;
      return RCV_REQUEST;
    }
  else
    {
      if (MSG_IS_STATUS_1XX (sip))
	return RCV_STATUS_1XX;
      else if (MSG_IS_STATUS_2XX (sip))
	return RCV_STATUS_2XX;
      return RCV_STATUS_3456XX;
    }
}
Exemplo n.º 5
0
static int
_eXosip_retry_with_auth (eXosip_dialog_t * jd, osip_transaction_t ** ptr,
                         int *retry)
{
  osip_transaction_t *out_tr = NULL;
  osip_transaction_t *tr = NULL;
  osip_message_t *msg = NULL;
  osip_event_t *sipevent;
  jinfo_t *ji = NULL;

  int cseq;
  osip_via_t *via;
  int i;

  if (!ptr)
    return -1;

  if (jd != NULL)
    {
      if (jd->d_out_trs == NULL)
        return -1;
    }

  out_tr = *ptr;

  if (out_tr == NULL
      || out_tr->orig_request == NULL || out_tr->last_response == NULL)
    return -1;

  if (retry && (*retry >= 3))
    return -1;

  osip_message_clone (out_tr->orig_request, &msg);
  if (msg == NULL)
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: could not clone msg for authentication\n"));
      return -1;
    }

  via = (osip_via_t *) osip_list_get (&msg->vias, 0);
  if (via == NULL || msg->cseq == NULL || msg->cseq->number == NULL)
    {
      osip_message_free (msg);
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: missing via or cseq header\n"));
      return -1;
    }

  /* increment cseq */
  cseq = atoi (msg->cseq->number);
  osip_free (msg->cseq->number);
  msg->cseq->number = strdup_printf ("%i", cseq + 1);
  if (jd != NULL && jd->d_dialog != NULL)
    {
      jd->d_dialog->local_cseq++;
    }

  i = eXosip_update_top_via(msg);
  if (i!=0)
    {
      osip_message_free (msg);
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: unsupported protocol\n"));
      return -1;
    }

  if (eXosip_add_authentication_information (msg, out_tr->last_response) < 0)
    {
      osip_message_free (msg);
      return -1;
    }

  osip_message_force_update (msg);

  if (MSG_IS_INVITE (msg))
    i = _eXosip_transaction_init (&tr, ICT, eXosip.j_osip, msg);
  else
    i = _eXosip_transaction_init (&tr, NICT, eXosip.j_osip, msg);

  if (i != 0)
    {
      osip_message_free (msg);
      return -1;
    }

  /* replace with the new tr */
  if (MSG_IS_PUBLISH(msg))
    {
      /* old transaction is put in the garbage list */
      osip_list_add (eXosip.j_transactions, out_tr, 0);
      /* new transaction is put in the publish context */
      *ptr = tr;
    }
  else
    osip_list_add (eXosip.j_transactions, tr, 0);

  sipevent = osip_new_outgoing_sipmessage (msg);

  ji = osip_transaction_get_your_instance (out_tr);

  osip_transaction_set_your_instance (out_tr, NULL);
  osip_transaction_set_your_instance (tr, ji);
  osip_transaction_add_event (tr, sipevent);

  if (retry)
    (*retry)++;

  eXosip_update ();             /* fixed? */
  __eXosip_wakeup ();
  return 0;
}
Exemplo n.º 6
0
Arquivo: proxy.c Projeto: OPSF/uClinux
/*
 * PROXY_REQUEST
 *
 * RETURNS
 *	STS_SUCCESS on success
 *	STS_FAILURE on error
 *
 * RFC3261
 *    Section 16.3: Proxy Behavior - Request Validation
 *    1. Reasonable Syntax
 *    2. URI scheme
 *    3. Max-Forwards
 *    4. (Optional) Loop Detection
 *    5. Proxy-Require
 *    6. Proxy-Authorization
 *
 *    Section 16.6: Proxy Behavior - Request Forwarding
 *    1.  Make a copy of the received request
 *    2.  Update the Request-URI
 *    3.  Update the Max-Forwards header field
 *    4.  Optionally add a Record-route header field value
 *    5.  Optionally add additional header fields
 *    6.  Postprocess routing information
 *    7.  Determine the next-hop address, port, and transport
 *    8.  Add a Via header field value
 *    9.  Add a Content-Length header field if necessary
 *    10. Forward the new request
 *    11. Set timer C
 */
int proxy_request (sip_ticket_t *ticket) {
   int i;
   int sts;
   int type;
   struct in_addr sendto_addr;
   osip_uri_t *url;
   int port;
   char *buffer;
   int buflen;
   osip_message_t *request;
   struct sockaddr_in *from;

   DEBUGC(DBCLASS_PROXY,"proxy_request");

   if (ticket==NULL) {
      ERROR("proxy_request: called with NULL ticket");
      return STS_FAILURE;
   }

   request=ticket->sipmsg;
   from=&ticket->from;

   /*
    * RFC 3261, Section 16.4
    * Proxy Behavior - Route Information Preprocessing
    * (process Route header)
    */
   route_preprocess(ticket);

   /*
    * figure out whether this is an incoming or outgoing request
    * by doing a lookup in the registration table.
    */
#define _OLD_DIRECTION_EVALUATION 0
#if _OLD_DIRECTION_EVALUATION
   type = 0;
   for (i=0; i<URLMAP_SIZE; i++) {
      if (urlmap[i].active == 0) continue;

      /* 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;
         DEBUGC(DBCLASS_PROXY,"incoming request from %s@%s from outbound",
	   request->from->url->username? request->from->url->username:"******",
           request->from->url->host? request->from->url->host: "*NULL*");
	 break;
      }

      /* outgoing request ('from' == 'reg') */
      if (compare_url(request->from->url, urlmap[i].reg_url)==STS_SUCCESS) {
         type=REQTYP_OUTGOING;
         DEBUGC(DBCLASS_PROXY,"outgoing request from %s@%s from inbound",
	   request->from->url->username? request->from->url->username:"******",
           request->from->url->host? request->from->url->host: "*NULL*");
	 break;
      }
   }
#else
   type = 0;
   /*
    * did I receive the telegram from a REGISTERED host?
    * -> it must be an OUTGOING request
    */
   for (i=0; i<URLMAP_SIZE; i++) {
      struct in_addr tmp_addr;

      if (urlmap[i].active == 0) continue;
      if (get_ip_by_host(urlmap[i].true_url->host, &tmp_addr) == STS_FAILURE) {
         DEBUGC(DBCLASS_PROXY, "proxy_request: cannot resolve host [%s]",
             urlmap[i].true_url);
      } else {
         DEBUGC(DBCLASS_PROXY, "proxy_request: 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) {
            type=REQTYP_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:[email protected]) 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)
          */

         /* 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;
         }
      }
   }
#endif
   ticket->direction=type;

   /*
    * logging of passing calls
    */
   if (configuration.log_calls) {
      osip_uri_t *cont_url = NULL;
      if (!osip_list_eol(request->contacts, 0))
         cont_url = ((osip_contact_t*)(request->contacts->node->element))->url;
      
      /* INVITE */
      if (MSG_IS_INVITE(request)) {
         if (cont_url) {
            INFO("%s Call from: %s@%s",
                 (type==REQTYP_INCOMING) ? "Incoming":"Outgoing",
                 cont_url->username ? cont_url->username:"******",
                 cont_url->host ? cont_url->host : "*NULL*");
         } else {
            INFO("%s Call (w/o contact header) from: %s@%s",
                 (type==REQTYP_INCOMING) ? "Incoming":"Outgoing",
	         request->from->url->username ? 
                    request->from->url->username:"******",
	         request->from->url->host ? 
                    request->from->url->host : "*NULL*");
         }
      /* BYE / CANCEL */
      } else if (MSG_IS_BYE(request) || MSG_IS_CANCEL(request)) {
         if (cont_url) {
            INFO("Ending Call from: %s@%s",
                 cont_url->username ? cont_url->username:"******",
                 cont_url->host ? cont_url->host : "*NULL*");
         } else {
            INFO("Ending Call (w/o contact header) from: %s@%s",
	         request->from->url->username ? 
                    request->from->url->username:"******",
	         request->from->url->host ? 
                    request->from->url->host : "*NULL*");
         }
      }
   } /* log_calls */


   /*
    * RFC 3261, Section 16.6 step 1
    * Proxy Behavior - Request Forwarding - Make a copy
    */
   /* nothing to do here, copy is ready in 'request'*/

   /* get destination address */
   url=osip_message_get_uri(request);

   switch (type) {
  /*
   * from an external host to the internal masqueraded host
   */
   case REQTYP_INCOMING:
      DEBUGC(DBCLASS_PROXY,"incoming request from %s@%s from outbound",
	request->from->url->username? request->from->url->username:"******",
        request->from->url->host? request->from->url->host: "*NULL*");

      /*
       * RFC 3261, Section 16.6 step 2
       * Proxy Behavior - Request Forwarding - Request-URI
       * (rewrite request URI to point to the real host)
       */
      /* 'i' still holds the valid index into the URLMAP table */
      if (check_rewrite_rq_uri(request) == STS_TRUE) {
         proxy_rewrite_request_uri(request, i);
      }

      /* if this is CANCEL/BYE request, stop RTP proxying */
      if (MSG_IS_BYE(request) || MSG_IS_CANCEL(request)) {
         /* stop the RTP proxying stream(s) */
         rtp_stop_fwd(osip_message_get_call_id(request), DIR_INCOMING);
         rtp_stop_fwd(osip_message_get_call_id(request), DIR_OUTGOING);

      /* check for incoming request */
      } else if (MSG_IS_INVITE(request)) {
         /* Rewrite the body */
         sts = proxy_rewrite_invitation_body(request, DIR_INCOMING);

      } else if (MSG_IS_ACK(request)) {
         /* Rewrite the body */
         sts = proxy_rewrite_invitation_body(request, DIR_INCOMING);

      }
      break;
   
  /*
   * from the internal masqueraded host to an external host
   */
   case REQTYP_OUTGOING:
      DEBUGC(DBCLASS_PROXY,"outgoing request from %s@%s from inbound",
	request->from->url->username? request->from->url->username:"******",
        request->from->url->host? request->from->url->host: "*NULL*");

      /*
       * RFC 3261, Section 16.6 step 2
       * Proxy Behavior - Request Forwarding - Request-URI
       */
      /* nothing to do for an outgoing request */


      /* if it is addressed to myself, then it must be some request
       * method that I as a proxy do not support. Reject */
#if 0
/* careful - an internal UA might send an request to another internal UA.
   This would be caught here, so don't do this. This situation should be
   caught in the default part of the CASE statement below */
      if (is_sipuri_local(ticket) == STS_TRUE) {
         WARN("unsupported request [%s] directed to proxy from %s@%s -> %s@%s",
	    request->sip_method? request->sip_method:"*NULL*",
	    request->from->url->username? request->from->url->username:"******",
	    request->from->url->host? request->from->url->host : "*NULL*",
	    url->username? url->username : "******",
	    url->host? url->host : "*NULL*");

         sip_gen_response(ticket, 403 /*forbidden*/);

         return STS_FAILURE;
      }
#endif

      /* rewrite Contact header to represent the masqued address */
      sip_rewrite_contact(ticket, DIR_OUTGOING);

      /* if an INVITE, rewrite body */
      if (MSG_IS_INVITE(request)) {
         sts = proxy_rewrite_invitation_body(request, DIR_OUTGOING);
      } else if (MSG_IS_ACK(request)) {
         sts = proxy_rewrite_invitation_body(request, DIR_OUTGOING);
      }

      /* if this is CANCEL/BYE request, stop RTP proxying */
      if (MSG_IS_BYE(request) || MSG_IS_CANCEL(request)) {
         /* stop the RTP proxying stream(s) */
         rtp_stop_fwd(osip_message_get_call_id(request), DIR_INCOMING);
         rtp_stop_fwd(osip_message_get_call_id(request), DIR_OUTGOING);
      }

      break;
   
   default:
      DEBUGC(DBCLASS_PROXY, "request [%s] from/to unregistered UA "
           "(RQ: %s@%s -> %s@%s)",
           request->sip_method? request->sip_method:"*NULL*",
	   request->from->url->username? request->from->url->username:"******",
	   request->from->url->host? request->from->url->host : "*NULL*",
	   url->username? url->username : "******",
	   url->host? url->host : "*NULL*");

/*
 * we may end up here for two reasons:
 *  1) An incomming request (from outbound) that is directed to
 *     an unknown (not registered) local UA
 *  2) an outgoing request from a local UA that is not registered.
 *
 * Case 1) we should probably answer with "404 Not Found",
 * case 2) more likely a "403 Forbidden"
 * 
 * How about "408 Request Timeout" ?
 *
 */
      sip_gen_response(ticket, 408 /* Request Timeout */);

      return STS_FAILURE;
   }


   /*
    * RFC 3261, Section 16.6 step 3
    * Proxy Behavior - Request Forwarding - Max-Forwards
    * (if Max-Forwards header exists, decrement by one, if it does not
    * exist, add a new one with value SHOULD be 70)
    */
   {
   osip_header_t *max_forwards;
   int forwards_count = DEFAULT_MAXFWD;
   char mfwd[8];

   osip_message_get_max_forwards(request, 0, &max_forwards);
   if (max_forwards == NULL) {
      sprintf(mfwd, "%i", forwards_count);
      osip_message_set_max_forwards(request, mfwd);
   } else {
      if (max_forwards->hvalue) {
         forwards_count = atoi(max_forwards->hvalue);
         forwards_count -=1;
         osip_free (max_forwards->hvalue);
      }

      sprintf(mfwd, "%i", forwards_count);
      max_forwards->hvalue = osip_strdup(mfwd);
   }

   DEBUGC(DBCLASS_PROXY,"setting Max-Forwards=%s",mfwd);
   }

   /*
    * RFC 3261, Section 16.6 step 4
    * Proxy Behavior - Request Forwarding - Add a Record-route header
    */

   /*
    * for ALL incoming requests, include my Record-Route header.
    * The local UA will probably send its answer to the topmost 
    * Route Header (8.1.2 of RFC3261)
    */
   if (type == REQTYP_INCOMING) {
      DEBUGC(DBCLASS_PROXY,"Adding my Record-Route");
      route_add_recordroute(ticket);
   } else {
      /*
       * outgoing packets must not have my record route header, as
       * this likely will contain a private IP address (my inbound).
       */
      DEBUGC(DBCLASS_PROXY,"Purging Record-Routes (outgoing packet)");
      route_purge_recordroute(ticket);
   }

   /*
    * RFC 3261, Section 16.6 step 5
    * Proxy Behavior - Request Forwarding - Add Additional Header Fields
    */
   /* NOT IMPLEMENTED (optional) */


   /*
    * RFC 3261, Section 16.6 step 6
    * Proxy Behavior - Request Forwarding - Postprocess routing information
    *
    * If the copy contains a Route header field, the proxy MUST
    * inspect the URI in its first value.  If that URI does not
    * contain an lr parameter, the proxy MUST modify the copy as
    * follows:
    *
    * -  The proxy MUST place the Request-URI into the Route header
    *    field as the last value.
    *
    * -  The proxy MUST then place the first Route header field value
    *    into the Request-URI and remove that value from the Route
    *    header field.
    */
#if 0
   route_postprocess(ticket);
#endif

   /*
    * RFC 3261, Section 16.6 step 7
    * Proxy Behavior - Determine Next-Hop Address
    */
/*&&&& priority probably should be:
 * 1) Route header
 * 2) fixed outbound proxy
 * 3) SIP URI
 */
   /*
    * fixed or domain outbound proxy defined ?
    */
   if ((type == REQTYP_OUTGOING) &&
       (sip_find_outbound_proxy(ticket, &sendto_addr, &port) == STS_SUCCESS)) {
      DEBUGC(DBCLASS_PROXY, "proxy_request: have outbound proxy %s:%i",
             utils_inet_ntoa(sendto_addr), port);
   /*
    * Route present?
    * If so, fetch address from topmost Route: header and remove it.
    */
   } else if ((type == REQTYP_OUTGOING) && 
              (request->routes && !osip_list_eol(request->routes, 0))) {
      sts=route_determine_nexthop(ticket, &sendto_addr, &port);
      if (sts == STS_FAILURE) {
         DEBUGC(DBCLASS_PROXY, "proxy_request: route_determine_nexthop failed");
         return STS_FAILURE;
      }
      DEBUGC(DBCLASS_PROXY, "proxy_request: have Route header to %s:%i",
             utils_inet_ntoa(sendto_addr), port);
   /*
    * destination from SIP URI
    */
   } else {
      /* get the destination from the SIP URI */
      sts = get_ip_by_host(url->host, &sendto_addr);
      if (sts == STS_FAILURE) {
         DEBUGC(DBCLASS_PROXY, "proxy_request: cannot resolve URI [%s]",
                url->host);
         return STS_FAILURE;
      }

      if (url->port) {
         port=atoi(url->port);
      } else {
         port=SIP_PORT;
      }
      DEBUGC(DBCLASS_PROXY, "proxy_request: have SIP URI to %s:%i",
             url->host, port);
   }

   /*
    * RFC 3261, Section 16.6 step 8
    * Proxy Behavior - Add a Via header field value
    */
   /* add my Via header line (outbound interface)*/
   if (type == REQTYP_INCOMING) {
      sts = sip_add_myvia(ticket, IF_INBOUND);
      if (sts == STS_FAILURE) {
         ERROR("adding my inbound via failed!");
      }
   } else {
      sts = sip_add_myvia(ticket, IF_OUTBOUND);
      if (sts == STS_FAILURE) {
         ERROR("adding my outbound via failed!");
         return STS_FAILURE;
      }
   }
  /*
   * RFC 3261, Section 16.6 step 9
   * Proxy Behavior - Add a Content-Length header field if necessary
   */
  /* not necessary, already in message and we do not support TCP */

  /*
   * RFC 3261, Section 16.6 step 10
   * Proxy Behavior - Forward the new request
   */
   sts = sip_message_to_str(request, &buffer, &buflen);
   if (sts != 0) {
      ERROR("proxy_request: sip_message_to_str failed");
      return STS_FAILURE;
   }

   sipsock_send(sendto_addr, port, ticket->protocol,
                buffer, buflen); 
   osip_free (buffer);

  /*
   * RFC 3261, Section 16.6 step 11
   * Proxy Behavior - Set timer C
   */
  /* NOT IMPLEMENTED - does this really apply for stateless proxies? */

   return STS_SUCCESS;
}
Exemplo n.º 7
0
PPL_DECLARE (int) psp_core_event_add_sip_message (osip_event_t * evt)
{
  osip_transaction_t *transaction;
  osip_message_t *answer1xx;
  int i;

  if (MSG_IS_REQUEST (evt->sip))
    {
      /* delete request where cseq method does not match
	 the method in request-line */
      if (evt->sip->cseq==NULL || evt->sip==NULL
	  || evt->sip->cseq->method==NULL || evt->sip->sip_method==NULL)
	{
	  osip_event_free (evt);
	  return -1;
	}
      if (0 != strcmp (evt->sip->cseq->method, evt->sip->sip_method))
	{
	  OSIP_TRACE (osip_trace
		      (__FILE__, __LINE__, OSIP_WARNING, NULL,
		       "core module: Discard invalid message with method!=cseq!\n"));
	  osip_event_free (evt);
	  return -1;
	}
    }

  i = psp_core_find_osip_transaction_and_add_event (evt);
  if (i == 0)
    {
      psp_osip_wakeup (core->psp_osip);
      return 0;			/*evt consumed */
    }
  if (MSG_IS_REQUEST (evt->sip))
    {
      if (MSG_IS_ACK (evt->sip))
	{			/* continue as it is a new transaction... */
	  osip_route_t *route;

	  /* If a route header is present, then plugins will give
	     the correct location. */
	  osip_message_get_route (evt->sip, 0, &route);
	  if (route == NULL)
	    {
	      OSIP_TRACE (osip_trace
			  (__FILE__, __LINE__, OSIP_INFO1, NULL,
			   "core module: This is a late ACK to discard!\n"));
	      /* It can be a ACK for 200 ok, but those ACK SHOULD
	         never go through this proxy! (and should be sent to the
	         contact header of the 200ok */
#ifdef SUPPORT_FOR_BROKEN_UA
	      /* if this ACK has a request-uri that is not us,
		 forward the message there. How should I modify this
		 message?? */
	      
	      if (evt!=NULL
		  && evt->sip!=NULL
		  && evt->sip!=NULL
		  && evt->sip->req_uri!=NULL)
		{
		  if (psp_core_is_responsible_for_this_domain(evt->sip->req_uri)!=0)
		    {
		      int port = 5060;
		      if (evt->sip->req_uri->port != NULL)
			port = osip_atoi (evt->sip->req_uri->port);
		      psp_core_cb_snd_message(NULL, evt->sip,
					      evt->sip->req_uri->host,
					      port, -1);
 		    }
		}
#endif
	      osip_event_free (evt);
	      return 0;
	    }

	  OSIP_TRACE (osip_trace
		      (__FILE__, __LINE__, OSIP_INFO1, NULL,
		       "core module: This is a ACK for INVITE!\n"));
	  psp_core_event_add_sfp_inc_ack (evt->sip);
	  osip_free (evt);
	  return 0;
	}

      /* we can create the transaction and send a 1xx */
      transaction = osip_create_transaction (core->psp_osip->osip, evt);
      if (transaction == NULL)
	{
	  OSIP_TRACE (osip_trace
		      (__FILE__, __LINE__, OSIP_INFO3, NULL,
		       "core module: Could not create a transaction for this request!\n"));
	  osip_event_free (evt);
	  return -1;
	}

      /* now, all retransmissions will be handled by oSIP. */

      /* From rfc3261: (Section: 16.2)
         "Thus, a stateful proxy SHOULD NOT generate 100 (Trying) responses
         to non-INVITE requests." */
      if (MSG_IS_INVITE (evt->sip))
	{
	  i = osip_msg_build_response (&answer1xx, 100, evt->sip);
	  if (i != 0)
	    {
	      OSIP_TRACE (osip_trace
			  (__FILE__, __LINE__, OSIP_ERROR, NULL,
			   "sfp module: could not create a 100 Trying for this transaction. (discard it and let the transaction die itself)!\n"));
	      osip_event_free (evt);
	      return -1;
	    }

	  osip_transaction_add_event (transaction, evt);

	  evt = osip_new_outgoing_sipmessage (answer1xx);
	  evt->transactionid = transaction->transactionid;
	  osip_transaction_add_event (transaction, evt);
	}
      else
	osip_transaction_add_event (transaction, evt);

      psp_osip_wakeup (core->psp_osip);
      return 0;
    }
  else
    {
      OSIP_TRACE (osip_trace
		  (__FILE__, __LINE__, OSIP_INFO3, NULL,
		   "sfp module: No module seems to be able to forward this response!\n"));
      /* this is probably a late answer? */
      /* let's forward it! */
      i = psp_core_handle_late_answer (evt->sip);
      if (i != 0)
	{
	  osip_event_free (evt);
	  return -1;
	}
      osip_event_free (evt);
    }
  return 0;
}
Exemplo n.º 8
0
static int
ac_packetfilter_stats(ac_sip_t *asip, void *data)
{
	osip_message_t* sip = asip->evt->sip;
	char *callid = 0;
	unsigned long now = ship_systemtimemillis();

	if (asip->remotely_got) {
		/* .. meaning remotely got */
		if (MSG_IS_RESPONSE(sip)) {
			pdd_stat_t *stat = 0;
			int code = osip_message_get_status_code(sip);
			
			/* check for ACK with code != 100 */
			callid = sipp_get_call_id(sip);
			ship_lock(stats) ;
			if (code != 100 && 
			    (stat = ship_ht_get_string(stats, callid)) &&
			    !stat->end) {
				
				stat->end = ship_systemtimemillis();
				LOG_INFO("Got PDD for %s %s -> %s (status %d) in %u.%03u seconds..\n",
					 stat->msg_type, stat->from, stat->to, code, 
					 (stat->end - stat->start) / 1000, 	
					 ((stat->end - stat->start) % 1000));

				/* ... if we are recording special, then do that! */
				if (pdd_log) {
					pdd_record_pdd(stat);
				}

				/* remove.. ? */
				ship_ht_remove_string(stats, callid);

				ship_lock(done_stats);
				while (ship_list_length(done_stats) > 20) {
					pdd_stat_t *s2 = ship_list_pop(done_stats);
					ship_ht_remove(done_stats_ht, s2);
					pdd_free_stat(s2);
				}
				ship_list_add(done_stats, stat);
				ship_ht_put_string(done_stats_ht, callid, stat);
				ship_unlock(done_stats);
			}
			ship_unlock(stats);
		} else if (MSG_IS_INVITE(sip) || MSG_IS_MESSAGE(sip)) {
			/* record the pdd for the other fellow .. */
			callid = sipp_get_call_id(sip);
			
			/* send 'stats' packet back, event remote_req */
			ac_send_stats(asip->remote, asip->local,
				      now, callid, "remote_start");
		}
	} else {
		/* if we get an invite or something like that, record the time .. and so on */
		if (MSG_IS_INVITE(sip) || MSG_IS_MESSAGE(sip)) {

			/* if not seen already & pdd mode, do some
			   funky stuff.. */
			if (pdd_reset_mode) {
				LOG_INFO("pdd measurement mode: clearing SAs and peer DB!\n");
#ifdef CONFIG_HIP_ENABLED
				hipapi_clear_sas();
#endif
				ident_reset_foreign_regs();
				conn_close_all();
			}

			callid = sipp_get_call_id(sip);
			ship_lock(stats);
			if (!ship_ht_get_string(stats, callid)) {
				pdd_stat_t *stat = pdd_new_stat(sip, asip->from, asip->to);
				if (stat) {
					stat->start = ship_systemtimemillis();
					ship_ht_put_string(stats, callid, stat);
				}
			}
			ship_unlock(stats);
		} else if (MSG_IS_RESPONSE(sip)) {
			int code = osip_message_get_status_code(sip);
			if (code != 100) {
				callid = sipp_get_call_id(sip);

				/* send 'stats' packet back, event remote_resp */
				ac_send_stats(asip->remote, asip->local,
					      now, callid, "remote_end");
			}
		}
	}
	
	freez(callid);
	return 1;
}
Exemplo n.º 9
0
int main (int argc, char *argv[])
{
	int port = 5060;
	eXosip_event_t *event = NULL;
	succeed_type flag;
#if !defined(__arc__)
	struct servent *service = NULL;
#endif
	struct regparam_t regparam = { 0, 3600, 0 };
	int debug = 1;

	port = 5060;
#if 0
	if (debug > 0)
		TRACE_INITIALIZE (6, NULL);
#endif
	context_eXosip = eXosip_malloc ();
	if (eXosip_init (context_eXosip)) {
		printf("eXosip_init failed\r\n");
		exit (1);
	}
	if (eXosip_listen_addr (context_eXosip, IPPROTO_UDP, "192.168.5.118", port, AF_INET, 0)) {
		printf("eXosip_listen_addr failed\r\n");
		exit (1);
	}

	/*start the notify thread */

#ifndef OSIP_MONOTHREAD
	notify_thread = osip_thread_create(20000, notify_proc, &regparam);

#endif

	for(;;)
	{

		eXosip_event_t *event;

		if (!(event = eXosip_event_wait (context_eXosip, 0, 1))) {
#ifdef OSIP_MONOTHREAD
			eXosip_execute (context_eXosip);
			eXosip_automatic_action (context_eXosip);
#endif
//			osip_usleep (10000);
			continue;
		}

		eXosip_lock(context_eXosip);
#ifdef OSIP_MONOTHREAD	
		eXosip_execute (context_eXosip);
#endif			
		//		eXosip_automatic_action (context_eXosip);
		eXosip_unlock(context_eXosip);
		
		eXosip_automatic_action(context_eXosip);
		switch (event->type) {

			case EXOSIP_CALL_INVITE: 
				if(MSG_IS_INVITE(event->request))
				{
					flag = handle_request_invite(context_eXosip, event);
					if(flag == succeed_type_failed)
					{
						printf("handle invite request failed\r\n");
					}else{
						printf("handle invite request succeed\r\n");
					}
					continue;
				}
				break;
			case EXOSIP_CALL_REINVITE:
				break;
			case EXOSIP_CALL_NOANSWER:
				break;
			case EXOSIP_CALL_PROCEEDING:
				break;
			case EXOSIP_CALL_RINGING:
				break;
			case EXOSIP_CALL_ANSWERED:
				break;
			case EXOSIP_CALL_REDIRECTED:
				break;
			case EXOSIP_CALL_REQUESTFAILURE:
				break;
			case EXOSIP_CALL_SERVERFAILURE:
				break;
			case EXOSIP_CALL_GLOBALFAILURE:
				break;
			case EXOSIP_CALL_ACK:
				break;
			case EXOSIP_CALL_CANCELLED:
				break;
			case EXOSIP_CALL_MESSAGE_NEW:

				break;
			case EXOSIP_CALL_MESSAGE_PROCEEDING:
				printf("EXOSIP_CALL_MESSAGE_PROCEEDING\r\n");
				break;
			case EXOSIP_CALL_MESSAGE_ANSWERED:
				break;
			case EXOSIP_CALL_MESSAGE_REDIRECTED:
				break;
			case EXOSIP_CALL_MESSAGE_REQUESTFAILURE:
				break;
			case EXOSIP_CALL_MESSAGE_SERVERFAILURE:
				break;
			case EXOSIP_CALL_MESSAGE_GLOBALFAILURE:
				break;
			case EXOSIP_CALL_CLOSED:
				break;
			case EXOSIP_CALL_RELEASED:
				break;
			case EXOSIP_MESSAGE_NEW:
				printf("answer EXOSIP_MESSAGE_NEW\r\n");
				if(MSG_IS_MESSAGE(event->request)) 
				{
					flag = handle_request_message(context_eXosip, event);
					if(flag == succeed_type_failed)
					{
						printf("handle message request failed\r\n");
					}else{
						printf("handle message request succeed\r\n");
					}
					continue;
				}

				if(MSG_IS_REGISTER(event->request))
				{
					flag = handle_request_register(context_eXosip, event);
					if(flag == succeed_type_failed)
					{
						printf("handle register request failed\r\n");
					}else{
						printf("handle register request succeed\r\n");
					}
					continue;
				}

				break;
			case EXOSIP_MESSAGE_PROCEEDING:
				break;
			case EXOSIP_MESSAGE_ANSWERED:
				break;
			case EXOSIP_MESSAGE_REDIRECTED:
				break;
			case EXOSIP_MESSAGE_REQUESTFAILURE:
				break;
			case EXOSIP_MESSAGE_SERVERFAILURE:
				break;
			case EXOSIP_MESSAGE_GLOBALFAILURE:
				break;
			case EXOSIP_SUBSCRIPTION_NOANSWER:
				break;
			case EXOSIP_SUBSCRIPTION_PROCEEDING:
				break;
			case EXOSIP_SUBSCRIPTION_ANSWERED:
				break;
			case EXOSIP_SUBSCRIPTION_REDIRECTED:
				break;
			case EXOSIP_SUBSCRIPTION_REQUESTFAILURE:
				break;
			case EXOSIP_SUBSCRIPTION_SERVERFAILURE:
				break;
			case EXOSIP_SUBSCRIPTION_GLOBALFAILURE:
				break;
			case EXOSIP_SUBSCRIPTION_NOTIFY:
				break;
			case EXOSIP_IN_SUBSCRIPTION_NEW:  //subscribe event
				if(MSG_IS_SUBSCRIBE(event->request))
				{

					flag = handle_request_subscribe(context_eXosip, event);
					if(flag == succeed_type_failed)
					{
						printf("handle subscribe request failed\r\n");
					}else{
						printf("handle subscribe request succeed\r\n");
					}
					continue;
				}
				break;
			case EXOSIP_NOTIFICATION_NOANSWER:
				break;
			case EXOSIP_NOTIFICATION_PROCEEDING:
				break;
			case EXOSIP_NOTIFICATION_ANSWERED:
				break;
			case EXOSIP_NOTIFICATION_REDIRECTED:
				break;
			case EXOSIP_NOTIFICATION_REQUESTFAILURE:
				break;
			case EXOSIP_NOTIFICATION_SERVERFAILURE:
				break;
			case EXOSIP_NOTIFICATION_GLOBALFAILURE:
				break;
			case EXOSIP_EVENT_COUNT:
				break;
			default:
				printf( "recieved unknown eXosip event (type, did, cid) = (%d, %d, %d)", event->type, event->did, event->cid);

		}
		eXosip_event_free (event);
	}
		

	
}
Exemplo n.º 10
0
/*
  This method returns:
  -2 if plugin consider this request should be totally discarded!
  -1 on error
  0  nothing has been done
  1  things has been done on psp_req element
*/
int
cb_ls_localdb_search_user_location (psp_request_t * psp_req)
{
  osip_route_t *route;
  ppl_uinfo_t *uinfo;
  int i;
  int numlocs = 0 /* DAB */ ;
  osip_message_t *request;
  request = psp_request_get_request(psp_req);

  /* default OUTPUT */
  if (ISSET_R_ROUTE_MODE (ls_localdb_context->flag))
    psp_request_set_property (psp_req, PSP_STAY_ON_PATH);
  else
    psp_request_set_property (psp_req, 0);

  /* mode */
  if (ISSET_FORKING_MODE (ls_localdb_context->flag))
    psp_request_set_mode (psp_req, PSP_FORK_MODE);
  else if (ISSET_SEQUENTIAL_MODE (ls_localdb_context->flag))
    psp_request_set_mode (psp_req, PSP_SEQ_MODE);
  else if (ISSET_REDIRECT_MODE (ls_localdb_context->flag))
    {
      psp_request_set_uas_status (psp_req, 302);
      psp_request_set_mode (psp_req, PSP_UAS_MODE);
    }
  else
    psp_request_set_mode (psp_req, PSP_FORK_MODE);

  psp_request_set_state (psp_req, PSP_MANDATE);

  /* THIS IS MANDATORY FOR ALL PLUGINS TO CHECK THAT!
     this is rarely used as a previous plugin 'ls_localdb' should have
     checked for it. In case you remove it. */
  osip_message_get_route (request, 1, &route);
  if (route != NULL)
    {
      if (ISSET_SEQUENTIAL_MODE (ls_localdb_context->flag))
	psp_request_set_mode (psp_req, PSP_SEQ_MODE);
      else
	psp_request_set_mode (psp_req, PSP_FORK_MODE);
      psp_request_set_state (psp_req, PSP_MANDATE);
      return 0;			/* do nothing.. */
    }

  if (request->req_uri->username == NULL)
    {
      /* Propose 484, but let's keep searching if another plugin can find
	 the destination. */
      psp_request_set_uas_status (psp_req, 484);
      psp_request_set_state (psp_req, PSP_CONTINUE);
      psp_request_set_mode (psp_req, PSP_UAS_MODE);
      return 0;
    }

  /* look for this URI in our list of users */
  uinfo = ppl_uinfo_find_by_aor (request->req_uri);
  if (uinfo != NULL)
    {
      /* add all locations to the psp_req element */
      binding_t *bind;
      binding_t *bindnext;
      location_t *loc;
      osip_uri_t *url;

      bind = uinfo->bindings;
      bindnext = uinfo->bindings;
      for (; bind != NULL; bind = bindnext)
	{
	  bindnext = bind->next;
	  i = ppl_uinfo_check_binding (bind);
	  if (i != 0)
	    {			/* binding is expired */
	      ppl_uinfo_remove_binding (uinfo, bind);
	    }
	}
      bind = uinfo->bindings;
      if (bind == NULL)
	{			/* user is not around... */
	  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
				  "ls_localdb plugin: User Exist but has no valid registration!\n"));
	  psp_request_set_uas_status (psp_req, 480);
	  psp_request_set_mode (psp_req, PSP_UAS_MODE);
	  psp_request_set_state (psp_req, PSP_MANDATE);
	  return 0;
	}

      bindnext = uinfo->bindings;	/* DAB */
      for (; bind != NULL; bind = bindnext)	/* DAB */
	{			/* DAB */
	  /* If this is an INVITE Request,  collect all locations  DAB */
#ifdef EXPERIMENTAL_FORK
	  if (MSG_IS_INVITE (request))
	    bindnext = bind->next;	/* DAB */
	  else
	    bindnext = NULL;	/* DAB */
#else
	  /* always accept only ONE location even for INVITE */
	  /* this is a limitation for stability reason as the forking mode
	     is unfinished (calculation of the best response is not compliant
	     to the rfc3261.txt behavior. */
	  bindnext = NULL;	/* loop will be execute onece only */
#endif

	  i = osip_uri_clone (bind->contact->url, &url);
	  if (i != 0)
	    {
	      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
				      "ls_localdb plugin: Could not clone contact info!\n"));
	      psp_request_set_uas_status (psp_req, 400);
	      psp_request_set_mode (psp_req, PSP_UAS_MODE);
	      psp_request_set_state (psp_req, PSP_MANDATE);
	      return -1;
	    }
	  i = location_init (&loc, url, 3600);
	  if (i != 0)
	    {
	      osip_uri_free (url);
	      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_BUG, NULL,
				      "ls_localdb plugin: Could not create location info!\n"));
	      psp_request_set_uas_status (psp_req, 400);
	      psp_request_set_mode (psp_req, PSP_UAS_MODE);
	      psp_request_set_state (psp_req, PSP_MANDATE);
	      return -1;
	    }

	  /* new support for rfc3327.txt and Path header */
	  if (bind->path!=NULL)
	    location_set_path(loc, osip_strdup(bind->path));

	  ADD_ELEMENT (psp_req->locations, loc);
	  numlocs++;		/* DAB */
	}			/* DAB */

      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
			      "ls_localdb plugin: %d locations found!\n",
			      numlocs));
      return 0;
    }

  /* no user location found in local database... */
  psp_request_set_uas_status (psp_req, 404);
  psp_request_set_state (psp_req, PSP_CONTINUE);
  psp_request_set_mode (psp_req, PSP_UAS_MODE);
  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
			  "ls_localdb plugin: No location found for known user: return 404 Not found!!\n"));
  return 0;
}
Exemplo n.º 11
0
static struct session			*sip_callback(struct session *sip, u_char *data, uint32_t len)
{
  osip_message_t			*msg;
  struct tuple4				addr;
  struct session			*start;
  struct session			*rtp;
  osip_call_id_t			*call_id;

  osip_message_init(&msg);
  if (!osip_message_parse(msg, (char *)data, len)) {
    if (NULL == sip->u.sip_params.call_id) {
      /*
       * If the session object was created by udp_callback
       * we need to fill in the call_id field here because
       * udp_callback doesn't know anything about SIP
       */
      if (NULL != (call_id = osip_message_get_call_id(msg)))
	osip_call_id_clone(call_id, &sip->u.sip_params.call_id);
    } else {
      /*
       * Otherwise check if the session object passed to this
       * function call was really the one corresponding to the
       * call ID in the SIP packet, in case several SIP calls
       * are passed upon the same transport layer protocol,
       * source and destination IPv4 address & port combination.
       * udp_callback has no way of knowing how to distinguish
       * SIP session objects based on call ID, so we have to do
       * it here. We just continue searching in the list of all
       * tracked sessions for similar SIP objects until we find
       * one that has the same call ID, or else we create a new
       * SIP session object that corresponds to the new call.
       */
      start = sip;
      do {
	if (NULL == (call_id = osip_message_get_call_id(msg)))
	  continue;
	if (!osip_call_id_match(sip->u.sip_params.call_id, call_id))
	  break;
      } while ((sip = sessions_find(sip->next, TYPE_SIP, 0, &sip->addr)));
      if (NULL == sip) {
	if (bonus_time) {
	  osip_message_free(msg);
	  return start;
	}
	sip = sessions_add(start->type, &start->addr, NULL);
	if (NULL != (call_id = osip_message_get_call_id(msg)))
	  osip_call_id_clone(call_id, &sip->u.sip_params.call_id);
      }
    }
    /*
     * If the current SIP packet is an INVITE message, store the
     * advertised source port and IPv4 address. It is not very
     * important, since we can do only with the destination part
     * (useful in case the capture missed the INVITE packet), but
     * it helps discriminating from unrelated packets.
     *
     * Unfortunately, some SIP implementations such as the one in
     * Audiocodes Mediant 1000 SIP gateways actually use a source
     * port different from the one they advertised in the INVITE
     * message parameters - how outrageous! - so we have to make
     * our sessions search engine ignore the source port part by
     * zeroing it :-/
     */
    if (MSG_IS_INVITE(msg)) {
      if (!bonus_time) {
	sip_get_address(msg, &sip->u.sip_params.rtp_addr.saddr, &sip->u.sip_params.rtp_addr.source);
#ifndef USING_NON_STUPID_SIP_IMPLEMENTATIONS
	sip->u.sip_params.rtp_addr.source = 0;
#endif
      }
    } else
      if (MSG_TEST_CODE(msg, 200)) {
	if (MSG_IS_RESPONSE_FOR(msg, "INVITE")) {
	  if (!bonus_time && sip_get_address(msg, &sip->u.sip_params.rtp_addr.daddr, &sip->u.sip_params.rtp_addr.dest)) {
	    sessions_add(TYPE_UDP | TYPE_RTP, &sip->u.sip_params.rtp_addr, sip);
	    sip->u.sip_params.picked_up = 1;
	  }
	} else
	  if (MSG_IS_RESPONSE_FOR(msg, "BYE") ||
	      MSG_IS_RESPONSE_FOR(msg, "CANCEL")) {
	    start = first_session;
	    while (NULL != (rtp = sessions_find(start, TYPE_RTP, sip->id, NULL))) {
	      sessions_del(rtp);
	      start = rtp->next;
	    }
	    /*
	     * Mark for deletion in 2 seconds, in order to give some
	     * time to the extra ACK packets that might be exchanged
	     */
	    if (sip->type & TYPE_UDP)
	      sip->timeout = nids_last_pcap_header->ts.tv_sec + 2;
	  }
      }
  }
  osip_message_free(msg);
  return sip;
}
Exemplo n.º 12
0
static int
dtls_tl_send_message(osip_transaction_t * tr, osip_message_t * sip, char *host,
                    int port, int out_socket)
{
  int len = 0;
  size_t length = 0;
  struct addrinfo *addrinfo;
  struct __eXosip_sockaddr addr;
  char *message;

  char ipbuf[INET6_ADDRSTRLEN];
  int i;

  int pos;
  struct socket_tab *socket_tab_used=NULL;
  BIO *sbio=NULL;

  if (dtls_socket <= 0)
    return -1;

  if (host == NULL)
    {
      host = sip->req_uri->host;
      if (sip->req_uri->port != NULL)
        port = osip_atoi (sip->req_uri->port);
      else
        port = 5061;
    }

  if (port == 5060)
    port = 5061;

  if (MSG_IS_REQUEST(sip))
    {
      if (MSG_IS_REGISTER(sip)
	  ||MSG_IS_INVITE(sip)
	  ||MSG_IS_SUBSCRIBE(sip)
	  || MSG_IS_NOTIFY(sip))
	eXtl_update_local_target(sip);
    }

  i=-1;
#ifndef MINISIZE
  if (tr!=NULL && tr->record.name[0]!='\0' && tr->record.srventry[0].srv[0]!='\0')
    {
      /* always choose the first here.
	 if a network error occur, remove first entry and
	 replace with next entries.
      */
      osip_srv_entry_t *srv;
      int n=0;
      for (srv = &tr->record.srventry[0];
	   n<10 && tr->record.srventry[0].srv[0];
	   srv = &tr->record.srventry[0])
	{
	  i = eXosip_get_addrinfo (&addrinfo, srv->srv, srv->port, IPPROTO_UDP);
	  if (i == 0)
	    {
	      host = srv->srv;
	      port = srv->port;
	      break;
	    }
	  memmove(&tr->record.srventry[0], &tr->record.srventry[1], 9*sizeof(osip_srv_entry_t));
	  memset(&tr->record.srventry[9], 0, sizeof(osip_srv_entry_t));
	  i=-1;
	  /* copy next element */
	  n++;
	}
    }
#endif
  
  /* if SRV was used, distination may be already found */
  if (i != 0)
    {
      i = eXosip_get_addrinfo (&addrinfo, host, port, IPPROTO_UDP);
    }
  
  if (i != 0)
    {
      return -1;
    }
  
  memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
  len = addrinfo->ai_addrlen;
  
  eXosip_freeaddrinfo (addrinfo);
  
  /* remove preloaded route if there is no tag in the To header
   */
  {
    osip_route_t *route=NULL;
    osip_generic_param_t *tag=NULL;
    osip_message_get_route (sip, 0, &route);
    
    osip_to_get_tag (sip->to, &tag);
    if (tag==NULL && route != NULL && route->url != NULL)
      {
	osip_list_remove(&sip->routes, 0);
      }
    i = osip_message_to_str (sip, &message, &length);
    if (tag==NULL && route != NULL && route->url != NULL)
      {
	osip_list_add(&sip->routes, route, 0);
      }
  }
  
  if (i != 0 || length <= 0)
    {
      return -1;
    }
  
  switch ( ((struct sockaddr *)&addr)->sa_family )
    {
    case AF_INET:
      inet_ntop (((struct sockaddr *)&addr)->sa_family, &(((struct sockaddr_in *) &addr)->sin_addr),
		 ipbuf, sizeof (ipbuf));
      break;
    case AF_INET6:
      inet_ntop (((struct sockaddr *)&addr)->sa_family,
		 &(((struct sockaddr_in6 *) &addr)->sin6_addr), ipbuf,
		 sizeof (ipbuf));
      break;
    default:
      strncpy (ipbuf, "(unknown)", sizeof (ipbuf));
      break;
    }
  
  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
                          "Message sent: \n%s (to dest=%s:%i)\n",
                          message, ipbuf, port));

  for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++)
    {
      if (dtls_socket_tab[pos].ssl_conn != NULL
	  && dtls_socket_tab[pos].ssl_type == EXOSIP_AS_A_SERVER)
	{
	  if (dtls_socket_tab[pos].remote_port == port &&
	      (strcmp (dtls_socket_tab[pos].remote_ip, ipbuf) == 0))
	    {
	      BIO *rbio;
	      socket_tab_used = &dtls_socket_tab[pos];
	      rbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE);
	      BIO_dgram_set_peer (rbio, &addr);
	      dtls_socket_tab[pos].ssl_conn->rbio = rbio;
	      break;
	    }
	}
    }
  if (socket_tab_used==NULL)
    {
      for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++)
	{
	  if (dtls_socket_tab[pos].ssl_conn != NULL
	      && dtls_socket_tab[pos].ssl_type == EXOSIP_AS_A_CLIENT)
	    {
	      if (dtls_socket_tab[pos].remote_port == port &&
		  (strcmp (dtls_socket_tab[pos].remote_ip, ipbuf) == 0))
		{
		  BIO *rbio;
		  socket_tab_used = &dtls_socket_tab[pos];
		  rbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE);
		  BIO_dgram_set_peer (rbio, &addr);
		  dtls_socket_tab[pos].ssl_conn->rbio = rbio;
		  break;
		}
	    }
	}
    }

  if (socket_tab_used==NULL)
    {
      /* delete an old one! */
      pos=0;
      if (dtls_socket_tab[pos].ssl_conn != NULL)
	{
	  shutdown_free_client_dtls (pos);
	  shutdown_free_server_dtls (pos);
	}
      
      memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab));
    }
  
  if (dtls_socket_tab[pos].ssl_conn == NULL)
    {
      /* create a new one */
      SSL_CTX_set_read_ahead (client_ctx, 1);
      dtls_socket_tab[pos].ssl_conn = SSL_new (client_ctx);

      if (dtls_socket_tab[pos].ssl_conn == NULL)
	{
	  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
				  "DTLS SSL_new error\n"));

	  if (dtls_socket_tab[pos].ssl_conn != NULL)
	    {
	      shutdown_free_client_dtls (pos);
	      shutdown_free_server_dtls (pos);
	    }
	  
	  memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab));

	  osip_free (message);
	  return -1;
	}

      if (connect (dtls_socket, (struct sockaddr *) &addr, sizeof (addr)) == -1)
	{
	  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
				  "DTLS connect error\n"));
	  if (dtls_socket_tab[pos].ssl_conn != NULL)
	    {
	      shutdown_free_client_dtls (pos);
	      shutdown_free_server_dtls (pos);
	    }
	  
	  memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab));

	  osip_free (message);
	  return -1;
	}
      
      SSL_set_options (dtls_socket_tab[pos].ssl_conn, SSL_OP_NO_QUERY_MTU);
      SSL_set_mtu (dtls_socket_tab[pos].ssl_conn, 2000);
      SSL_set_connect_state (dtls_socket_tab[pos].ssl_conn);
      sbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE);
      BIO_ctrl_set_connected (sbio, 1, (struct sockaddr *) &addr);
      SSL_set_bio (dtls_socket_tab[pos].ssl_conn, sbio, sbio);

      dtls_socket_tab[pos].ssl_type = 2;
      dtls_socket_tab[pos].ssl_state = 2;
      
      osip_strncpy (dtls_socket_tab[pos].remote_ip, ipbuf,
		    sizeof (dtls_socket_tab[pos].remote_ip));
      dtls_socket_tab[pos].remote_port = port;
    }

  i = SSL_write (dtls_socket_tab[pos].ssl_conn, message, length);

  if (i<0)
    {
      i = SSL_get_error (dtls_socket_tab[pos].ssl_conn, i);
      print_ssl_error (i);
      if (i==SSL_ERROR_SSL
	  || i==SSL_ERROR_SYSCALL)
	{
	  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
				  "DTLS SSL_write error\n"));
	  if (dtls_socket_tab[pos].ssl_conn != NULL)
	      {
		shutdown_free_client_dtls (pos);
		shutdown_free_server_dtls (pos);
	      }
	  
	  memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab));
	  
	}

#ifndef MINISIZE
      /* delete first SRV entry that is not reachable */
      if (tr->record.name[0]!='\0' && tr->record.srventry[0].srv[0]!='\0')
	{
	  memmove(&tr->record.srventry[0], &tr->record.srventry[1], 9*sizeof(osip_srv_entry_t));
	  memset(&tr->record.srventry[9], 0, sizeof(osip_srv_entry_t));
	  osip_free (message);
	  return 0; /* retry for next retransmission! */
	}
#endif
      /* SIP_NETWORK_ERROR; */
      osip_free (message);
      return -1;
    }

  if (eXosip.keep_alive > 0)
    {
      if (MSG_IS_REGISTER (sip))
        {
          eXosip_reg_t *reg = NULL;
	  
          if (_eXosip_reg_find (&reg, tr) == 0)
            {
              memcpy (&(reg->addr), &addr, len);
              reg->len = len;
            }
        }
    }
  
  osip_free (message);
  return 0;
}
Exemplo n.º 13
0
char *
generating_sdp_answer(osip_message_t *request, osip_negotiation_ctx_t *context)
{
  sdp_message_t *remote_sdp;
  sdp_message_t *local_sdp = NULL;
  int i;
  char *local_body;
  if (context==NULL)
    return NULL;

  local_body = NULL;
  if (MSG_IS_INVITE(request)||MSG_IS_OPTIONS(request)||MSG_IS_RESPONSE_FOR(request, "INVITE"))
    {
      osip_body_t *body;
      body = (osip_body_t *)osip_list_get(&request->bodies,0);
      if(body == NULL)
	return NULL;
      
      /* remote_sdp = (sdp_message_t *) osip_malloc(sizeof(sdp_message_t)); */
      i = sdp_message_init(&remote_sdp);
      if (i!=0) return NULL;
      
      /* WE ASSUME IT IS A SDP BODY AND THAT    */
      /* IT IS THE ONLY ONE, OF COURSE, THIS IS */
      /* NOT TRUE */
      i = sdp_message_parse(remote_sdp,body->body);
      if (i!=0) return NULL;

      i = osip_negotiation_ctx_set_remote_sdp(context, remote_sdp);

      i = osip_negotiation_ctx_execute_negotiation(eXosip.osip_negotiation, context);
      if (i==200)
	{
	  local_sdp = osip_negotiation_ctx_get_local_sdp(context);

	  i = sdp_message_to_str(local_sdp, &local_body);

	  remote_sdp = osip_negotiation_ctx_get_remote_sdp(context);
	  sdp_message_free(remote_sdp);
	  osip_negotiation_ctx_set_remote_sdp(context, NULL);

	  if (i!=0) {
	    OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_ERROR,NULL,"ERROR: Could not parse local SDP answer %i\n",i));
	    return NULL;
	  }
	  return local_body;
	}
      else if (i==415)
	{
	  OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_INFO1,NULL,"WARNING: Unsupported media %i\n",i));
	}
      else
	{
	  OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_ERROR,NULL,"ERROR: while building answer to SDP (%i)\n",i));
	}
      remote_sdp = osip_negotiation_ctx_get_remote_sdp(context);
      sdp_message_free(remote_sdp);
      osip_negotiation_ctx_set_remote_sdp(context, NULL);
    }
  return NULL;
}
Exemplo n.º 14
0
/* code (entry point) */
static int plugin_regex_process(sip_ticket_t *ticket) {
   int sts=STS_SUCCESS;
   osip_uri_t *req_url;
   osip_uri_t *to_url;
   osip_generic_param_t *r=NULL;

   /* plugin loaded and not configured, return with success */
   if (plugin_cfg.regex_pattern.used==0) return STS_SUCCESS;
   if (plugin_cfg.regex_replace.used==0) return STS_SUCCESS;

   DEBUGC(DBCLASS_PLUGIN,"plugin entered");
   req_url=osip_message_get_uri(ticket->sipmsg);
   to_url=osip_to_get_url(ticket->sipmsg);

   /* only outgoing direction is handled */
   sip_find_direction(ticket, NULL);
   if (ticket->direction != DIR_OUTGOING)
      return STS_SUCCESS;

   /* only INVITE and ACK are handled */
   if (!MSG_IS_INVITE(ticket->sipmsg) && !MSG_IS_ACK(ticket->sipmsg))
      return STS_SUCCESS;

   /* expire old cache entries */
   expire_redirected_cache(&redirected_cache);

   /* REQ URI with username must exist, prefix string must exist */
   if (!req_url || !req_url->username)
      return STS_SUCCESS; /* ignore */

   /* Loop avoidance:
    * If this INVITE has already been redirected by a prior 302
    * moved response a "REDIRECTED_TAG" parameter should be present in the
    * URI.
    * Hopefully all UAs (Clients) do honor RFC3261 and copy the
    * *full* URI form the contact header into the new request header
    * upon a 3xx response.
    */
   if (req_url) {
      osip_uri_param_get_byname(&(req_url->url_params), REDIRECTED_TAG, &r);
      if (r && r->gvalue && strcmp(r->gvalue,REDIRECTED_VAL)== 0) {
         DEBUGC(DBCLASS_PLUGIN,"Packet has already been processed (ReqURI)");
         return STS_SUCCESS;
      }
   }
   if (to_url) {
      osip_uri_param_get_byname(&(to_url->url_params), REDIRECTED_TAG, &r);
      if (r && r->gvalue && strcmp(r->gvalue,REDIRECTED_VAL)== 0) {
         DEBUGC(DBCLASS_PLUGIN,"Packet has already been processed (ToURI)");
         return STS_SUCCESS;
      }
   }

   /*
    * The SIP message is to be processed
    */

   /* outgoing INVITE request */
   if (MSG_IS_INVITE(ticket->sipmsg)) {
      DEBUGC(DBCLASS_PLUGIN,"processing INVITE");
      sts=plugin_regex_redirect(ticket);
   }
   /* outgoing ACK request: is result of a local 3xx answer (moved...)
    *
    * Only consume that particular ACK that belongs to a sent 302 answer,
    * nothing else. Otherwise the ACK from the redirected call will get 
    * consumed as well and causes the call to be aborted (timeout).
    * We keep a cache with Call-Ids of such "302 moved" dialogs.
    * Only consume such ACKs that are part of such a dialog.
    */
   else if (MSG_IS_ACK(ticket->sipmsg)) {
      if (is_in_redirected_cache(&redirected_cache, ticket) == STS_TRUE) {
	 DEBUGC(DBCLASS_PLUGIN,"processing ACK (consume it)");
	 sts=STS_SIP_SENT; /* eat up the ACK that was directed to myself */
      }
   }

   return sts;
}