コード例 #1
0
int sca_set_called_line(struct sip_msg *msg, char *line_var)
{
	pv_value_t value;
	str line;

	if (no_dialog_support) {
		LM_ERR("dialog support is disabled, cannot use this function\n");
		return -1;
	}

	if (msg->REQ_METHOD != METHOD_INVITE)
		return 1;

	/* get the name of line first */
	if (line_var) {
		/* take it from param */
		if ( pv_get_spec_value( msg, (pv_spec_p)line_var, &value) < 0 ) {
			LM_ERR("failed to evaluate parameter\n");
			return -1;
		}
		if ( (value.flags&PV_VAL_STR)==0 ) {
			LM_ERR("line value is not a string (flags are %d)\n",value.flags);
			return -1;
		}
		line = value.rs;
	} else {
		/* take it from RURI msg */
		line = *GET_RURI(msg);
	}

	return sca_set_line(msg, &line, 0/*called*/);
}
コード例 #2
0
ファイル: t_fwd.c プロジェクト: rrb3942/opensips
static int dst_to_msg(struct sip_msg *s_msg, struct sip_msg *d_msg)
{
	/* move RURI */
	if (set_ruri( d_msg, GET_RURI(s_msg))<0) {
		LM_ERR("failed to set new RURI\n");
		return -1;
	}

	/* move DURI (empty is accepted as reset) */
	if (set_dst_uri( d_msg, &s_msg->dst_uri)<0) {
		LM_ERR("failed to set DST URI\n");
		return -1;
	}

	/* move PATH  (empty is accepted as reset) */
	if (set_path_vector( d_msg, & s_msg->path_vec)<0) {
		LM_ERR("failed to set PATH\n");
		return -1;
	}

	/* Qval */
	set_ruri_q( d_msg, get_ruri_q(s_msg) );

	/* BFLAGS */
	setb0flags( d_msg, getb0flags(s_msg) );

	/* socket info */
	d_msg->force_send_socket = s_msg->force_send_socket;

	return 0;
}
コード例 #3
0
ファイル: tm.c プロジェクト: Deni90/opensips
static int pv_get_tm_ruri(struct sip_msg *msg, pv_param_t *param,
		pv_value_t *res)
{
	struct cell *t;

	if(msg==NULL || res==NULL)
		return -1;

	/* first get the transaction */
	if (t_check( msg , 0 )==-1) return -1;
	if ( (t=get_t())==0) {
		/* no T */
		if (msg!=NULL&&msg!=FAKED_REPLY && msg->first_line.type==SIP_REQUEST){
			res->rs = *GET_RURI(msg);
			res->flags = PV_VAL_STR;
			return 0;
		}
		return pv_get_null(msg, param,res);
	}

	/* return the RURI for the current branch */
	if (_tm_branch_index>=t->nr_of_outgoings) {
		LM_ERR("BUG: _tm_branch_index greater than nr_of_outgoings\n");
		return -1;
	}

	res->rs = t->uac[_tm_branch_index].uri;

	res->flags = PV_VAL_STR;

	return 0;
}
コード例 #4
0
int w_is_gruu(sip_msg_t *msg, char *uri1, char *p2)
{
	str s1, *s2;
	sip_uri_t turi;
	sip_uri_t *puri;

	if(uri1!=NULL)
	{
		if(fixup_get_svalue(msg, (gparam_p)uri1, &s1)!=0)
		{
			LM_ERR("cannot get first parameter\n");
			return -8;
		}
		if(parse_uri(s1.s, s1.len, &turi)!=0) {
			LM_ERR("parsing of uri '%.*s' failed\n", s1.len, s1.s);
			return -1;
		}
		puri = &turi;
	} else {
		if(parse_sip_msg_uri(msg)<0) {
			s2 = GET_RURI(msg);
			LM_ERR("parsing of uri '%.*s' failed\n", s2->len, s2->s);
			return -1;
		}
		puri = &msg->parsed_uri;
	}
	if(puri->gr.s!=NULL)
	{
		if(puri->gr_val.len>0)
			return 1;
		return 2;
	}
	return -1;
}
コード例 #5
0
/* these wrappers parse all what may be needed; they don't care about
 * the result -- accounting functions just display "unavailable" if there
 * is nothing meaningful
 */
static int acc_rad_missed1(struct sip_msg *rq, char* p1, char* p2)
{
    int code;
    preparse_req(rq);
    if (get_int_fparam(&code, rq, (fparam_t*)p1) < 0) {
	code = 0;
    }
    return log_request(rq, GET_RURI(rq), rq->to, code, time(0));
}
コード例 #6
0
static void log_ack(struct cell* t , struct sip_msg *ack, time_t req_time)
{
	struct sip_msg *rq;
	struct hdr_field *to;

	rq = t->uas.request;
	if (ack->to) to = ack->to;
	else to = rq->to;
	log_request(ack, GET_RURI(ack), to, t->uas.status, req_time);
}
コード例 #7
0
/* these wrappers parse all what may be needed; they don't care about
 * the result -- accounting functions just display "unavailable" if there
 * is nothing meaningful
 */
static int acc_db_request1(struct sip_msg *rq, char* p1, char* p2)
{
    int code;

    if (get_int_fparam(&code, rq, (fparam_t*)p1) < 0) {
	code = 0;
    }
    preparse_req(rq);
    return log_request(rq, GET_RURI(rq), rq->to, acc_table.s, code, time(0));
}
コード例 #8
0
ファイル: checks.c プロジェクト: BackupTheBerlios/ser
/*
 * Converts Request-URI, if it is tel URI, to SIP URI.  Returns 1, if
 * conversion succeeded or if no conversion was needed, i.e., Request-URI
 * was not tel URI.  Returns -1, if conversion failed.
 */
int tel2sip(struct sip_msg* _msg, char* _s1, char* _s2)
{
	str *ruri, furi;
	struct sip_uri pfuri;
	str suri;
	char* at;

	ruri = GET_RURI(_msg);

	if (ruri->len < 4) return 1;

	if (strncmp(ruri->s, "tel:", 4) != 0) return 1;

	if (parse_from_header(_msg) < 0) {
		LOG(L_ERR, "tel2sip(): Error while parsing From header\n");
		return -1;
	}
	furi = get_from(_msg)->uri;
	if (parse_uri(furi.s, furi.len, &pfuri) < 0) {
		LOG(L_ERR, "tel2sip(): Error while parsing From URI\n");
		return -1;
	}

	suri.len = 4 + ruri->len - 4 + 1 + pfuri.host.len + 1 + 10;
	suri.s = pkg_malloc(suri.len);
	if (suri.s == 0) {
		LOG(L_ERR, "tel2sip(): Memory allocation failure\n");
		return -1;
	}
	at = suri.s;
	memcpy(at, "sip:", 4);
	at = at + 4;
	memcpy(at, ruri->s + 4, ruri->len - 4);
	at = at + ruri->len - 4;
	*at = '@';
	at = at + 1;
	memcpy(at, pfuri.host.s, pfuri.host.len);
	at = at + pfuri.host.len;
	*at = ';';
	at = at + 1;
	memcpy(at, "user=phone", 10);

	LOG(L_ERR, "tel2sip(): SIP URI is <%.*s>\n", suri.len, suri.s);

	if (rewrite_uri(_msg, &suri) == 1) {
		pkg_free(suri.s);
		return 1;
	} else {
		pkg_free(suri.s);
		return -1;
	}
}
コード例 #9
0
ファイル: call_control.c プロジェクト: 4N7HR4X/kamailio
// Get canonical request URI
static str
get_canonical_request_uri(struct sip_msg* msg)
{
    int_str value;

    if (!search_first_avp(canonical_uri_avp.type | AVP_VAL_STR,
                          canonical_uri_avp.name, &value, NULL) ||
        value.s.s==NULL || value.s.len==0) {

        return *GET_RURI(msg);
    }

    return value.s;
}
コード例 #10
0
ファイル: checks.c プロジェクト: alias-neo/opensips
/*
 * Converts Request-URI, if it is tel URI, to SIP URI.  Returns 1, if
 * conversion succeeded or if no conversion was needed, i.e., Request-URI
 * was not tel URI.  Returns -1, if conversion failed.
 */
int tel2sip(struct sip_msg* _msg, char* _s1, char* _s2)
{
	str *ruri;
	struct sip_uri *pfuri;
	str suri;
	char* at;

	ruri = GET_RURI(_msg);

	if (ruri->len < 4) return 1;

	if (strncasecmp(ruri->s, "tel:", 4) != 0){
		return 1;
	}

	if ((pfuri=parse_from_uri(_msg))==NULL) {
		LM_ERR("parsing From header failed\n");
		return -1;
	}

	suri.len = 4 + ruri->len - 4 + 1 + pfuri->host.len + 1 + 10;
	suri.s = pkg_malloc(suri.len);
	if (suri.s == 0) {
		LM_ERR("no more pkg memory\n");
		return -1;
	}
	at = suri.s;
	memcpy(at, "sip:", 4);
	at = at + 4;
	memcpy(at, ruri->s + 4, ruri->len - 4);
	at = at + ruri->len - 4;
	*at = '@';
	at = at + 1;
	memcpy(at, pfuri->host.s, pfuri->host.len);
	at = at + pfuri->host.len;
	*at = ';';
	at = at + 1;
	memcpy(at, "user=phone", 10);

	if (set_ruri(_msg, &suri) == 1) {
		pkg_free(suri.s);
		return 1;
	} else {
		pkg_free(suri.s);
		return -1;
	}
}
コード例 #11
0
ファイル: t_fwd.c プロジェクト: rrb3942/opensips
int t_replicate(struct sip_msg *p_msg, str *dst, int flags)
{
	/* this is a quite horrible hack -- we just take the message
	   as is, including Route-s, Record-route-s, and Vias ,
	   forward it downstream and prevent replies received
	   from relaying by setting the replication/local_trans bit;

		nevertheless, it should be good enough for the primary
		customer of this function, REGISTER replication

		if we want later to make it thoroughly, we need to
		introduce delete lumps for all the header fields above
	*/
	struct cell *t;

	if ( set_dst_uri( p_msg, dst)!=0 ) {
		LM_ERR("failed to set dst uri\n");
		return -1;
	}

	if ( branch_uri2dset( GET_RURI(p_msg) )!=0 ) {
		LM_ERR("failed to convert uri to dst\n");
		return -1;
	}

	t=get_t();

	if (!t || t==T_UNDEFINED) {
		/* no transaction yet */
		if (route_type==FAILURE_ROUTE) {
			LM_CRIT("BUG - undefined transaction in failure route\n");
			return -1;
		}
		return t_relay_to( p_msg, NULL, flags|TM_T_RELAY_repl_FLAG);
	} else {
		/* transaction already created */
		if (p_msg->REQ_METHOD==METHOD_ACK)
			/* local ACK */
			return -1;

		t->flags|=T_IS_LOCAL_FLAG;

		return t_forward_nonack( t, p_msg, NULL, 1/*reset*/, 0/*unlocked*/);
	}
}
コード例 #12
0
ファイル: ds_backend.c プロジェクト: 4N7HR4X/kamailio
int ds_hash_ruri(struct sip_msg *msg, unsigned int *hash)
{
	str* uri;
	str key1;
	str key2;
	
	
	if(msg==NULL || hash == NULL)
	{
		LOG(L_ERR, "DISPATCHER:ds_hash_ruri: bad parameters\n");
		return -1;
	}
	if (parse_sip_msg_uri(msg)<0){
		LOG(L_ERR, "DISPATCHER: ds_hash_ruri: ERROR: bad request uri\n");
		return -1;
	}
	
	uri=GET_RURI(msg);
	if (get_uri_hash_keys(&key1, &key2, uri, &msg->parsed_uri, ds_flags)<0)
		return -1;
	
	*hash = ds_get_hash(&key1, &key2);
	return 0;
}
コード例 #13
0
ファイル: t_serial.c プロジェクト: mehulsbhatt/voip-foip
/* 
 * Loads contacts in destination set into contacts_avp in reverse
 * priority order and associated each contact with Q_FLAG telling if
 * contact is the last one in its priority class.  Finally, removes
 * all branches from destination set.
 */
int t_load_contacts(struct sip_msg* msg, char* key, char* value)
{
    str uri, tmp, dst_uri, path, branch_info, *ruri;
    qvalue_t first_q, q;
    struct contact *contacts, *next, *prev, *curr;
    int_str val;
    int first_idx, idx;
    struct socket_info* sock;
    unsigned int flags;

    /* Check if contacts_avp has been defined */
    if (contacts_avp.n == 0) {
		LM_ERR("feature has been disabled - "
		       "to enable define contacts_avp module parameter");
		return -1;
    }

    /* Check if anything needs to be done */
    if (nr_branches == 0) {
		LM_DBG("t_load_contacts(): nothing to do - no branches!\n");
		return 1;
    }

    ruri = (str *)0;

    /* Take first q from Request-URI */
    ruri = GET_RURI(msg);
    if (!ruri) {
	LM_ERR("no Request-URI found\n");
	return -1;
    }
    first_q = get_ruri_q();
    first_idx = 0;

    /* Check if all q values are equal */
    for(idx = first_idx; (tmp.s = get_branch(idx, &tmp.len, &q, 0, 0, 0, 0))
			!= 0; idx++) {
		if (q != first_q) {
			goto rest;
		}
    }

    LM_DBG("t_load_contacts(): nothing to do - all contacts have same q!\n");
    return 1;

rest:

    /* Allocate memory for first contact */
    contacts = (struct contact *)pkg_malloc(sizeof(struct contact));
    if (!contacts) {
		LM_ERR("no memory for contact info\n");
		return -1;
    }

    /* Insert Request-URI branch to first contact */
    contacts->uri.s = ruri->s;
    contacts->uri.len = ruri->len;
    contacts->dst_uri = msg->dst_uri;
    contacts->sock = msg->force_send_socket;
    getbflagsval(0, &contacts->flags);
    contacts->path = msg->path_vec;
    contacts->q = first_q;
    contacts->next = (struct contact *)0;

    /* Insert (remaining) branches to contact list in increasing q order */

    for(idx = first_idx;
		(uri.s = get_branch(idx,&uri.len,&q,&dst_uri,&path,&flags,&sock))
			!= 0;
		idx++ ) {
		next = (struct contact *)pkg_malloc(sizeof(struct contact));
		if (!next) {
			LM_ERR("no memory for contact info\n");
			free_contact_list(contacts);
			return -1;
		}
		next->uri = uri;
		next->q = q;
		next->dst_uri = dst_uri;
		next->path = path;
		next->flags = flags;
		next->sock = sock;
		next->next = (struct contact *)0;
		prev = (struct contact *)0;
		curr = contacts;
		while (curr && (curr->q < q)) {
			prev = curr;
			curr = curr->next;
		}
		if (!curr) {
			next->next = (struct contact *)0;
			prev->next = next;
		} else {
			next->next = curr;
			if (prev) {
				prev->next = next;
			} else {
				contacts = next;
			}
		}    
    }

    /* Assign values for q_flags */
    curr = contacts;
    curr->q_flag = 0;
    while (curr->next) {
		if (curr->q < curr->next->q) {
			curr->next->q_flag = Q_FLAG;
		} else {
			curr->next->q_flag = 0;
		}
		curr = curr->next;
    }

    /* Add contacts to contacts_avp */
    curr = contacts;
    while (curr) {
		if (encode_branch_info(&branch_info, curr) == 0) {
			LM_ERR("encoding of branch info failed\n");
			free_contact_list(contacts);
			if (branch_info.s) pkg_free(branch_info.s);
			return -1;
		}
		val.s = branch_info;
		add_avp(contacts_avp_type|AVP_VAL_STR|(curr->q_flag),
				contacts_avp, val);
		pkg_free(branch_info.s);
		LM_DBG("loaded contact <%.*s> with q_flag <%d>\n",
		       STR_FMT(&val.s), curr->q_flag);
		curr = curr->next;
    }

    /* Clear all branches */
    clear_branches();

    /* Free contact list */
    free_contact_list(contacts);

    return 1;
}
コード例 #14
0
ファイル: seas_action.c プロジェクト: 4N7HR4X/kamailio
/* Actions are composed as follows:
 * (the action length and type as always= 5 bytes)
 *
 * TODO performance speedup: instead of using
 * dynamically allocated memory for headers,body,totag,reason and my_msg
 * use static buffers.
 *
 */
int ac_sl_msg(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len)
{
   struct sip_msg *my_msg;
   str *uri;
   struct proxy_l *proxy;
   rr_t *my_route;
   int k,retval;
   //enum sip_protos proto;

   my_msg=NULL;
   k=0;

   proxy=0;

   if(!(my_msg = parse_ac_msg(HDR_EOH_F,action+k,len-k))){
      LM_ERR("out of memory!\n");
      goto error;
   }
   if(my_msg->first_line.type == SIP_REQUEST)
      LM_DBG("forwarding request:\"%.*s\" statelessly \n",my_msg->first_line.u.request.method.len+1+\
	    my_msg->first_line.u.request.uri.len,my_msg->first_line.u.request.method.s);
   else
      LM_DBG("forwarding reply:\"%.*s\" statelessly \n",my_msg->first_line.u.reply.status.len+1+\
	    my_msg->first_line.u.reply.reason.len,my_msg->first_line.u.reply.status.s);

   if (my_msg->route) {
      if (parse_rr(my_msg->route) < 0) {
	 LM_ERR( "Error while parsing Route body\n");
	 goto error;
      }
      my_route = (rr_t*)my_msg->route->parsed;
      uri=&(my_route->nameaddr.uri);
   }else{
      uri = GET_RURI(my_msg);
   }
   set_force_socket(my_msg, grep_sock_info(&my_msg->via1->host,
                                            my_msg->via1->port,
                                            my_msg->via1->proto) );
   /* or also could be:
      my_msg->force_send_socket=the_as->binds[processor_id].bind_address;
      not sure which is better...
      */
   /*proxy=uri2proxy(uri,PROTO_NONE);
   if (proxy==0) {
      LM_ERR("unable to create proxy from URI \n");
      goto error;
   }
   proto=proxy->proto;
   */
   //TODO my_msg->recvd
   if(0>forward_sl_request(my_msg,uri,PROTO_NONE))
      goto error;
   retval=0;
   goto exit;
error:
   retval = -1;
exit:
   if(proxy){
      free_proxy(proxy);
      pkg_free(proxy);
   }
   if(my_msg){
      free_sip_msg_lite(my_msg);
      pkg_free(my_msg);
   }
   return retval;
}
コード例 #15
0
ファイル: checks.c プロジェクト: AndreyRybkin/kamailio
/*
 * Adds a new parameter to Request URI
 */
int add_uri_param(struct sip_msg* _msg, char* _param, char* _s2)
{
	str *param, *cur_uri, new_uri;
	struct sip_uri *parsed_uri;
	char *at;

	param = (str*)_param;

	if (param->len == 0) {
		return 1;
	}

	if (parse_sip_msg_uri(_msg) < 0) {
	        LM_ERR("ruri parsing failed\n");
	        return -1;
	}

	parsed_uri = &(_msg->parsed_uri);

	/* if current ruri has no headers, pad param at the end */
	if (parsed_uri->headers.len == 0) {
		cur_uri =  GET_RURI(_msg);
		new_uri.len = cur_uri->len + param->len + 1;
		if (new_uri.len > MAX_URI_SIZE) {
			LM_ERR("new ruri too long\n");
			return -1;
		}
		new_uri.s = pkg_malloc(new_uri.len);
		if (new_uri.s == 0) {
			LM_ERR("add_uri_param(): Memory allocation failure\n");
			return -1;
		}
		memcpy(new_uri.s, cur_uri->s, cur_uri->len);
		*(new_uri.s + cur_uri->len) = ';';
		memcpy(new_uri.s + cur_uri->len + 1, param->s, param->len);
		if (rewrite_uri(_msg, &new_uri ) == 1) {
			goto ok;
		} else {
			goto nok;
		}
	}

	/* otherwise take the long path */
	new_uri.len = 4 +
		(parsed_uri->user.len ? parsed_uri->user.len + 1 : 0) +
		(parsed_uri->passwd.len ? parsed_uri->passwd.len + 1 : 0) +
		parsed_uri->host.len +
		(parsed_uri->port.len ? parsed_uri->port.len + 1 : 0) +
		parsed_uri->params.len + param->len + 1 +
		parsed_uri->headers.len + 1;
	if (new_uri.len > MAX_URI_SIZE) {
	        LM_ERR("new ruri too long\n");
		return -1;
	}

	new_uri.s = pkg_malloc(new_uri.len);
	if (new_uri.s == 0) {
		LM_ERR("no more pkg memory\n");
		return -1;
	}

	at = new_uri.s;
	memcpy(at, "sip:", 4);
	at = at + 4;
	if (parsed_uri->user.len) {
		memcpy(at, parsed_uri->user.s, parsed_uri->user.len);
		if (parsed_uri->passwd.len) {
			*at = ':';
			at = at + 1;
			memcpy(at, parsed_uri->passwd.s, parsed_uri->passwd.len);
			at = at + parsed_uri->passwd.len;
		};
		*at = '@';
		at = at + 1;
	}
	memcpy(at, parsed_uri->host.s, parsed_uri->host.len);
	at = at + parsed_uri->host.len;
	if (parsed_uri->port.len) {
		*at = ':';
		at = at + 1;
		memcpy(at, parsed_uri->port.s, parsed_uri->port.len);
		at = at + parsed_uri->port.len;
	}
	memcpy(at, parsed_uri->params.s, parsed_uri->params.len);
	at = at + parsed_uri->params.len;
	*at = ';';
	at = at + 1;
	memcpy(at, param->s, param->len);
	at = at + param->len;
	*at = '?';
	at = at + 1;
	memcpy(at, parsed_uri->headers.s, parsed_uri->headers.len);

	if (rewrite_uri(_msg, &new_uri) == 1) {
		goto ok;
	}

nok:
	pkg_free(new_uri.s);
	return -1;

ok:
	pkg_free(new_uri.s);
	return 1;
}
コード例 #16
0
int t_relay_to( struct sip_msg  *p_msg , struct proxy_l *proxy, int proto,
				int replicate)
{
	int ret;
	int new_tran;
	str *uri;
	int reply_ret;
	/* struct hdr_field *hdr; */
	struct cell *t;

	ret=0;

	new_tran = t_newtran( p_msg );

	/* parsing error, memory alloc, whatever ... if via is bad
	   and we are forced to reply there, return with 0 (->break),
	   pass error status otherwise
	*/
	if (new_tran<0) {
		ret = (ser_error==E_BAD_VIA && reply_to_via) ? 0 : new_tran;
		goto done;
	}
	/* if that was a retransmission, return we are happily done */
	if (new_tran==0) {
		ret = 1;
		goto done;
	}

	/* new transaction */

	/* ACKs do not establish a transaction and are fwd-ed statelessly */
	if ( p_msg->REQ_METHOD==METHOD_ACK) {
		DBG("DEBUG:tm:t_relay: forwarding ACK  statelessly \n");
		if (proxy==0) {
			uri = GET_RURI(p_msg);
			proxy=uri2proxy(GET_NEXT_HOP(p_msg), proto);
			if (proxy==0) {
					ret=E_BAD_ADDRESS;
					goto done;
			}
			proto=proxy->proto; /* uri2proxy set it correctly */
			ret=forward_request( p_msg , proxy, proto) ;
			free_proxy( proxy );	
			pkg_free( proxy );
		} else {
			proto=get_proto(proto, proxy->proto);
			ret=forward_request( p_msg , proxy, proto ) ;
		}
		goto done;
	}

	/* if replication flag is set, mark the transaction as local
	   so that replies will not be relaied */
	t=get_t();
	if (replicate) t->flags|=T_IS_LOCAL_FLAG;

	/* INVITE processing might take long, particularly because of DNS
	   look-ups -- let upstream know we're working on it */
	if (p_msg->REQ_METHOD==METHOD_INVITE )
	{
		DBG("DEBUG:tm:t_relay: new INVITE\n");
		if (!t_reply( t, p_msg , 100 ,
			"trying -- your call is important to us"))
				DBG("SER: ERROR: t_reply (100)\n");
	} 

	/* now go ahead and forward ... */
	ret=t_forward_nonack(t, p_msg, proxy, proto);
	if (ret<=0) {
		DBG( "ERROR:tm:t_relay_to:  t_forward_nonack returned error \n");
		/* we don't want to pass upstream any reply regarding replicating
		 * a request; replicated branch must stop at us*/
		if (!replicate) {
			reply_ret=kill_transaction( t );
			if (reply_ret>0) {
				/* we have taken care of all -- do nothing in
			  	script */
				DBG("ERROR: generation of a stateful reply "
					"on error succeeded\n");
				ret=0;
			}  else {
				DBG("ERROR: generation of a stateful reply "
					"on error failed\n");
			}
		}
	} else {
		DBG( "SER: new transaction fwd'ed\n");
	}

done:
	return ret;
}
コード例 #17
0
/* these wrappers parse all what may be needed; they don't care about
 * the result -- accounting functions just display "unavailable" if there
 * is nothing meaningful
 */
static int acc_db_missed0(struct sip_msg *rq, char* s1, char* s2)
{
	preparse_req(rq);
	return log_request(rq, GET_RURI(rq), rq->to, mc_table.s, 0, time(0));
}
コード例 #18
0
ファイル: t_msgbuilder.c プロジェクト: lbalaceanu/kamailio
/**
 * Evaluates the routing elements in locally originated request or reply to
 * locally originated request.
 * If original INVITE was in-dialog (had to-tag), it uses the
 * routes present there (b/c the 2xx for it does not have a RR set, normally).
 * Otherwise, use the reply (b/c the INVITE does not have yet the complete
 * route set).
 *
 * @return: negative for failure; out params:
 *  - list: route set;
 *  - ruri: RURI to be used in ACK;
 *  - nexthop: where to first send the ACK.
 *
 *  NOTE: assumes rpl's parsed to EOF!
 *
 */
static int eval_uac_routing(sip_msg_t *rpl, const struct retr_buf *inv_rb,
		str* contact, struct rte **list, str *ruri, str *next_hop)
{
	sip_msg_t orig_inv, *sipmsg; /* reparse original INVITE */
	rte_t *t, *prev_t, *rtset = NULL;
	int is_req;
	struct sip_uri puri;
	static size_t chklen;

	/* parse the retr. buffer */
	memset(&orig_inv, 0, sizeof(struct sip_msg));
	orig_inv.buf = inv_rb->buffer;
	orig_inv.len = inv_rb->buffer_len;
	LM_DBG("reparsing retransmission buffer of original INVITE:\n%.*s\n",
			(int)orig_inv.len, orig_inv.buf);
	if (parse_msg(orig_inv.buf, orig_inv.len, &orig_inv) != 0) {
		LM_ERR("failed to parse retr buffer (weird!): \n%.*s\n",
				(int)orig_inv.len, orig_inv.buf);
		return -1;
	}

	/* check if we need to look at request or reply */
	if ((parse_headers(&orig_inv, HDR_TO_F, 0) < 0) || (! orig_inv.to)) {
		/* the bug is at message assembly */
		LM_BUG("failed to parse INVITE retr. buffer and/or extract 'To' HF:"
				"\n%.*s\n", (int)orig_inv.len, orig_inv.buf);
		goto error;
	}
	if (((struct to_body *)orig_inv.to->parsed)->tag_value.len) {
		LM_DBG("building ACK for in-dialog INVITE (using RS in orig. INV.)\n");
		if (parse_headers(&orig_inv, HDR_EOH_F, 0) < 0) {
			LM_BUG("failed to parse INVITE retr. buffer to EOH:"
					"\n%.*s\n", (int)orig_inv.len, orig_inv.buf);
			goto error;
		}
		sipmsg = &orig_inv;
		is_req = 1;
	} else {
		LM_DBG("building ACK for out-of-dialog INVITE (using RS in RR set).\n");
		sipmsg = rpl;
		is_req = 0;
	}

	/* extract the route set */
	if (get_uac_rs(sipmsg, is_req, &rtset) < 0) {
		LM_ERR("failed to extract route set.\n");
		goto error;
	}

	if (! rtset) { /* No routes */
		*ruri = *contact;
		*next_hop = *contact;
	} else if (! is_req) { /* out of dialog req. */
		if (parse_uri(rtset->ptr->nameaddr.uri.s, rtset->ptr->nameaddr.uri.len,
				&puri) < 0) {
			LM_ERR("failed to parse first route in set.\n");
			goto error;
		}

		if (puri.lr.s) { /* Next hop is loose router */
			*ruri = *contact;
			*next_hop = rtset->ptr->nameaddr.uri;
		} else { /* Next hop is strict router */
			*ruri = rtset->ptr->nameaddr.uri;
			*next_hop = *ruri;
			/* consume first route, b/c it will be put in RURI */
			t = rtset;
			rtset = rtset->next;
			pkg_free(t);
		}
	} else {
		unsigned long route_flags = inv_rb->flags;
		LM_DBG("UAC rb flags: 0x%x.\n", (unsigned int)route_flags);
eval_flags:
		switch (route_flags & (F_RB_NH_LOOSE|F_RB_NH_STRICT)) {
		case 0:
			LM_WARN("calculate_hooks() not called when built the local UAC of "
					"in-dialog request, or called with empty route set.\n");
			/* try to figure out what kind of hop is the next one
			 * (strict/loose) by reading the original invite */
			if ((route_flags = nhop_type(&orig_inv, rtset, &inv_rb->dst,
					contact))) {
				LM_DBG("original request's next hop type evaluated to: 0x%x.\n",
						(unsigned int)route_flags);
				goto eval_flags;
			} else {
				LM_ERR("failed to establish what kind of router the next "
						"hop is.\n");
				goto error;
			}
			break;
		case F_RB_NH_LOOSE:
			*ruri = *contact;
			*next_hop = rtset->ptr->nameaddr.uri;
			break;
		case F_RB_NH_STRICT:
			/* find ptr to last route body that contains the (possibly) old
			 * remote target
			 */
			for (t = rtset, prev_t = NULL; t->next; prev_t = t, t = t->next)
				;
			if ((t->ptr->len == contact->len) &&
					(memcmp(t->ptr->nameaddr.name.s, contact->s,
							contact->len) == 0)){
				/* the remote target didn't update -> keep the whole route set,
				 * including the last entry */
				/* do nothing */
			} else {
				/* trash last entry and replace with new remote target */
				free_rte_list(t);
				/* compact the rr_t struct along with rte. this way, free'ing
				 * it can be done along with rte chunk, independent of Route
				 * header parser's allocator (using pkg/shm) */
				chklen = sizeof(struct rte) + sizeof(rr_t);
				if (! (t = pkg_malloc(chklen))) {
					ERR("out of pkg memory (%d required)\n", (int)chklen);
					/* last element was freed, unlink it */
					if(prev_t == NULL) {
						/* there is only one elem in route set: the remote target */
						rtset = NULL;
					} else {
						prev_t->next = NULL;
					}
					goto error;
				}
				/* this way, .free_rr is also set to 0 (!!!) */
				memset(t, 0, chklen);
				((rr_t *)&t[1])->nameaddr.name = *contact;
				((rr_t *)&t[1])->len = contact->len;
				/* chain the new route elem in set */
				if (prev_t == NULL)
					/* there is only one elem in route set: the remote target */
					rtset = t;
				else
					prev_t->next = t;
			}

			*ruri = *GET_RURI(&orig_inv); /* reuse original RURI */
			*next_hop = *ruri;
			break;
		default:
			/* probably a mem corruption */
			LM_BUG("next hop of original request marked as both loose"
					" and strict router (buffer: %.*s).\n",
					inv_rb->buffer_len, inv_rb->buffer);
#ifdef EXTRA_DEBUG
			abort();
#else
			goto error;
#endif
		}
	}

	*list = rtset;
	free_sip_msg(&orig_inv);
	/* all went well */
	return 0;

error:
	free_sip_msg(&orig_inv);
	if (rtset)
		free_rte_list(rtset);
	return -1;
}
コード例 #19
0
ファイル: contact_ops.c プロジェクト: AndreyRybkin/kamailio
int
decode_contact_header (struct sip_msg *msg,char *unused1,char *unused2)
{

	contact_body_t *cb;
	contact_t *c;
	str uri;
	str newUri;
	char separator;
	int res;
	
	
#ifdef DEBUG
	str* ruri;
	fprintf (stdout,"---START--------DECODE CONTACT HEADER-----------------\n");
#endif

	if ((msg->contact == NULL)&&((parse_headers(msg,HDR_CONTACT_F,0) == -1) ||
				(msg->contact== NULL) ))
		{
		LM_ERR("no Contact header present\n");
		return -1;
		}

	separator = DEFAULT_SEPARATOR[0];
	if (contact_flds_separator != NULL)
		if (strlen(contact_flds_separator)>=1)
			separator = contact_flds_separator[0];

#ifdef DEBUG
	fprintf (stdout,"Using separator %c\n",separator);
	ruri = GET_RURI(msg);
	fprintf (stdout,"[len = %d]New uri is->%.*s\n",
			ruri->len,ruri->len,ruri->s);
	ruri = &msg->first_line.u.request.uri;
	fprintf (stdout, "INITIAL.s=[%.*s]\n", ruri->len, ruri->s);
#endif
		
	if (msg->contact->parsed == NULL) parse_contact (msg->contact);
	if (msg->contact->parsed != NULL)
	{
		cb = (contact_body_t *) msg->contact->parsed;
		c = cb->contacts;
		// we visit each contact 
	 if (c != NULL)
	  {
		uri = c->uri;

		res = decode_uri (uri, separator, &newUri);
#ifdef DEBUG
		fprintf (stdout, "newuri.s=[%.*s]\n", newUri.len, newUri.s);
#endif
		if (res != 0)
		{
			LM_ERR("failed decoding contact.Code %d\n", res);
#ifdef STRICT_CHECK
				return res;
#endif
		}
		else
		if (patch (msg, uri.s, uri.len, newUri.s, newUri.len) < 0)
		{
			LM_ERR("lumping failed in mangling port \n");
			return -2;
		}

#ifdef DECODE_ALL_CONTACTS
		while (c->next != NULL)
		{
			c = c->next;
			uri = c->uri;

			res = decode_uri (uri, separator, &newUri);
			if (res != 0)
				{
				LM_ERR("failed decoding contact.Code %d\n",res);
#ifdef STRICT_CHECK
				return res;
#endif
				}
			else
			if (patch (msg, uri.s, uri.len, newUri.s, newUri.len) < 0)
			{
				LM_ERR("lumping failed in mangling port \n");
				return -3;
			}
		} // end while 
#endif
	   } // if c!= NULL 
	} // end if 
	else // after parsing still NULL 
		{
			LM_ERR("unable to parse Contact header\n");
			return -4;
		}
#ifdef DEBUG
	fprintf (stdout,"---END--------DECODE CONTACT HEADER-----------------\n");fflush(stdout);
#endif
	return 1;
}
コード例 #20
0
ファイル: t_fwd.c プロジェクト: OPSF/uClinux
/* function returns:
 *       1 - forward successful
 *      -1 - error during forward
 */
int t_forward_nonack( struct cell *t, struct sip_msg* p_msg ,
                      struct proxy_l * proxy, int proto)
{
    str          backup_uri;
    int branch_ret, lowest_ret;
    str current_uri;
    branch_bm_t	added_branches;
    int first_branch;
    int i, q;
    struct cell *t_invite;
    int success_branch;
    int try_new;
    str dst_uri;

    /* make -Wall happy */
    current_uri.s=0;

    set_kr(REQ_FWDED);

    if (p_msg->REQ_METHOD==METHOD_CANCEL) {
        t_invite=t_lookupOriginalT(  p_msg );
        if (t_invite!=T_NULL_CELL) {
            e2e_cancel( p_msg, t, t_invite );
            UNREF(t_invite);
            return 1;
        }
    }

    /* backup current uri ... add_uac changes it */
    backup_uri = p_msg->new_uri;
    /* if no more specific error code is known, use this */
    lowest_ret=E_BUG;
    /* branches added */
    added_branches=0;
    /* branch to begin with */
    first_branch=t->nr_of_outgoings;

    /* on first-time forwarding, use current uri, later only what
       is in additional branches (which may be continuously refilled
    */
    if (first_branch==0) {
        try_new=1;
        branch_ret=add_uac( t, p_msg, GET_RURI(p_msg), GET_NEXT_HOP(p_msg), proxy, proto );
        if (branch_ret>=0)
            added_branches |= 1<<branch_ret;
        else
            lowest_ret=branch_ret;
    } else try_new=0;

    init_branch_iterator();
    while((current_uri.s=next_branch( &current_uri.len, &q, &dst_uri.s, &dst_uri.len))) {
        try_new++;
        branch_ret=add_uac( t, p_msg, &current_uri,
                            (dst_uri.len) ? (&dst_uri) : &current_uri,
                            proxy, proto);
        /* pick some of the errors in case things go wrong;
           note that picking lowest error is just as good as
           any other algorithm which picks any other negative
           branch result */
        if (branch_ret>=0)
            added_branches |= 1<<branch_ret;
        else
            lowest_ret=branch_ret;
    }
    /* consume processed branches */
    clear_branches();

    /* restore original URI */
    p_msg->new_uri=backup_uri;

    /* don't forget to clear all branches processed so far */

    /* things went wrong ... no new branch has been fwd-ed at all */
    if (added_branches==0) {
        if (try_new==0) {
            LOG(L_ERR, "ERROR: t_forward_nonack: no branched for forwarding\n");
            return -1;
        }
        LOG(L_ERR, "ERROR: t_forward_nonack: failure to add branches\n");
        return lowest_ret;
    }

    /* send them out now */
    success_branch=0;
    for (i=first_branch; i<t->nr_of_outgoings; i++) {
        if (added_branches & (1<<i)) {
            if (SEND_BUFFER( &t->uac[i].request)==-1) {
                LOG(L_ERR, "ERROR: t_forward_nonack: sending request failed\n");
                if (proxy) {
                    proxy->errors++;
                    proxy->ok=0;
                }
            } else {
                success_branch++;
            }
            start_retr( &t->uac[i].request );
        }
    }
    if (success_branch<=0) {
        ser_error=E_SEND;
        return -1;
    }
    return 1;
}
コード例 #21
0
ファイル: t_fwd.c プロジェクト: abh-gitcs1989/opensips
/* function returns:
 *       1 - forward successful
 *      -1 - error during forward
 */
int t_forward_nonack( struct cell *t, struct sip_msg* p_msg ,
	struct proxy_l * proxy)
{
	str backup_uri;
	str backup_dst;
	int branch_ret, lowest_ret;
	str current_uri;
	branch_bm_t  added_branches;
	int i, q;
	struct cell *t_invite;
	int success_branch;
	str dst_uri;
	struct socket_info *bk_sock;
	unsigned int br_flags;
	unsigned int bk_br_flags;
	int idx;
	str path;
	str bk_path;

	/* make -Wall happy */
	current_uri.s=0;

	/* before doing enything, update the t falgs from msg */
	t->uas.request->flags = p_msg->flags;

	if (p_msg->REQ_METHOD==METHOD_CANCEL) {
		t_invite=t_lookupOriginalT(  p_msg );
		if (t_invite!=T_NULL_CELL) {
			t_invite->flags |= T_WAS_CANCELLED_FLAG;
			cancel_invite( p_msg, t, t_invite );
			return 1;
		}
	}

	/* do not forward requests which were already cancelled*/
	if (was_cancelled(t) || no_new_branches(t)) {
		LM_ERR("discarding fwd for a cancelled/6xx transaction\n");
		ser_error = E_NO_DESTINATION;
		return -1;
	}

	/* backup current uri, sock and flags... add_uac changes it */
	backup_uri = p_msg->new_uri;
	backup_dst = p_msg->dst_uri;
	bk_sock = p_msg->force_send_socket;
	bk_br_flags = getb0flags();
	bk_path = p_msg->path_vec;

	/* check if the UAS retranmission port needs to be updated */
	if ( (p_msg->msg_flags ^ t->uas.request->msg_flags) & FL_FORCE_RPORT )
		su_setport( &t->uas.response.dst.to, p_msg->rcv.src_port );

	/* if no more specific error code is known, use this */
	lowest_ret=E_BUG;
	/* branches added */
	added_branches=0;
	/* branch to begin with */
	t->first_branch=t->nr_of_outgoings;

	/* as first branch, use current uri */
	current_uri = *GET_RURI(p_msg);
	branch_ret = add_uac( t, p_msg, &current_uri, &backup_dst,
		&p_msg->path_vec, proxy);
	if (branch_ret>=0)
		added_branches |= 1<<branch_ret;
	else
		lowest_ret=branch_ret;

	/* ....and now add the remaining additional branches */
	for( idx=0; (current_uri.s=get_branch( idx, &current_uri.len, &q,
	&dst_uri, &path, &br_flags, &p_msg->force_send_socket))!=0 ; idx++ ) {
		setb0flags(br_flags);
		branch_ret = add_uac( t, p_msg, &current_uri, &dst_uri, &path, proxy);
		/* pick some of the errors in case things go wrong;
		   note that picking lowest error is just as good as
		   any other algorithm which picks any other negative
		   branch result */
		if (branch_ret>=0)
			added_branches |= 1<<branch_ret;
		else
			lowest_ret=branch_ret;
	}
	/* consume processed branches */
	clear_branches();

	/* restore original stuff */
	p_msg->new_uri=backup_uri;
	p_msg->parsed_uri_ok = 0;/* just to be sure; add_uac may parse other uris*/
	p_msg->dst_uri = backup_dst;
	p_msg->force_send_socket = bk_sock;
	p_msg->path_vec = bk_path;
	setb0flags(bk_br_flags);
	/* update on_branch, if modified */
	t->on_branch = get_on_branch();
	/* update flags, if changed in branch route */
	t->uas.request->flags = p_msg->flags;

	/* things went wrong ... no new branch has been fwd-ed at all */
	if (added_branches==0) {
		LM_ERR("failure to add branches\n");
		ser_error = lowest_ret;
		return lowest_ret;
	}

	/* send them out now */
	success_branch=0;
	for (i=t->first_branch; i<t->nr_of_outgoings; i++) {
		if (added_branches & (1<<i)) {

#ifdef USE_TCP
			if (t->uac[i].br_flags & tcp_no_new_conn_bflag)
				tcp_no_new_conn = 1;
#endif

			do {
				if (check_blacklists( t->uac[i].request.dst.proto,
				&t->uac[i].request.dst.to,
				t->uac[i].request.buffer.s,
				t->uac[i].request.buffer.len)) {
					LM_DBG("blocked by blacklists\n");
					ser_error=E_IP_BLOCKED;
				} else {
					if (SEND_BUFFER( &t->uac[i].request)==0) {
						ser_error = 0;
						break;
					}
					LM_ERR("sending request failed\n");
					ser_error=E_SEND;
				}
				/* get next dns entry */
				if ( t->uac[i].proxy==0 ||
				get_next_su( t->uac[i].proxy, &t->uac[i].request.dst.to,
				(ser_error==E_IP_BLOCKED)?0:1)!=0 )
					break;
				t->uac[i].request.dst.proto = t->uac[i].proxy->proto;
				/* update branch */
				if ( update_uac_dst( p_msg, &t->uac[i] )!=0)
					break;
			}while(1);

#ifdef USE_TCP
			tcp_no_new_conn = 0;
#endif

			if (ser_error) {
				shm_free(t->uac[i].request.buffer.s);
				t->uac[i].request.buffer.s = NULL;
				t->uac[i].request.buffer.len = 0;
				continue;
			}

			success_branch++;

			start_retr( &t->uac[i].request );
			set_kr(REQ_FWDED);

			/* successfully sent out -> run callbacks */
			if ( has_tran_tmcbs( t, TMCB_REQUEST_BUILT) ) {
				set_extra_tmcb_params( &t->uac[i].request.buffer,
					&t->uac[i].request.dst);
				run_trans_callbacks( TMCB_REQUEST_BUILT, t, p_msg,0,
					-p_msg->REQ_METHOD);
			}

		}
	}

	return (success_branch>0)?1:-1;
}
コード例 #22
0
ファイル: sterman.c プロジェクト: 4N7HR4X/kamailio
/*
 * This function creates and submits radius authentication request as per
 * draft-sterman-aaa-sip-00.txt.  In addition, _user parameter is included
 * in the request as value of a SER specific attribute type SIP-URI-User,
 * which can be be used as a check item in the request.  Service type of
 * the request is Authenticate-Only.
 */
int radius_authorize_sterman(VALUE_PAIR** received, struct sip_msg* _msg, dig_cred_t* _cred, str* _method, str* _user) 
{
	static char msg[4096];
	VALUE_PAIR *send;
	UINT4 service, ser_service_type;
	str method, user, user_name;
	str *ruri;
	int i;
	
	send = 0;

	if (!(_cred && _method && _user)) {
		LOG(L_ERR, "radius_authorize_sterman(): Invalid parameter value\n");
		return -1;
	}

	method = *_method;
	user = *_user;
	
	/*
	 * Add all the user digest parameters according to the qop defined.
	 * Most devices tested only offer support for the simplest digest.
	 */
	if (_cred->username.domain.len) {
	        if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_USER_NAME].v), 
				   _cred->username.whole.s, _cred->username.whole.len, 
			           VENDOR(attrs[A_USER_NAME].v))) {
			LOG(L_ERR, "radius_authorize_sterman(): Unable to add User-Name attribute\n");
			goto err;
		}
	} else {
		user_name.len = _cred->username.user.len + _cred->realm.len + 1;
		user_name.s = pkg_malloc(user_name.len);
		if (!user_name.s) {
			LOG(L_ERR, "radius_authorize_sterman(): No memory left\n");
			return -3;
		}
		memcpy(user_name.s, _cred->username.whole.s, _cred->username.whole.len);
		user_name.s[_cred->username.whole.len] = '@';
		memcpy(user_name.s + _cred->username.whole.len + 1, _cred->realm.s, _cred->realm.len);
		if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_USER_NAME].v), 
				   user_name.s, user_name.len, 
				   VENDOR(attrs[A_USER_NAME].v))) {
			LOG(L_ERR, "sterman(): Unable to add User-Name attribute\n");
			pkg_free(user_name.s);
			goto err;
		}
		pkg_free(user_name.s);
	}

	if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_USER_NAME].v), 
			   _cred->username.whole.s, _cred->username.whole.len, 
			   VENDOR(attrs[A_DIGEST_USER_NAME].v))) {
		LOG(L_ERR, "sterman(): Unable to add Digest-User-Name attribute\n");
		goto err;
	}

	if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_REALM].v), 
			   _cred->realm.s, _cred->realm.len, 
			   VENDOR(attrs[A_DIGEST_REALM].v))) {
		LOG(L_ERR, "sterman(): Unable to add Digest-Realm attribute\n");
		goto err;
	}
	if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_NONCE].v), 
			   _cred->nonce.s, _cred->nonce.len, 
			   VENDOR(attrs[A_DIGEST_NONCE].v))) {
		LOG(L_ERR, "sterman(): Unable to add Digest-Nonce attribute\n");
		goto err;
	}
	
	if (use_ruri_flag < 0 || isflagset(_msg, use_ruri_flag) != 1) {
		ruri = &_cred->uri;
	} else {
		ruri = GET_RURI(_msg);
	}
	if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_URI].v), 
			   ruri->s, ruri->len, 
			   VENDOR(attrs[A_DIGEST_URI].v))) {
		LOG(L_ERR, "sterman(): Unable to add Digest-URI attribute\n");
		goto err;
	}
		
	if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_METHOD].v),
			   method.s, method.len, 
			   VENDOR(attrs[A_DIGEST_METHOD].v))) {
	        LOG(L_ERR, "sterman(): Unable to add Digest-Method attribute\n");
		goto err;
	}
	
	/* 
	 * Add the additional authentication fields according to the QOP.
	 */
	if (_cred->qop.qop_parsed == QOP_AUTH) {
		if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_QOP].v), "auth", 4,
				   VENDOR(attrs[A_DIGEST_QOP].v))) {
			LOG(L_ERR, "sterman(): Unable to add Digest-QOP attribute\n");
			goto err;
		}
		if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_NONCE_COUNT].v), 
				   _cred->nc.s, _cred->nc.len,
				   VENDOR(attrs[A_DIGEST_NONCE_COUNT].v))) {
			LOG(L_ERR, "sterman(): Unable to add Digest-CNonce-Count attribute\n");
			goto err;
		}
		if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_CNONCE].v), 
				   _cred->cnonce.s, _cred->cnonce.len,
				   VENDOR(attrs[A_DIGEST_CNONCE].v))) {
			LOG(L_ERR, "sterman(): Unable to add Digest-CNonce attribute\n");
			goto err;
		}
	} else if (_cred->qop.qop_parsed == QOP_AUTHINT) {
	        if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_QOP].v), "auth-int", 8, 
				   VENDOR(attrs[A_DIGEST_QOP].v))) {
		        LOG(L_ERR, "sterman(): Unable to add Digest-QOP attribute\n");
			goto err;
		}
		if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_NONCE_COUNT].v), 
				   _cred->nc.s, _cred->nc.len, 
				   VENDOR(attrs[A_DIGEST_NONCE_COUNT].v))) {
			LOG(L_ERR, "sterman(): Unable to add Digest-Nonce-Count attribute\n");
			goto err;
		}
		if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_CNONCE].v), 
				   _cred->cnonce.s, _cred->cnonce.len, 
				   VENDOR(attrs[A_DIGEST_CNONCE].v))) {
			LOG(L_ERR, "sterman(): Unable to add Digest-CNonce attribute\n");
			goto err;
		}
		if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_BODY_DIGEST].v), 
				   _cred->opaque.s, _cred->opaque.len, 
				   VENDOR(attrs[A_DIGEST_BODY_DIGEST].v))) {
			LOG(L_ERR, "sterman(): Unable to add Digest-Body-Digest attribute\n");
			goto err;
		}
		
	} else  {
		/* send nothing for qop == "" */
	}

	/* Add the response... What to calculate against... */
	if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_RESPONSE].v), 
			   _cred->response.s, _cred->response.len, 
			   VENDOR(attrs[A_DIGEST_RESPONSE].v))) {
		LOG(L_ERR, "sterman(): Unable to add Digest-Response attribute\n");
		goto err;
	}

	/* Indicate the service type, Authenticate only in our case */
	service = vals[V_SIP_SESSION].v;
	if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SERVICE_TYPE].v), 
			   &service, -1, 
			   VENDOR(attrs[A_SERVICE_TYPE].v))) {
	        LOG(L_ERR, "sterman(): Unable to add Service-Type attribute\n");
		goto err;
	}

	/* Indicate the service type, Authenticate only in our case */
	ser_service_type = vals[V_DIGEST_AUTHENTICATION].v;
	if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SER_SERVICE_TYPE].v), 
			   &ser_service_type, -1, 
			   VENDOR(attrs[A_SER_SERVICE_TYPE].v))) {
		LOG(L_ERR, "sterman(): Unable to add SER-Service-Type attribute\n");
		goto err;
	}

	/* Add SIP URI as a check item */
	if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SER_URI_USER].v), 
			   user.s, user.len, 
			   VENDOR(attrs[A_SER_URI_USER].v))) {
		LOG(L_ERR, "sterman(): Unable to add Sip-URI-User attribute\n");
		goto err;
	}

	if (attrs[A_CISCO_AVPAIR].n != NULL) {
		if (add_cisco_vsa(&send, _msg)) {
			goto err;
		}
	}

	/* Send request */
	if ((i = rc_auth(rh, SIP_PORT, send, received, msg)) == OK_RC) {
		DBG("radius_authorize_sterman(): Success\n");
		rc_avpair_free(send);
		send = 0;
		return 1;
	} else {
		DBG("radius_authorize_sterman(): Failure\n");
		goto err;
	}

 err:
	if (send) rc_avpair_free(send);	
	return -1;
}
コード例 #23
0
ファイル: t_msgbuilder.c プロジェクト: lbalaceanu/kamailio
/**
 * Evaluate if next hop is a strict or loose router, by looking at the
 * retr. buffer of the original INVITE.
 * Assumes:
 * 	orig_inv is a parsed SIP message;
 * 	rtset is not NULL.
 * @return:
 * 	F_RB_NH_LOOSE : next hop was loose router;
 * 	F_RB_NH_STRICT: nh is strict;
 * 	0 on error.
 */
static unsigned long nhop_type(sip_msg_t *orig_inv, rte_t *rtset,
		const struct dest_info *dst_inv, str *contact)
{
	struct sip_uri puri, topr_uri, lastr_uri, inv_ruri, cont_uri;
	struct ip_addr *uri_ia;
	union sockaddr_union uri_sau;
	unsigned int uri_port, dst_port, inv_port, cont_port, lastr_port;
	rte_t *last_r;
#ifdef TM_LOC_ACK_DO_REV_DNS
	struct ip_addr ia;
	struct hostent *he;
	char **alias;
#endif

#define PARSE_URI(_str_, _uri_) \
	do { \
		/* parse_uri() 0z the puri */ \
		if (parse_uri((_str_)->s, \
				(_str_)->len, _uri_) < 0) { \
			LM_ERR("failed to parse route body '%.*s'.\n", STR_FMT(_str_)); \
			return 0; \
		} \
	} while (0)

#define HAS_LR(_rte_) \
	({ \
		PARSE_URI(&(_rte_)->ptr->nameaddr.uri, &puri); \
		puri.lr.s; \
	})

#define URI_PORT(_puri_, _port) \
	do { \
		if (! (_port = uri2port(_puri_))) \
			return 0; \
	} while (0)

	/* examine the easy/fast & positive cases foremost */

	/* [1] check if 1st route lacks ;lr */
	LM_DBG("checking lack of ';lr' in 1st route.\n");
	if (! HAS_LR(rtset))
		return F_RB_NH_STRICT;
	topr_uri = puri; /* save 1st route's URI */

	/* [2] check if last route shows ;lr */
	LM_DBG("checking presence of ';lr' in last route.\n");
	for (last_r = rtset; last_r->next; last_r = last_r->next)
		/* scroll down to last route */
		;
	if (HAS_LR(last_r))
		return F_RB_NH_LOOSE;

	/* [3] 1st route has ;lr -> check if the destination of original INV
	 * equals the address provided by this route; if does -> loose */
	LM_DBG("checking INVITE's destination against its first route.\n");
	URI_PORT(&topr_uri, uri_port);
	if (! (dst_port = su_getport(&dst_inv->to)))
		return 0; /* not really expected */
	if (dst_port != uri_port)
		return F_RB_NH_STRICT;
	/* if 1st route contains an IP address, comparing it against .dst */
	if ((uri_ia = str2ip(&topr_uri.host))
			|| (uri_ia = str2ip6(&topr_uri.host))
			) {
		/* we have an IP address in route -> comparison can go swiftly */
		if (init_su(&uri_sau, uri_ia, uri_port) < 0)
			return 0; /* not really expected */
		if (su_cmp(&uri_sau, &dst_inv->to))
			/* ;lr and sent there */
			return F_RB_NH_LOOSE;
		else
			/* ;lr and NOT sent there (probably sent to RURI address) */
			return F_RB_NH_STRICT;
	} else {
		/*if 1st route contains a name, rev resolve the .dst and compare*/
		LM_INFO("Failed to decode string '%.*s' in route set element as IP"
				" address. Trying name resolution.\n",STR_FMT(&topr_uri.host));

	/* TODO: alternatively, rev name and compare against dest. IP.  */
#ifdef TM_LOC_ACK_DO_REV_DNS
		ia.af = 0;
		su2ip_addr(&ia, (void *)&dst_inv->to);
		if (! ia.af)
			return 0; /* not really expected */
		if ((he = rev_resolvehost(&ia))) {
			if ((strlen(he->h_name) == topr_uri.host.len) &&
					(memcmp(he->h_name, topr_uri.host.s,
							topr_uri.host.len) == 0))
				return F_RB_NH_LOOSE;
			for (alias = he->h_aliases; *alias; alias ++)
				if ((strlen(*alias) == topr_uri.host.len) &&
						(memcmp(*alias, topr_uri.host.s,
								topr_uri.host.len) == 0))
					return F_RB_NH_LOOSE;
			return F_RB_NH_STRICT;
		} else {
			LM_INFO("failed to resolve address '%s' to a name.\n",
					ip_addr2a(&ia));
		}
#endif
	}

	LM_WARN("failed to establish with certainty the type of next hop;"
			" trying an educated guess.\n");

	/* [4] compare (possibly updated) remote target to original RURI; if
	 * equal, a strict router's address wasn't filled in as RURI -> loose */
	LM_DBG("checking remote target against INVITE's RURI.\n");
	PARSE_URI(contact, &cont_uri);
	PARSE_URI(GET_RURI(orig_inv), &inv_ruri);
	URI_PORT(&cont_uri, cont_port);
	URI_PORT(&inv_ruri, inv_port);
	if ((cont_port == inv_port) && (cont_uri.host.len == inv_ruri.host.len) &&
			(memcmp(cont_uri.host.s, inv_ruri.host.s, cont_uri.host.len) == 0))
		return F_RB_NH_LOOSE;

	/* [5] compare (possibly updated) remote target to last route; if equal,
	 * strict router's address might have been filled as RURI and remote
	 * target appended to route set -> strict */
	LM_DBG("checking remote target against INVITE's last route.\n");
	PARSE_URI(&last_r->ptr->nameaddr.uri, &lastr_uri);
	URI_PORT(&lastr_uri, lastr_port);
	if ((cont_port == lastr_port) &&
			(cont_uri.host.len == lastr_uri.host.len) &&
			(memcmp(cont_uri.host.s, lastr_uri.host.s,
					lastr_uri.host.len) == 0))
		return F_RB_NH_STRICT;

	LM_WARN("failed to establish the type of next hop;"
			" assuming loose router.\n");
	return F_RB_NH_LOOSE;

#undef PARSE_URI
#undef HAS_LR
#undef URI_PORT
}
コード例 #24
0
/*! \brief
 * Loads contacts in destination set into "serial_fork" AVP in reverse
 * priority order and associated each contact with Q_FLAG telling if
 * contact is the last one in its priority class.  Finally, removes
 * all branches from destination set.
 */
int serialize_branches(struct sip_msg *msg, int clean_before )
{
	static struct serial_contact contacts[MAX_BRANCHES];
	int n, last, first, i, prev;
	str branch, *ruri;
	qvalue_t q, ruri_q;
	char *p;
	str dst_uri, path, enc_info;
	unsigned int flags;
	struct socket_info *sock_info;
	int_str val;
	int idx;

	/* Check if anything needs to be done */
	if (nr_branches == 0) {
		LM_DBG("nothing to do - no branches!\n");
		return 0;
	}

	ruri = GET_RURI(msg);
	ruri_q = get_ruri_q();
	flags = getb0flags();

	for (idx = 0; (branch.s = get_branch(idx,&branch.len,&q,0,0,0,0)); idx++) {
		if (q != ruri_q)
			break;
	}

	if (branch.s == 0) {
		LM_DBG("nothing to do - all same q!\n");
		return 0;
	}

	/* reset contact array */
	n = 0;

	/* Insert Request-URI to contact list */
	enc_info.len = 3 * sizeof(long)
			+ ruri->len + msg->dst_uri.len + msg->path_vec.len + 3;
	enc_info.s = (char*) pkg_malloc (enc_info.len);

	if (!enc_info.s) {
		LM_ERR("no pkg memory left\n");
		goto error; /* nothing to free here */
	}

	memset(enc_info.s, 0, enc_info.len);
	p = enc_info.s;

	LM_DBG("Msg information <%.*s,%.*s,%.*s,%d,%u>\n",
			ruri->len, ruri->s,
			msg->dst_uri.len, msg->dst_uri.s,
			msg->path_vec.len, msg->path_vec.s,
			ruri_q, flags);

	*((long*) p) = (long)msg->force_send_socket;
	p += sizeof(long);
	*((long*) p) = (long)flags;
	p += sizeof(long);
	*((long*) p) = (long)ruri_q;
	p += sizeof(long);

	memcpy(p , ruri->s, ruri->len);
	p += ruri->len + 1;
	memcpy(p, msg->dst_uri.s, msg->dst_uri.len);
	p += msg->dst_uri.len + 1;
	memcpy(p, msg->path_vec.s, msg->path_vec.len);

	contacts[n].enc_info = enc_info;
	contacts[n].q = ruri_q;
	contacts[n].next = -1;
	last = n;
	first = n;
	n++;

	/* Insert branch URIs to contact list in increasing q order */
	for (idx = 0;(branch.s = get_branch(idx, &branch.len, &q,
					&dst_uri, &path, &flags, &sock_info)); idx++){

		enc_info.len = 3 * sizeof(long)
						+ branch.len + dst_uri.len + path.len + 3;
		enc_info.s = (char*) pkg_malloc (enc_info.len);

		if (!enc_info.s) {
			LM_ERR("no pkg memory left\n");
			goto error_free;
		}

		memset(enc_info.s, 0, enc_info.len);
		p = enc_info.s;

		LM_DBG("Branch information <%.*s,%.*s,%.*s,%d,%u>\n", 
				branch.len, branch.s,
				dst_uri.len, dst_uri.s,
				path.len, path.s,
				q, flags);

		*((long*) p) = (long)sock_info;
		p += sizeof(long);
		*((long*) p) = (long)flags;
		p += sizeof(long);
		*((long*) p) = (long)q;
		p += sizeof(long);

		memcpy(p , branch.s, branch.len);
		p += branch.len + 1;
		memcpy(p, dst_uri.s, dst_uri.len);
		p += dst_uri.len + 1;
		memcpy(p, path.s, path.len);

		contacts[n].enc_info = enc_info;
		contacts[n].q = q;

		/* insert based on q */
		for (i = first, prev=-1; i != -1 && contacts[i].q < q; prev=i,i = contacts[i].next);

		if (i == -1) {
			/* append */
			last = contacts[last].next = n;
			contacts[n].next = -1;
		} else {
			if (i == first) {
				/* first element */
				contacts[n].next = first;
				first = n;
			} else {
				/* before pos i */
				contacts[n].next = contacts[prev].next;
				contacts[prev].next = n;
			}
		}

		n++;
	}

	/* Assign values for q_flags */
	for (i = first; contacts[i].next != -1; i = contacts[i].next) {
		if (contacts[i].q < contacts[contacts[i].next].q)
			contacts[contacts[i].next].q_flag = Q_FLAG;
		else
			contacts[contacts[i].next].q_flag = 0;
	}

	if (clean_before)
		destroy_avps( 0/*type*/, serial_avp, 1/*all*/);

	/* Add contacts to "contacts" AVP */
	for (i = first; i != -1; i = contacts[i].next) {
		val.s = contacts[i].enc_info;

		if (add_avp( AVP_VAL_STR|contacts[i].q_flag, serial_avp, val)) {
			LM_ERR("failed to add avp\n");
			goto error_free;
		}

		pkg_free(contacts[i].enc_info.s);
		contacts[i].enc_info.s = NULL;
	}

	/* Clear all branches */
	clear_branches();

	return 0;
error_free:
	for( i=0 ; i<n ; i++) {
		if (contacts[i].enc_info.s)
			pkg_free(contacts[i].enc_info.s);
	}
error:
	return -1;
}
コード例 #25
0
ファイル: async.c プロジェクト: ionutrazvanionita/opensips
/* function triggered from reactor in order to continue the processing
 */
int t_resume_async(int *fd, void *param)
{
    static struct sip_msg faked_req;
    static struct ua_client uac;
    async_ctx *ctx = (async_ctx *)param;
    struct cell *backup_t;
    struct cell *backup_cancelled_t;
    struct cell *backup_e2eack_t;
    struct usr_avp **backup_list;
    struct socket_info* backup_si;
    struct cell *t= ctx->t;
    int route;

    LM_DBG("resuming on fd %d, transaction %p \n",*fd, t);

    if (current_processing_ctx) {
        LM_CRIT("BUG - a context already set!\n");
        abort();
    }

    /* prepare for resume route */
    uac.br_flags = getb0flags( t->uas.request ) ;
    uac.uri = *GET_RURI( t->uas.request );
    if (!fake_req( &faked_req /* the fake msg to be built*/,
                   t->uas.request, /* the template msg saved in transaction */
                   &t->uas, /*the UAS side of the transaction*/
                   &uac, /* the fake UAC */
                   1 /* copy dst_uri too */)
       ) {
        LM_ERR("fake_req failed\n");
        return 0;
    }

    /* enviroment setting */
    current_processing_ctx = ctx->msg_ctx;
    backup_t = get_t();
    backup_e2eack_t = get_e2eack_t();
    backup_cancelled_t = get_cancelled_t();
    /* fake transaction */
    set_t( t );
    set_cancelled_t(ctx->cancelled_t);
    set_e2eack_t(ctx->e2eack_t);
    reset_kr();
    set_kr(ctx->kr);
    /* make available the avp list from transaction */
    backup_list = set_avp_list( &t->user_avps );
    /* set default send address to the saved value */
    backup_si = bind_address;
    bind_address = t->uac[0].request.dst.send_sock;

    async_status = ASYNC_DONE; /* assume default status as done */
    /* call the resume function in order to read and handle data */
    return_code = ctx->resume_f( *fd, &faked_req, ctx->resume_param );
    if (async_status==ASYNC_CONTINUE) {
        /* do not run the resume route */
        goto restore;
    } else if (async_status==ASYNC_CHANGE_FD) {
        if (return_code<0) {
            LM_ERR("ASYNC_CHANGE_FD: given file descriptor shall be positive!\n");
            goto restore;
        } else if (return_code > 0 && return_code == *fd) {
            /*trying to add the same fd; shall continue*/
            LM_CRIT("You are trying to replace the old fd with the same fd!"
                    "Will act as in ASYNC_CONTINUE!\n");
            goto restore;
        }

        /* remove the old fd from the reactor */
        reactor_del_reader( *fd, -1, IO_FD_CLOSING);
        *fd=return_code;

        /* insert the new fd inside the reactor */
        if (reactor_add_reader( *fd, F_SCRIPT_ASYNC, RCT_PRIO_ASYNC, (void*)ctx)<0 ) {
            LM_ERR("failed to add async FD to reactor -> act in sync mode\n");
            do {
                return_code = ctx->resume_f( *fd, &faked_req, ctx->resume_param );
                if (async_status == ASYNC_CHANGE_FD)
                    *fd=return_code;
            } while(async_status==ASYNC_CONTINUE||async_status==ASYNC_CHANGE_FD);
            goto route;
        }

        /* changed fd; now restore old state */
        goto restore;
    }

    /* remove from reactor, we are done */
    reactor_del_reader( *fd, -1, IO_FD_CLOSING);

route:
    if (async_status == ASYNC_DONE_CLOSE_FD)
        close(*fd);

    /* run the resume_route (some type as the original one) */
    swap_route_type(route, ctx->route_type);
    run_resume_route( ctx->resume_route, &faked_req);
    set_route_type(route);

    /* no need for the context anymore */
    shm_free(ctx);

    /* free also the processing ctx if still set
     * NOTE: it may become null if inside the run_resume_route
     * another async jump was made (and context attached again
     * to transaction) */
    if (current_processing_ctx) {
        context_destroy(CONTEXT_GLOBAL, current_processing_ctx);
        pkg_free(current_processing_ctx);
    }

restore:
    /* restore original environment */
    set_t(backup_t);
    set_cancelled_t(backup_cancelled_t);
    set_e2eack_t(backup_e2eack_t);
    /* restore original avp list */
    set_avp_list( backup_list );
    bind_address = backup_si;

    free_faked_req( &faked_req, t);
    current_processing_ctx = NULL;

    return 0;
}
コード例 #26
0
ファイル: sterman.c プロジェクト: AndreiPlesa/opensips
/*
 * This function creates and submits aaa authentication request as per
 * draft-sterman-aaa-sip-00.txt.  In addition, _user parameter is included
 * in the request as value of a SER specific attribute type SIP-URI-User,
 * which can be be used as a check item in the request.  Service type of
 * the request is Authenticate-Only.
 */
int aaa_authorize_sterman(struct sip_msg* _msg, dig_cred_t* _cred, str* _method, str* _user)
{
	aaa_message *send, *received;
	uint32_t service;
	str method, user, user_name;
	str *ruri;

	send = received = NULL;

	if (!(_cred && _method && _user)) {
		LM_ERR("invalid parameter value\n");
		return -1;
	}

	method = *_method;
	user = *_user;

	if ((send = proto.create_aaa_message(conn, AAA_AUTH)) == NULL) {
		LM_ERR("failed to create new aaa message for auth\n");
		return -1;
	}

	/*
	 * Add all the user digest parameters according to the qop defined.
	 * Most devices tested only offer support for the simplest digest.
	 */
	if (_cred->username.domain.len) {
		if (proto.avp_add(conn, send, &attrs[A_USER_NAME], _cred->username.whole.s, _cred->username.whole.len, 0)) {
			LM_ERR("unable to add User-Name attribute\n");
			goto err;
		}
	} else {
		user_name.len = _cred->username.user.len + _cred->realm.len + 1;
		user_name.s = pkg_malloc(user_name.len);
		if (!user_name.s) {
			LM_ERR("no pkg memory left\n");
			return -3;
		}
		memcpy(user_name.s, _cred->username.whole.s, _cred->username.whole.len);
		user_name.s[_cred->username.whole.len] = '@';
		memcpy(user_name.s + _cred->username.whole.len + 1, _cred->realm.s,
			_cred->realm.len);
		if (proto.avp_add(conn, send, &attrs[A_USER_NAME], user_name.s,
					user_name.len, 0)) {
			LM_ERR("unable to add User-Name attribute\n");
			pkg_free(user_name.s);
			goto err;
		}
		pkg_free(user_name.s);
	}

	if (proto.avp_add(conn, send, &attrs[A_DIGEST_USER_NAME],
				_cred->username.whole.s, _cred->username.whole.len, 0)) {
		LM_ERR("unable to add Digest-User-Name attribute\n");
		goto err;
	}

	if (proto.avp_add(conn, send, &attrs[A_DIGEST_REALM], _cred->realm.s,
				_cred->realm.len, 0)) {
		LM_ERR("unable to add Digest-Realm attribute\n");
		goto err;
	}
	if (proto.avp_add(conn, send, &attrs[A_DIGEST_NONCE], _cred->nonce.s,
				_cred->nonce.len, 0)) {
		LM_ERR("unable to add Digest-Nonce attribute\n");
		goto err;
	}

	if (use_ruri_flag < 0 || isflagset(_msg, use_ruri_flag) != 1) {
		ruri = &_cred->uri;
	} else {
		ruri = GET_RURI(_msg);
	}
	if (proto.avp_add(conn, send, &attrs[A_DIGEST_URI], ruri->s,
				ruri->len, 0)) {
		LM_ERR("unable to add Digest-URI attribute\n");
		goto err;
	}

	if (proto.avp_add(conn, send, &attrs[A_DIGEST_METHOD], method.s,
				method.len, 0)) {
		LM_ERR("unable to add Digest-Method attribute\n");
		goto err;
	}

	/*
	 * Add the additional authentication fields according to the QOP.
	 */
	if (_cred->qop.qop_parsed == QOP_AUTH_D) {
		if (proto.avp_add(conn, send, &attrs[A_DIGEST_QOP], "auth", 4, 0)) {
			LM_ERR("unable to add Digest-QOP attribute\n");
			goto err;
		}
		if (proto.avp_add(conn, send, &attrs[A_DIGEST_NONCE_COUNT],
				_cred->nc.s, _cred->nc.len, 0)) {
			LM_ERR("unable to add Digest-CNonce-Count attribute\n");
			goto err;
		}
		if (proto.avp_add(conn, send, &attrs[A_DIGEST_CNONCE],
				_cred->cnonce.s, _cred->cnonce.len, 0)) {
			LM_ERR("unable to add Digest-CNonce attribute\n");
			goto err;
		}
	} else if (_cred->qop.qop_parsed == QOP_AUTHINT_D) {
		if (proto.avp_add(conn, send, &attrs[A_DIGEST_QOP],
				"auth-int", 8, 0)) {
			LM_ERR("unable to add Digest-QOP attribute\n");
			goto err;
		}
		if (proto.avp_add(conn, send, &attrs[A_DIGEST_NONCE_COUNT],
				_cred->nc.s, _cred->nc.len, 0)) {
			LM_ERR("unable to add Digest-Nonce-Count attribute\n");
			goto err;
		}
		if (proto.avp_add(conn, send, &attrs[A_DIGEST_CNONCE],
				_cred->cnonce.s, _cred->cnonce.len, 0)) {
			LM_ERR("unable to add Digest-CNonce attribute\n");
			goto err;
		}
		if (proto.avp_add(conn, send, &attrs[A_DIGEST_BODY_DIGEST],
				_cred->opaque.s, _cred->opaque.len, 0)) {
			LM_ERR("unable to add Digest-Body-Digest attribute\n");
			goto err;
		}
	} else  {
		/* send nothing for qop == "" */
	}

	/* Add the response... What to calculate against... */
	if (proto.avp_add(conn, send, &attrs[A_DIGEST_RESPONSE],
			_cred->response.s, _cred->response.len, 0)) {
		LM_ERR("unable to add Digest-Response attribute\n");
		goto err;
	}

	/* Indicate the service type, Authenticate only in our case */
	service = vals[V_SIP_SESSION].value;
	if (proto.avp_add(conn, send, &attrs[A_SERVICE_TYPE], &service, -1, 0)) {
		LM_ERR("unable to add Service-Type attribute\n");
		goto err;
	}

	/* Add SIP URI as a check item */
	if (proto.avp_add(conn, send, &attrs[A_SIP_URI_USER], user.s,user.len,0)) {
		LM_ERR("unable to add Sip-URI-User attribute\n");
		goto err;
	}

	/* Add CALL-ID in Acct-Session-Id Attribute */
	if ( _msg->callid==NULL &&
		(parse_headers(_msg, HDR_CALLID_F, 0)==-1 || _msg->callid==NULL)  ) {
		LM_ERR("msg parsing failed or callid not present");
		goto err;
	}
	if (proto.avp_add(conn, send, &attrs[A_ACCT_SESSION_ID],
				_msg->callid->body.s, _msg->callid->body.len, 0)) {
		LM_ERR("unable to add CALL-ID attribute\n");
		goto err;
	}

	if (attrs[A_CISCO_AVPAIR].name != NULL) {
		if (add_cisco_vsa(&send, _msg)) {
			goto err;
		}
	}

	/* Send request */
	if (!proto.send_aaa_request(conn, send, &received)) {
		LM_DBG("Success\n");
		proto.destroy_aaa_message(conn, send);
		proto.destroy_aaa_message(conn, received);
		return 1;
	} else {
#ifdef REJECT_RC
/*		if (i == REJECT_RC) {
			LM_DBG("Failure\n");
			goto err;
		}*/
#endif
		LM_ERR("authorization failed\n");
	}

err:
	if (send)
		proto.destroy_aaa_message(conn, send);
	if (received)
		proto.destroy_aaa_message(conn, received);
	return -1;
}
コード例 #27
0
ファイル: t_fwd.c プロジェクト: rrb3942/opensips
/* function returns:
 *       1 - forward successful
 *      -1 - error during forward
 */
int t_forward_nonack( struct cell *t, struct sip_msg* p_msg ,
						struct proxy_l * proxy, int reset_bcounter, int locked)
{
	str reply_reason_487 = str_init("Request Terminated");
	str backup_uri;
	str backup_dst;
	int branch_ret, lowest_ret;
	str current_uri;
	branch_bm_t  added_branches;
	int i, q;
	struct cell *t_invite;
	int success_branch;
	str dst_uri;
	struct socket_info *bk_sock;
	unsigned int br_flags, bk_bflags;
	int idx;
	str path;
	str bk_path;

	/* make -Wall happy */
	current_uri.s=0;

	/* before doing enything, update the t flags from msg */
	t->uas.request->flags = p_msg->flags;

	if (p_msg->REQ_METHOD==METHOD_CANCEL) {
		t_invite=t_lookupOriginalT(  p_msg );
		if (t_invite!=T_NULL_CELL) {
			t_invite->flags |= T_WAS_CANCELLED_FLAG;
			cancel_invite( p_msg, t, t_invite, locked );
			return 1;
		}
	}

	/* do not forward requests which were already cancelled*/
	if (no_new_branches(t)) {
		LM_INFO("discarding fwd for a 6xx transaction\n");
		ser_error = E_NO_DESTINATION;
		return -1;
	}
	if (was_cancelled(t)) {
		/* is this the first attempt of sending a branch out ? */
		if (t->nr_of_outgoings==0) {
			/* if no other signalling was performed on the transaction
			 * and the transaction was already canceled, better
			 * internally generate the 487 reply here */
			if (locked)
				t_reply_unsafe( t, p_msg , 487 , &reply_reason_487);
			else
				t_reply( t, p_msg , 487 , &reply_reason_487);
		}
		LM_INFO("discarding fwd for a cancelled transaction\n");
		ser_error = E_NO_DESTINATION;
		return -1;
	}

	/* backup current uri, sock and flags... add_uac changes it */
	backup_uri = p_msg->new_uri;
	backup_dst = p_msg->dst_uri;
	bk_sock = p_msg->force_send_socket;
	bk_path = p_msg->path_vec;
	bk_bflags = p_msg->ruri_bflags;
	/* advertised address/port are not changed */

	/* check if the UAS retranmission port needs to be updated */
	if ( (p_msg->msg_flags ^ t->uas.request->msg_flags) & FL_FORCE_RPORT )
		su_setport( &t->uas.response.dst.to, p_msg->rcv.src_port );

	/* if no more specific error code is known, use this */
	lowest_ret=E_BUG;
	/* branches added */
	added_branches=0;
	/* branch to begin with */
	if (reset_bcounter) {
		t->first_branch=t->nr_of_outgoings;
		/* check if the previous branch is a PHONY one and if yes
		 * keep it in the set of active branches; that means the 
		 * transaction had a t_wait_for_new_branches() call prior to relay() */
		if ( t->first_branch>0 &&
		(t->uac[t->first_branch-1].flags & T_UAC_IS_PHONY) )
			t->first_branch--;
	}

	/* as first branch, use current uri */
	current_uri = *GET_RURI(p_msg);
	branch_ret = add_uac( t, p_msg, &current_uri, &backup_dst,
		getb0flags(p_msg), &p_msg->path_vec, proxy);
	if (branch_ret>=0)
		added_branches |= 1<<branch_ret;
	else
		lowest_ret=branch_ret;

	/* ....and now add the remaining additional branches */
	for( idx=0; (current_uri.s=get_branch( idx, &current_uri.len, &q,
	&dst_uri, &path, &br_flags, &p_msg->force_send_socket))!=0 ; idx++ ) {
		branch_ret = add_uac( t, p_msg, &current_uri, &dst_uri,
			br_flags, &path, proxy);
		/* pick some of the errors in case things go wrong;
		   note that picking lowest error is just as good as
		   any other algorithm which picks any other negative
		   branch result */
		if (branch_ret>=0)
			added_branches |= 1<<branch_ret;
		else
			lowest_ret=branch_ret;
	}
	/* consume processed branches */
	clear_branches();

	/* restore original stuff */
	p_msg->new_uri=backup_uri;
	p_msg->parsed_uri_ok = 0;/* just to be sure; add_uac may parse other uris*/
	p_msg->dst_uri = backup_dst;
	p_msg->force_send_socket = bk_sock;
	p_msg->path_vec = bk_path;
	p_msg->ruri_bflags = bk_bflags;

	/* update on_branch, _only_ if modified, otherwise it overwrites
	 * whatever it is already in the transaction */
	if (get_on_branch())
		t->on_branch = get_on_branch();

	/* update flags, if changed in branch route */
	t->uas.request->flags = p_msg->flags;

	/* things went wrong ... no new branch has been fwd-ed at all */
	if (added_branches==0) {
		LM_ERR("failure to add branches\n");
		ser_error = lowest_ret;
		return lowest_ret;
	}

	/* send them out now */
	success_branch=0;
	for (i=t->first_branch; i<t->nr_of_outgoings; i++) {
		if (added_branches & (1<<i)) {

			if (t->uac[i].br_flags & tcp_no_new_conn_bflag)
				tcp_no_new_conn = 1;

			do {
				if (check_blacklists( t->uac[i].request.dst.proto,
				&t->uac[i].request.dst.to,
				t->uac[i].request.buffer.s,
				t->uac[i].request.buffer.len)) {
					LM_DBG("blocked by blacklists\n");
					ser_error=E_IP_BLOCKED;
				} else {
					run_trans_callbacks(TMCB_PRE_SEND_BUFFER, t, p_msg, 0, i);

					if (SEND_BUFFER( &t->uac[i].request)==0) {
						ser_error = 0;
						break;
					}

					LM_ERR("sending request failed\n");
					ser_error=E_SEND;
				}
				/* get next dns entry */
				if ( t->uac[i].proxy==0 ||
				get_next_su( t->uac[i].proxy, &t->uac[i].request.dst.to,
				(ser_error==E_IP_BLOCKED)?0:1)!=0 )
					break;
				t->uac[i].request.dst.proto = t->uac[i].proxy->proto;
				/* update branch */
				if ( update_uac_dst( p_msg, &t->uac[i] )!=0)
					break;
			}while(1);

			tcp_no_new_conn = 0;

			if (ser_error) {
				shm_free(t->uac[i].request.buffer.s);
				t->uac[i].request.buffer.s = NULL;
				t->uac[i].request.buffer.len = 0;
				continue;
			}

			success_branch++;

			start_retr( &t->uac[i].request );
			set_kr(REQ_FWDED);

			/* successfully sent out -> run callbacks */
			if ( has_tran_tmcbs( t, TMCB_REQUEST_BUILT|TMCB_MSG_SENT_OUT) ) {
				set_extra_tmcb_params( &t->uac[i].request.buffer,
					&t->uac[i].request.dst);
				run_trans_callbacks( TMCB_REQUEST_BUILT|TMCB_MSG_SENT_OUT, t,
					p_msg, 0, 0);
			}

		}
	}

	return (success_branch>0)?1:-1;
}
コード例 #28
0
ファイル: pua_dialoginfo.c プロジェクト: NormB/opensips
int dialoginfo_set(struct sip_msg* msg, char* flag_pv, char* str2)
{
	struct dlg_cell * dlg;
	str peer_uri= {0, 0}; /* constructed from TO display name and RURI */
	struct to_body* from, peer_to_body, FROM, *to;
	str* ruri;
	int len =0,ret=-1;
	char flag= DLG_PUB_AB;
	static char buf[256];
	int buf_len= 255;
	str flag_str;
	char caller_buf[256], callee_buf[256];
	pv_value_t tok;

	peer_to_body.param_lst = FROM.param_lst = NULL;

	if (msg->REQ_METHOD != METHOD_INVITE)
		return 1;

	if(dlg_api.create_dlg(msg,0)< 0)
	{
		LM_ERR("Failed to create dialog\n");
		return -1;
	}

	dlg = dlg_api.get_dlg();

	LM_DBG("new INVITE dialog created: from=%.*s\n",
		dlg->from_uri.len, dlg->from_uri.s);

	from = get_from(msg);
	/* if defined overwrite */
	if(caller_spec_param.s) /* if parameter defined */
	{
		memset(&tok, 0, sizeof(pv_value_t));
		if(pv_get_spec_value(msg, &caller_spec, &tok) < 0)  /* if value set */
		{
			LM_ERR("Failed to get caller value\n");
			return -1;
		}
		if(tok.flags&PV_VAL_STR)
		{
			str caller_str;
			if(tok.rs.len + CRLF_LEN > buf_len)
			{
				LM_ERR("Buffer overflow");
				return -1;
			}
			trim(&tok.rs);
			memcpy(caller_buf, tok.rs.s, tok.rs.len);
			len = tok.rs.len;
			if(strncmp(tok.rs.s+len-CRLF_LEN, CRLF, CRLF_LEN))
			{
				memcpy(caller_buf + len, CRLF, CRLF_LEN);
				len+= CRLF_LEN;
			}

			parse_to(caller_buf, caller_buf+len , &FROM);
			if(FROM.error != PARSE_OK)
			{
				LM_ERR("Failed to parse caller specification - not a valid uri\n");
				goto end;
			}
			from = &FROM;
			caller_str.s = caller_buf;
			caller_str.len = len;
			LM_DBG("caller: %*s- len= %d\n", len, caller_buf, len);
			/* store caller in a dlg variable */
			if(dlg_api.store_dlg_value(dlg, &entity_dlg_var, &caller_str)< 0)
			{
				LM_ERR("Failed to store dialog ruri\n");
				goto end;
			}
		}
	}

	peer_uri.s = callee_buf;
	if(callee_spec_param.s)
	{
		memset(&tok, 0, sizeof(pv_value_t));
		if(pv_get_spec_value(msg, &callee_spec, &tok) < 0)
		{
			LM_ERR("Failed to get callee value\n");
			goto end;
		}
		if(tok.flags&PV_VAL_STR)
		{
			if(tok.rs.len + CRLF_LEN > buf_len)
			{
				LM_ERR("Buffer overflow");
				goto end;
			}
			trim(&tok.rs);
			memcpy(peer_uri.s, tok.rs.s, tok.rs.len);
			len = tok.rs.len;
			if(strncmp(tok.rs.s+len-CRLF_LEN, CRLF, CRLF_LEN))
			{
				memcpy(peer_uri.s + len, CRLF, CRLF_LEN);
				len+= CRLF_LEN;
			}
			peer_uri.len = len;
		}
		else
			goto default_callee;
	}
	else
	{
default_callee:
		ruri = GET_RURI(msg);
		to = get_to(msg);
		len= to->display.len + 2 + ruri->len + CRLF_LEN;
		if(len > buf_len)
		{
			LM_ERR("Buffer overflow\n");
			goto end;
		}
		len = 0;
		if(to->display.len && to->display.s)
		{
			memcpy(peer_uri.s, to->display.s, to->display.len);
			peer_uri.s[to->display.len]='<';
			len = to->display.len + 1;
		}
		memcpy(peer_uri.s + len, ruri->s, ruri->len);
		len+= ruri->len;
		if(to->display.len)
		{
			peer_uri.s[len++]='>';
		}
		memcpy(peer_uri.s + len, CRLF, CRLF_LEN);
		len+= CRLF_LEN;
		peer_uri.len = len;
	}
	LM_DBG("Peer uri = %.*s\n", peer_uri.len, peer_uri.s);

	parse_to(peer_uri.s, peer_uri.s+peer_uri.len, &peer_to_body);
	if(peer_to_body.error != PARSE_OK)
	{
		LM_ERR("Failed to peer uri [%.*s]\n", peer_uri.len, peer_uri.s);
		goto end;
	}

	/* store peer uri in dialog structure */
	if(dlg_api.store_dlg_value(dlg, &peer_dlg_var, &peer_uri)< 0)
	{
		LM_ERR("Failed to store dialog ruri\n");
		goto end;
	}

	/* store flag, if defined  */
	if(flag_pv)
	{
		if(pv_printf(msg, (pv_elem_t*)flag_pv, buf, &buf_len)<0)
		{
			LM_ERR("cannot print the format\n");
			goto end;
		}

		if(!check_flag(buf, buf_len))
		{
			LM_ERR("Wrong value for flag\n");
			goto end;
		}
		flag = buf[0];
		flag_str.s = buf;
		flag_str.len = buf_len;
		if(dlg_api.store_dlg_value(dlg, &flag_dlg_var, &flag_str)< 0)
		{
			LM_ERR("Failed to store dialog ruri\n");
			goto end;
		}
	}

	/* register dialog callbacks which triggers sending PUBLISH */
	if (dlg_api.register_dlgcb(dlg,
		DLGCB_FAILED| DLGCB_CONFIRMED | DLGCB_TERMINATED | DLGCB_EXPIRED |
		DLGCB_RESPONSE_WITHIN | DLGCB_EARLY,
		__dialog_sendpublish, 0, 0) != 0) {
		LM_ERR("cannot register callback for interesting dialog types\n");
		goto end;
	}

#ifdef PUA_DIALOGINFO_DEBUG
	/* dialog callback testing (registered last to be executed first) */
	if (dlg_api.register_dlgcb(dlg,
		DLGCB_FAILED| DLGCB_CONFIRMED | DLGCB_REQ_WITHIN | DLGCB_TERMINATED |
		DLGCB_EXPIRED | DLGCB_EARLY | DLGCB_RESPONSE_FWDED |
		DLGCB_RESPONSE_WITHIN  | DLGCB_MI_CONTEXT | DLGCB_DESTROY,
		__dialog_cbtest, NULL, NULL) != 0) {
		LM_ERR("cannot register callback for all dialog types\n");
		goto end;
	}
#endif

        if(publish_on_trying) {
	        if(flag == DLG_PUB_A || flag == DLG_PUB_AB)
		        dialog_publish("trying", from, &peer_to_body, &(dlg->callid), 1, DEFAULT_CREATED_LIFETIME, 0, 0);

	        if(flag == DLG_PUB_B || flag == DLG_PUB_AB)
		        dialog_publish("trying", &peer_to_body, from, &(dlg->callid), 0, DEFAULT_CREATED_LIFETIME, 0, 0);
        }

	ret=1;
end:
	if (peer_to_body.param_lst)
		free_to_params(&peer_to_body);
	if (FROM.param_lst)
		free_to_params(&FROM);
	return ret;
}
コード例 #29
0
ファイル: uac.c プロジェクト: AndreiPlesa/opensips
/*
 * Send a request using data from the dialog structure
 */
int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
				transaction_cb cb, void* cbp,release_tmcb_param release_func)
{
	union sockaddr_union to_su, new_to_su;
	struct cell *new_cell;
	struct cell *backup_cell;
	struct retr_buf *request;
	static struct sip_msg *req;
	struct usr_avp **backup;
	char *buf, *buf1;
	int buf_len, buf_len1;
	int ret, flags, sflag_bk;
	int backup_route_type;
	int sip_msg_len;
	unsigned int hi;
	struct socket_info *new_send_sock;
	str h_to, h_from, h_cseq, h_callid;
	struct proxy_l *proxy, *new_proxy;
	unsigned short dst_changed;

	ret=-1;

	/*** added by dcm
	 * - needed by external ua to send a request within a dlg
	 */
	if(!dialog->hooks.next_hop && w_calculate_hooks(dialog)<0)
		goto error3;

	if(dialog->obp.s)
		dialog->hooks.next_hop = &dialog->obp;

	LM_DBG("next_hop=<%.*s>\n",dialog->hooks.next_hop->len,
			dialog->hooks.next_hop->s);

	/* calculate the socket corresponding to next hop */
	proxy = uri2proxy( dialog->hooks.next_hop,
		dialog->send_sock ? dialog->send_sock->proto : PROTO_NONE );
	if (proxy==0)  {
		ret=E_BAD_ADDRESS;
		goto error3;
	}
	/* use the first address */
	hostent2su( &to_su,
		&proxy->host, proxy->addr_idx, proxy->port ? proxy->port:SIP_PORT);

	/* check/discover the send socket */
	if (dialog->send_sock) {
		/* if already set, the protocol of send sock must have the 
		   the same type as the proto required by destination URI */
		if (proxy->proto != dialog->send_sock->proto)
			dialog->send_sock = NULL;
	}
	if (dialog->send_sock==NULL) {
		/* get the send socket */
		dialog->send_sock = get_send_socket( NULL/*msg*/, &to_su, proxy->proto);
		if (!dialog->send_sock) {
			LM_ERR("no corresponding socket for af %d\n", to_su.s.sa_family);
			ser_error = E_NO_SOCKET;
			goto error2;
		}
	}
	LM_DBG("sending socket is %.*s \n",
		dialog->send_sock->name.len,dialog->send_sock->name.s);


	/* ***** Create TRANSACTION and all related  ***** */
	new_cell = build_cell( NULL/*msg*/, 1/*full UAS clone*/);
	if (!new_cell) {
		ret=E_OUT_OF_MEM;
		LM_ERR("short of cell shmem\n");
		goto error2;
	}

	/* pass the transaction flags from dialog to transaction */
	new_cell->flags |= dialog->T_flags;

	/* add the callback the transaction for LOCAL_COMPLETED event */
	flags = TMCB_LOCAL_COMPLETED;
	/* Add also TMCB_LOCAL_RESPONSE_OUT if provisional replies are desired */
	if (pass_provisional_replies || pass_provisional(new_cell))
		flags |= TMCB_LOCAL_RESPONSE_OUT;
	if(cb && insert_tmcb(&(new_cell->tmcb_hl),flags,cb,cbp,release_func)!=1){
		ret=E_OUT_OF_MEM;
		LM_ERR("short of tmcb shmem\n");
		goto error2;
	}

	if (method->len==INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN)==0)
		new_cell->flags |= T_IS_INVITE_FLAG;
	new_cell->flags |= T_IS_LOCAL_FLAG;

	request = &new_cell->uac[0].request;
	if (dialog->forced_to_su.s.sa_family == AF_UNSPEC)
		request->dst.to = to_su;
	else
		request->dst.to = dialog->forced_to_su;
	request->dst.send_sock = dialog->send_sock;
	request->dst.proto = dialog->send_sock->proto;
	request->dst.proto_reserved1 = 0;

	hi=dlg2hash(dialog);
	LOCK_HASH(hi);
	insert_into_hash_table_unsafe(new_cell, hi);
	UNLOCK_HASH(hi);

	/* copy AVPs into transaction */
	new_cell->user_avps = dialog->avps;
	dialog->avps = NULL;


	/* ***** Create the message buffer ***** */
	buf = build_uac_req(method, headers, body, dialog, 0, new_cell, &buf_len);
	if (!buf) {
		LM_ERR("failed to build message\n");
		ret=E_OUT_OF_MEM;
		goto error1;
	}

	if (local_rlist.a) {
		LM_DBG("building sip_msg from buffer\n");
		req = buf_to_sip_msg(buf, buf_len, dialog);
		if (req==NULL) {
			LM_ERR("failed to build sip_msg from buffer\n");
		} else {
			/* set this transaction as active one */
			backup_cell = get_t();
			set_t( new_cell );
			/* set transaction AVP list */
			backup = set_avp_list( &new_cell->user_avps );
			/* backup script flags */
			sflag_bk = getsflags();
			/* disable parallel forking */
			set_dset_state( 0 /*disable*/);

			/* run the route */
			swap_route_type( backup_route_type, LOCAL_ROUTE);
			run_top_route( local_rlist.a, req);
			set_route_type( backup_route_type );

			/* transfer current message context back to t */
			new_cell->uac[0].br_flags = getb0flags(req);
			/* restore the prevoius active transaction */
			set_t( backup_cell );

			set_dset_state( 1 /*enable*/);
			setsflagsval(sflag_bk);
			set_avp_list( backup );

			/* check for changes - if none, do not regenerate the buffer */
			dst_changed = 1;
			if (req->new_uri.s || req->force_send_socket!=dialog->send_sock ||
			req->dst_uri.len != dialog->hooks.next_hop->len ||
			memcmp(req->dst_uri.s,dialog->hooks.next_hop->s,req->dst_uri.len) ||
			(dst_changed=0)==0 || req->add_rm || req->body_lumps){

				new_send_sock = NULL;
				/* do we also need to change the destination? */
				if (dst_changed) {
					/* calculate the socket corresponding to next hop */
					new_proxy = uri2proxy(
						req->dst_uri.s ? &(req->dst_uri) : &req->new_uri,
						PROTO_NONE );
					if (new_proxy==0)
						goto abort_update;
					/* use the first address */
					hostent2su( &new_to_su,
						&new_proxy->host, new_proxy->addr_idx,
						new_proxy->port ? new_proxy->port:SIP_PORT);
					/* get the send socket */
					new_send_sock = get_send_socket( req, &new_to_su,
						new_proxy->proto);
					if (!new_send_sock) {
						free_proxy( new_proxy );
						pkg_free( new_proxy );
						LM_ERR("no socket found for the new destination\n");
						goto abort_update;
					}
				}

				/* if interface change, we need to re-build the via */
				if (new_send_sock && new_send_sock != dialog->send_sock) {
					LM_DBG("Interface change in local route -> "
						"rebuilding via\n");
					if (!del_lump(req,req->h_via1->name.s - req->buf,
					req->h_via1->len,0)) {
						LM_ERR("Failed to remove initial via \n");
						goto abort_update;
					}

					memcpy(req->add_to_branch_s,req->via1->branch->value.s,
						req->via1->branch->value.len);
					req->add_to_branch_len = req->via1->branch->value.len;

					/* update also info about new destination and send sock */
					dialog->send_sock = new_send_sock;
					free_proxy( proxy );
					pkg_free( proxy );
					proxy = new_proxy;
					request->dst.send_sock = new_send_sock;
					request->dst.proto = new_send_sock->proto;
					request->dst.proto_reserved1 = 0;

					/* build the shm buffer now */
					set_init_lump_flags(LUMPFLAG_BRANCH);
					buf1 = build_req_buf_from_sip_req(req,
						(unsigned int*)&buf_len1,
						new_send_sock, new_send_sock->proto,
						MSG_TRANS_SHM_FLAG);
					reset_init_lump_flags();
					del_flaged_lumps( &req->add_rm, LUMPFLAG_BRANCH);

				} else {

					LM_DBG("Change in local route -> rebuilding buffer\n");
					/* build the shm buffer now */
					buf1 = build_req_buf_from_sip_req(req,
						(unsigned int*)&buf_len1,
						dialog->send_sock, dialog->send_sock->proto,
						MSG_TRANS_SHM_FLAG|MSG_TRANS_NOVIA_FLAG);
					/* now as it used, hide the original VIA header */
					del_lump(req,req->h_via1->name.s - req->buf,
						req->h_via1->len, 0);

				}

				if (!buf1) {
					LM_ERR("no more shm mem\n");
					/* keep original buffer */
					goto abort_update;
				}
				/* update shortcuts */
				if(!req->add_rm && !req->new_uri.s) {
					/* headers are not affected, simply tranlate */
					new_cell->from.s = new_cell->from.s - buf + buf1;
					new_cell->to.s = new_cell->to.s - buf + buf1;
					new_cell->callid.s = new_cell->callid.s - buf + buf1;
					new_cell->cseq_n.s = new_cell->cseq_n.s - buf + buf1;
				} else {
					/* use heavy artilery :D */
					if (extract_ftc_hdrs( buf1, buf_len1, &h_from, &h_to,
					&h_cseq, &h_callid)!=0 ) {
						LM_ERR("failed to update shortcut pointers\n");
						shm_free(buf1);
						goto abort_update;
					}
					new_cell->from = h_from;
					new_cell->to = h_to;
					new_cell->callid = h_callid;
					new_cell->cseq_n = h_cseq;
				}
				/* here we rely on how build_uac_req()
				   builds the first line */
				new_cell->uac[0].uri.s = buf1 +
					req->first_line.u.request.method.len + 1;
				new_cell->uac[0].uri.len = GET_RURI(req)->len;

				/* update also info about new destination and send sock */
				if (new_send_sock)
					request->dst.to = new_to_su;

				shm_free(buf);
				buf = buf1;
				buf_len = buf_len1;
				/* use new buffer */
			} else {
				/* no changes over the message, buffer is already generated,
				   just hide the original VIA for potential further branches */
				del_lump(req,req->h_via1->name.s-req->buf,req->h_via1->len,0);
			}
abort_update:
			/* save the SIP message into transaction */
			new_cell->uas.request = sip_msg_cloner( req, &sip_msg_len, 1);
			if (new_cell->uas.request==NULL) {
				/* reset any T triggering */
				new_cell->on_negative = 0;
				new_cell->on_reply = 0;
			} else {
				new_cell->uas.end_request=
					((char*)new_cell->uas.request)+sip_msg_len;
			}
			/* no parallel support in UAC transactions */
			new_cell->on_branch = 0;
			free_sip_msg(req);
		}
	}

	/* for DNS based failover, copy the DNS proxy into transaction */
	if (!disable_dns_failover) {
		new_cell->uac[0].proxy = shm_clone_proxy( proxy, 1/*do_free*/);
		if (new_cell->uac[0].proxy==NULL)
			LM_ERR("failed to store DNS info -> no DNS based failover\n");
	}

	new_cell->method.s = buf;
	new_cell->method.len = method->len;

	request->buffer.s = buf;
	request->buffer.len = buf_len;
	new_cell->nr_of_outgoings++;

	if(last_localT) {
		*last_localT = new_cell;
		REF_UNSAFE(new_cell);
	}

	if (SEND_BUFFER(request) == -1) {
		LM_ERR("attempt to send to '%.*s' failed\n",
			dialog->hooks.next_hop->len,
			dialog->hooks.next_hop->s);
	}

	if (method->len==ACK_LEN && memcmp(method->s, ACK, ACK_LEN)==0 ) {
		t_release_transaction(new_cell);
	} else {
		start_retr(request);
	}

	free_proxy( proxy );
	pkg_free( proxy );

	return 1;

error1:
	LOCK_HASH(hi);
	remove_from_hash_table_unsafe(new_cell);
	UNLOCK_HASH(hi);
	free_cell(new_cell);
error2:
	free_proxy( proxy );
	pkg_free( proxy );
error3:
	return ret;
}
コード例 #30
0
ファイル: sterman.c プロジェクト: AndreiPlesa/kamailio
/*
 * This function creates and submits radius authentication request as per
 * draft-sterman-aaa-sip-00.txt.  In addition, _user parameter is included
 * in the request as value of a SER specific attribute type SIP-URI-User,
 * which can be be used as a check item in the request.  Service type of
 * the request is Authenticate-Only.
 */
int radius_authorize_sterman(struct sip_msg* _msg, dig_cred_t* _cred, str* _method, str* _user) 
{
	static char msg[4096];
	VALUE_PAIR *send, *received;
	uint32_t service;
	str method, user, user_name;
	str *ruri;
	int extra_cnt, offset, i;
		
	send = received = 0;

	if (!(_cred && _method && _user)) {
		LM_ERR("invalid parameter value\n");
		return -1;
	}

	method = *_method;
	user = *_user;
	
	/*
	 * Add all the user digest parameters according to the qop defined.
	 * Most devices tested only offer support for the simplest digest.
	 */
	if (_cred->username.domain.len || !append_realm_to_username) {
		if (!rc_avpair_add(rh, &send, attrs[A_USER_NAME].v, _cred->username.whole.s, _cred->username.whole.len, 0)) {
			LM_ERR("unable to add User-Name attribute\n");
			goto err;
		}
	} else {
		user_name.len = _cred->username.user.len + _cred->realm.len + 1;
		user_name.s = pkg_malloc(user_name.len);
		if (!user_name.s) {
			LM_ERR("no pkg memory left\n");
			return -3;
		}
		memcpy(user_name.s, _cred->username.whole.s, _cred->username.whole.len);
		user_name.s[_cred->username.whole.len] = '@';
		memcpy(user_name.s + _cred->username.whole.len + 1, _cred->realm.s,
			_cred->realm.len);
		if (!rc_avpair_add(rh, &send, attrs[A_USER_NAME].v, user_name.s,
		user_name.len, 0)) {
			LM_ERR("unable to add User-Name attribute\n");
			pkg_free(user_name.s);
			goto err;
		}
		pkg_free(user_name.s);
	}

	if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_USER_NAME].v, 
	_cred->username.whole.s, _cred->username.whole.len, 0)) {
		LM_ERR("unable to add Digest-User-Name attribute\n");
		goto err;
	}

	if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_REALM].v, _cred->realm.s,
	_cred->realm.len, 0)) {
		LM_ERR("unable to add Digest-Realm attribute\n");
		goto err;
	}
	if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_NONCE].v, _cred->nonce.s,
	_cred->nonce.len, 0)) {
		LM_ERR("unable to add Digest-Nonce attribute\n");
		goto err;
	}

	if (use_ruri_flag < 0 || isflagset(_msg, use_ruri_flag) != 1) {
		ruri = &_cred->uri;
	} else {
		ruri = GET_RURI(_msg);
	}
	if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_URI].v, ruri->s,
	ruri->len, 0)) {
		LM_ERR("unable to add Digest-URI attribute\n");
		goto err;
	}

	if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_METHOD].v, method.s,
	method.len, 0)) {
		LM_ERR("unable to add Digest-Method attribute\n");
		goto err;
	}
	
	/* 
	 * Add the additional authentication fields according to the QOP.
	 */
	if (_cred->qop.qop_parsed == QOP_AUTH) {
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_QOP].v, "auth", 4, 0)) {
			LM_ERR("unable to add Digest-QOP attribute\n");
			goto err;
		}
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_NONCE_COUNT].v, 
		_cred->nc.s, _cred->nc.len, 0)) {
			LM_ERR("unable to add Digest-CNonce-Count attribute\n");
			goto err;
		}
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_CNONCE].v, 
		_cred->cnonce.s, _cred->cnonce.len, 0)) {
			LM_ERR("unable to add Digest-CNonce attribute\n");
			goto err;
		}
	} else if (_cred->qop.qop_parsed == QOP_AUTHINT) {
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_QOP].v,
		"auth-int", 8, 0)) {
			LM_ERR("unable to add Digest-QOP attribute\n");
			goto err;
		}
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_NONCE_COUNT].v,
		_cred->nc.s, _cred->nc.len, 0)) {
			LM_ERR("unable to add Digest-Nonce-Count attribute\n");
			goto err;
		}
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_CNONCE].v,
		_cred->cnonce.s, _cred->cnonce.len, 0)) {
			LM_ERR("unable to add Digest-CNonce attribute\n");
			goto err;
		}
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_BODY_DIGEST].v, 
		_cred->opaque.s, _cred->opaque.len, 0)) {
			LM_ERR("unable to add Digest-Body-Digest attribute\n");
			goto err;
		}
		
	} else  {
		/* send nothing for qop == "" */
	}

	/* Add the response... What to calculate against... */
	if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_RESPONSE].v, 
	_cred->response.s, _cred->response.len, 0)) {
		LM_ERR("unable to add Digest-Response attribute\n");
		goto err;
	}

	/* Indicate the service type, Authenticate only in our case */
	service = vals[V_SIP_SESSION].v;
	if (!rc_avpair_add(rh, &send, attrs[A_SERVICE_TYPE].v, &service, -1, 0)) {
		LM_ERR("unable to add Service-Type attribute\n");
		goto err;
	}

	/* Add SIP URI as a check item */
	if (!rc_avpair_add(rh,&send,attrs[A_SIP_URI_USER].v,user.s,user.len,0)) {
		LM_ERR("unable to add Sip-URI-User attribute\n");
		goto err;
	}

	if (attrs[A_CISCO_AVPAIR].n != NULL) {
		if (add_cisco_vsa(&send, _msg)) {
			goto err;
		}
	}

	/* Add extra attributes */
	extra_cnt = extra2strar(auth_extra, _msg, val_arr);
	if (extra_cnt == -1) {
	    LM_ERR("in getting values of extra attributes\n");
	    goto err;
	}
	offset = A_MAX;
	for (i = 0; i < extra_cnt; i++) {
	    if (val_arr[i].len == -1) {
		/* Add integer attribute */
		ADD_EXTRA_AVPAIR(attrs, offset+i,
				 &(val_arr[i].s), val_arr[i].len );
	    } else {
		/* Add string attribute */
		ADD_EXTRA_AVPAIR(attrs, offset+i,
				 val_arr[i].s, val_arr[i].len );
	    }
	}

	/* Send request */
	if ((i = rc_auth(rh, SIP_PORT, send, &received, msg)) == OK_RC) {
		LM_DBG("Success\n");
		rc_avpair_free(send);
		send = 0;

		generate_avps(received);

		rc_avpair_free(received);
		return 1;
	} else {
#ifdef REJECT_RC
                if (i == REJECT_RC) {
                        LM_DBG("Failure\n");
                        goto err;
                }
#endif 
		LM_ERR("authorization failed. RC auth returned %d\n", i);
	}

 err:
	if (send) rc_avpair_free(send);
	if (received) rc_avpair_free(received);
	return -1;
}