Exemple #1
0
int pres_refresh_watchers(str *pres, str *event, int type, str *file_uri, str *filename)
{
	pres_ev_t *ev;
	struct sip_uri uri;
	str *rules_doc= NULL;
	int result;

	ev= contains_event(event, NULL);
	if(ev==NULL)
	{
		LM_ERR("wrong event parameter\n");
		return -1;
	}

	if(type==0)
	{
		/* if a request to refresh watchers authorization */
		if(ev->get_rules_doc==NULL)
		{
			LM_ERR("wrong request for a refresh watchers authorization status"
					"for an event that does not require authorization\n");
			goto error;
		}

		if(parse_uri(pres->s, pres->len, &uri)<0)
		{
			LM_ERR("parsing uri [%.*s]\n", pres->len, pres->s);
			goto error;
		}

		result= ev->get_rules_doc(&uri.user, &uri.host, &rules_doc);
		if(result<0 || rules_doc==NULL || rules_doc->s==NULL)
		{
			LM_ERR("no rules doc found for the user\n");
			goto error;
		}

		if(update_watchers_status(*pres, ev, rules_doc)<0)
		{
			LM_ERR("failed to update watchers\n");
			goto error;
		}

		pkg_free(rules_doc->s);
		pkg_free(rules_doc);
		rules_doc = NULL;

	} else {
		if (type == 2) {
			if (update_hard_presentity(pres, ev, file_uri, filename) < 0)
			{
				LM_ERR("updating hard presentity\n");
				goto error;
			}
		}

		/* if a request to refresh notified info */
		if(query_db_notify(pres, ev, NULL)< 0)
		{
			LM_ERR("sending Notify requests\n");
			goto error;
		}

	}
	return 0;

error:
	if(rules_doc)
	{
		if(rules_doc->s)
			pkg_free(rules_doc->s);
		pkg_free(rules_doc);
	}
	return -1;
}
/* ret= 0! if action -> end of list(e.g DROP), 
      > 0 to continue processing next actions
   and <0 on error */
int do_action(struct action* a, struct sip_msg* msg)
{
	int ret;
	int v;
	union sockaddr_union* to;
	struct socket_info* send_sock;
	struct proxy_l* p;
	char* tmp;
	char *new_uri, *end, *crt;
	int len;
	int user;
	struct sip_uri uri, next_hop;
	struct sip_uri* u;
	unsigned short port;
	int proto;

	/* reset the value of error to E_UNSPEC so avoid unknowledgable
	   functions to return with errror (status<0) and not setting it
	   leaving there previous error; cache the previous value though
	   for functions which want to process it */
	prev_ser_error=ser_error;
	ser_error=E_UNSPEC;

	ret=E_BUG;
	switch ((unsigned char)a->type){
		case DROP_T:
				ret=0;
			break;
		case FORWARD_T:
#ifdef USE_TCP
		case FORWARD_TCP_T:
#endif
#ifdef USE_TLS
		case FORWARD_TLS_T:
#endif
		case FORWARD_UDP_T:

			if (a->type==FORWARD_UDP_T) proto=PROTO_UDP;
#ifdef USE_TCP
			else if (a->type==FORWARD_TCP_T) proto= PROTO_TCP;
#endif
#ifdef USE_TLS
			else if (a->type==FORWARD_TLS_T) proto= PROTO_TLS;
#endif
			else proto=msg->rcv.proto;
			if (a->p1_type==URIHOST_ST){
				/*parse uri*/

				if (msg->dst_uri.len) {
					ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len, &next_hop);
					u = &next_hop;
				} else {
					ret = parse_sip_msg_uri(msg);
					u = &msg->parsed_uri;
				}

				if (ret<0) {
					LOG(L_ERR, "ERROR: do_action: forward: bad_uri "
								" dropping packet\n");
					break;
				}
				
				switch (a->p2_type){
					case URIPORT_ST:
									port=u->port_no;
									break;
					case NUMBER_ST:
									port=a->p2.number;
									break;
					default:
							LOG(L_CRIT, "BUG: do_action bad forward 2nd"
										" param type (%d)\n", a->p2_type);
							ret=E_UNSPEC;
							goto error_fwd_uri;
				}
				switch(u->proto){
					case PROTO_NONE:
						proto=PROTO_UDP;
						break;
					case PROTO_UDP:
#ifdef USE_TCP
					case PROTO_TCP:
#endif
#ifdef USE_TLS
					case PROTO_TLS:
#endif
						proto=u->proto;
						break;
					default:
						LOG(L_ERR,"ERROR: do action: forward: bad uri"
								" transport %d\n", u->proto);
						ret=E_BAD_PROTO;
						goto error_fwd_uri;
				}
#ifdef USE_TLS
				if (u->secure){
					if (u->proto==PROTO_UDP){
						LOG(L_ERR, "ERROR: do_action: forward: secure uri"
								" incompatible with transport %d\n", u->proto);
						ret=E_BAD_PROTO;
						goto error_fwd_uri;
					}
					proto=PROTO_TLS;
				}
#endif
				/* create a temporary proxy*/
				p=mk_proxy(&u->host, port, proto);
				if (p==0){
					LOG(L_ERR, "ERROR:  bad host name in uri,"
							" dropping packet\n");
					ret=E_BAD_ADDRESS;
					goto error_fwd_uri;
				}
				ret=forward_request(msg, p, proto);
				/*free_uri(&uri); -- no longer needed, in sip_msg*/
				free_proxy(p); /* frees only p content, not p itself */
				pkg_free(p);
				if (ret>=0) ret=1;
			}else if ((a->p1_type==PROXY_ST) && (a->p2_type==NUMBER_ST)){
				ret=forward_request(msg,(struct proxy_l*)a->p1.data, proto);
				if (ret>=0) ret=1;
			}else{
				LOG(L_CRIT, "BUG: do_action: bad forward() types %d, %d\n",
						a->p1_type, a->p2_type);
				ret=E_BUG;
			}
			break;
		case SEND_T:
		case SEND_TCP_T:
			if ((a->p1_type!= PROXY_ST)|(a->p2_type!=NUMBER_ST)){
				LOG(L_CRIT, "BUG: do_action: bad send() types %d, %d\n",
						a->p1_type, a->p2_type);
				ret=E_BUG;
				break;
			}
			to=(union sockaddr_union*)
					pkg_malloc(sizeof(union sockaddr_union));
			if (to==0){
				LOG(L_ERR, "ERROR: do_action: "
							"memory allocation failure\n");
				ret=E_OUT_OF_MEM;
				break;
			}
			
			p=(struct proxy_l*)a->p1.data;
			
			if (p->ok==0){
				if (p->host.h_addr_list[p->addr_idx+1])
					p->addr_idx++;
				else 
					p->addr_idx=0;
				p->ok=1;
			}
			ret=hostent2su(	to, &p->host, p->addr_idx,
						(p->port)?p->port:SIP_PORT );
			if (ret==0){
				p->tx++;
				p->tx_bytes+=msg->len;
				if (a->type==SEND_T){
					/*udp*/
					send_sock=get_send_socket(to, PROTO_UDP);
					if (send_sock!=0){
						ret=udp_send(send_sock, msg->buf, msg->len, to);
					}else{
						ret=-1;
					}
				}
#ifdef USE_TCP
					else{
					/*tcp*/
					ret=tcp_send(PROTO_TCP, msg->buf, msg->len, to, 0);
				}
#endif
			}
			pkg_free(to);
			if (ret<0){
				p->errors++;
				p->ok=0;
			}else ret=1;
			
			break;
		case LOG_T:
			if ((a->p1_type!=NUMBER_ST)|(a->p2_type!=STRING_ST)){
				LOG(L_CRIT, "BUG: do_action: bad log() types %d, %d\n",
						a->p1_type, a->p2_type);
				ret=E_BUG;
				break;
			}
			LOG(a->p1.number, a->p2.string);
			ret=1;
			break;

		/* jku -- introduce a new branch */
		case APPEND_BRANCH_T:
			if ((a->p1_type!=STRING_ST)) {
				LOG(L_CRIT, "BUG: do_action: bad append_branch_t %d\n",
					a->p1_type );
				ret=E_BUG;
				break;
			}
			ret=append_branch( msg, a->p1.string, 
				a->p1.string ? strlen(a->p1.string):0 );
			break;

		/* jku begin: is_length_greater_than */
		case LEN_GT_T:
			if (a->p1_type!=NUMBER_ST) {
				LOG(L_CRIT, "BUG: do_action: bad len_gt type %d\n",
					a->p1_type );
				ret=E_BUG;
				break;
			}
			/* DBG("XXX: message length %d, max %d\n", 
				msg->len, a->p1.number ); */
			ret = msg->len >= a->p1.number ? 1 : -1;
			break;
		/* jku end: is_length_greater_than */
			
		/* jku - begin : flag processing */

		case SETFLAG_T:
			if (a->p1_type!=NUMBER_ST) {
				LOG(L_CRIT, "BUG: do_action: bad setflag() type %d\n",
					a->p1_type );
				ret=E_BUG;
				break;
			}
			if (!flag_in_range( a->p1.number )) {
				ret=E_CFG;
				break;
			}
			setflag( msg, a->p1.number );
			ret=1;
			break;

		case RESETFLAG_T:
			if (a->p1_type!=NUMBER_ST) {
				LOG(L_CRIT, "BUG: do_action: bad resetflag() type %d\n",
					a->p1_type );
				ret=E_BUG;
				break;
			}
			if (!flag_in_range( a->p1.number )) {
				ret=E_CFG;
				break;
			}
			resetflag( msg, a->p1.number );
			ret=1;
			break;
			
		case ISFLAGSET_T:
			if (a->p1_type!=NUMBER_ST) {
				LOG(L_CRIT, "BUG: do_action: bad isflagset() type %d\n",
					a->p1_type );
				ret=E_BUG;
				break;
			}
			if (!flag_in_range( a->p1.number )) {
				ret=E_CFG;
				break;
			}
			ret=isflagset( msg, a->p1.number );
			break;
		/* jku - end : flag processing */

		case ERROR_T:
			if ((a->p1_type!=STRING_ST)|(a->p2_type!=STRING_ST)){
				LOG(L_CRIT, "BUG: do_action: bad error() types %d, %d\n",
						a->p1_type, a->p2_type);
				ret=E_BUG;
				break;
			}
			LOG(L_NOTICE, "WARNING: do_action: error(\"%s\", \"%s\") "
					"not implemented yet\n", a->p1.string, a->p2.string);
			ret=1;
			break;
		case ROUTE_T:
			if (a->p1_type!=NUMBER_ST){
				LOG(L_CRIT, "BUG: do_action: bad route() type %d\n",
						a->p1_type);
				ret=E_BUG;
				break;
			}
			if ((a->p1.number>RT_NO)||(a->p1.number<0)){
				LOG(L_ERR, "ERROR: invalid routing table number in"
							"route(%lu)\n", a->p1.number);
				ret=E_CFG;
				break;
			}
			ret=((ret=run_actions(rlist[a->p1.number], msg))<0)?ret:1;
			break;
		case EXEC_T:
			if (a->p1_type!=STRING_ST){
				LOG(L_CRIT, "BUG: do_action: bad exec() type %d\n",
						a->p1_type);
				ret=E_BUG;
				break;
			}
			LOG(L_NOTICE, "WARNING: exec(\"%s\") not fully implemented,"
						" using dumb version...\n", a->p1.string);
			ret=system(a->p1.string);
			if (ret!=0){
				LOG(L_NOTICE, "WARNING: exec() returned %d\n", ret);
			}
			ret=1;
			break;
		case REVERT_URI_T:
			if (msg->new_uri.s) {
				pkg_free(msg->new_uri.s);
				msg->new_uri.len=0;
				msg->new_uri.s=0;
				msg->parsed_uri_ok=0; /* invalidate current parsed uri*/
			};
			ret=1;
			break;
		case SET_HOST_T:
		case SET_HOSTPORT_T:
		case SET_USER_T:
		case SET_USERPASS_T:
		case SET_PORT_T:
		case SET_URI_T:
		case PREFIX_T:
		case STRIP_T:
		case STRIP_TAIL_T:
				user=0;
				if (a->type==STRIP_T || a->type==STRIP_TAIL_T) {
					if (a->p1_type!=NUMBER_ST) {
						LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
							a->p1_type);
						break;
					}
				} else if (a->p1_type!=STRING_ST){
					LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
							a->p1_type);
					ret=E_BUG;
					break;
				}
				if (a->type==SET_URI_T){
					if (msg->new_uri.s) {
							pkg_free(msg->new_uri.s);
							msg->new_uri.len=0;
					}
					msg->parsed_uri_ok=0;
					len=strlen(a->p1.string);
					msg->new_uri.s=pkg_malloc(len+1);
					if (msg->new_uri.s==0){
						LOG(L_ERR, "ERROR: do_action: memory allocation"
								" failure\n");
						ret=E_OUT_OF_MEM;
						break;
					}
					memcpy(msg->new_uri.s, a->p1.string, len);
					msg->new_uri.s[len]=0;
					msg->new_uri.len=len;
					
					ret=1;
					break;
				}
				if (msg->new_uri.s) {
					tmp=msg->new_uri.s;
					len=msg->new_uri.len;
				}else{
					tmp=msg->first_line.u.request.uri.s;
					len=msg->first_line.u.request.uri.len;
				}
				if (parse_uri(tmp, len, &uri)<0){
					LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping"
								" packet\n", tmp);
					ret=E_UNSPEC;
					break;
				}
				
				new_uri=pkg_malloc(MAX_URI_SIZE);
				if (new_uri==0){
					LOG(L_ERR, "ERROR: do_action: memory allocation "
								" failure\n");
					ret=E_OUT_OF_MEM;
					break;
				}
				end=new_uri+MAX_URI_SIZE;
				crt=new_uri;
				/* begin copying */
				len=strlen("sip:"); if(crt+len>end) goto error_uri;
				memcpy(crt,"sip:",len);crt+=len;

				/* user */

				/* prefix (-jiri) */
				if (a->type==PREFIX_T) {
					tmp=a->p1.string;
					len=strlen(tmp); if(crt+len>end) goto error_uri;
					memcpy(crt,tmp,len);crt+=len;
					/* whatever we had before, with prefix we have username 
					   now */
					user=1;
				}

				if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) {
					tmp=a->p1.string;
					len=strlen(tmp);
				} else if (a->type==STRIP_T) {
					if (a->p1.number>uri.user.len) {
						LOG(L_WARN, "Error: too long strip asked; "
									" deleting username: %lu of <%.*s>\n",
									a->p1.number, uri.user.len, uri.user.s );
						len=0;
					} else if (a->p1.number==uri.user.len) {
						len=0;
					} else {
						tmp=uri.user.s + a->p1.number;
						len=uri.user.len - a->p1.number;
					}
				} else if (a->type==STRIP_TAIL_T) {
					if (a->p1.number>uri.user.len) {
						LOG(L_WARN, "WARNING: too long strip_tail asked; "
									" deleting username: %lu of <%.*s>\n",
									a->p1.number, uri.user.len, uri.user.s );
						len=0;
					} else if (a->p1.number==uri.user.len) {
						len=0;
					} else {
						tmp=uri.user.s;
						len=uri.user.len - a->p1.number;
					}
				} else {
					tmp=uri.user.s;
					len=uri.user.len;
				}

				if (len){
					if(crt+len>end) goto error_uri;
					memcpy(crt,tmp,len);crt+=len;
					user=1; /* we have an user field so mark it */
				}

				if (a->type==SET_USERPASS_T) tmp=0;
				else tmp=uri.passwd.s;
				/* passwd */
				if (tmp){
					len=uri.passwd.len; if(crt+len+1>end) goto error_uri;
					*crt=':'; crt++;
					memcpy(crt,tmp,len);crt+=len;
				}
				/* host */
				if (user || tmp){ /* add @ */
					if(crt+1>end) goto error_uri;
					*crt='@'; crt++;
				}
				if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T)) {
					tmp=a->p1.string;
					if (tmp) len = strlen(tmp);
					else len=0;
				} else {
					tmp=uri.host.s;
					len = uri.host.len;
				}
				if (tmp){
					if(crt+len>end) goto error_uri;
					memcpy(crt,tmp,len);crt+=len;
				}
				/* port */
				if (a->type==SET_HOSTPORT_T) tmp=0;
				else if (a->type==SET_PORT_T) {
					tmp=a->p1.string;
					if (tmp) len = strlen(tmp);
					else len = 0;
				} else {
					tmp=uri.port.s;
					len = uri.port.len;
				}
				if (tmp){
					if(crt+len+1>end) goto error_uri;
					*crt=':'; crt++;
					memcpy(crt,tmp,len);crt+=len;
				}
				/* params */
				tmp=uri.params.s;
				if (tmp){
					len=uri.params.len; if(crt+len+1>end) goto error_uri;
					*crt=';'; crt++;
					memcpy(crt,tmp,len);crt+=len;
				}
				/* headers */
				tmp=uri.headers.s;
				if (tmp){
					len=uri.headers.len; if(crt+len+1>end) goto error_uri;
					*crt='?'; crt++;
					memcpy(crt,tmp,len);crt+=len;
				}
				*crt=0; /* null terminate the thing */
				/* copy it to the msg */
				if (msg->new_uri.s) pkg_free(msg->new_uri.s);
				msg->new_uri.s=new_uri;
				msg->new_uri.len=crt-new_uri;
				msg->parsed_uri_ok=0;
				ret=1;
				break;
		case IF_T:
				/* if null expr => ignore if? */
				if ((a->p1_type==EXPR_ST)&&a->p1.data){
					v=eval_expr((struct expr*)a->p1.data, msg);
					if (v<0){
						if (v==EXPR_DROP){ /* hack to quit on DROP*/
							ret=0;
							break;
						}else{
							LOG(L_WARN,"WARNING: do_action:"
										"error in expression\n");
						}
					}
					
					ret=1;  /*default is continue */
					if (v>0) {
						if ((a->p2_type==ACTIONS_ST)&&a->p2.data){
							ret=run_actions((struct action*)a->p2.data, msg);
						}
					}else if ((a->p3_type==ACTIONS_ST)&&a->p3.data){
							ret=run_actions((struct action*)a->p3.data, msg);
					}
				}
			break;
		case MODULE_T:
			if ( ((a->p1_type==CMDF_ST)&&a->p1.data)/*&&
					((a->p2_type==STRING_ST)&&a->p2.data)*/ ){
				ret=((cmd_function)(a->p1.data))(msg, (char*)a->p2.data,
													  (char*)a->p3.data);
			}else{
				LOG(L_CRIT,"BUG: do_action: bad module call\n");
			}
			break;
		case FORCE_RPORT_T:
			msg->msg_flags|=FL_FORCE_RPORT;
			ret=1; /* continue processing */
			break;
		case SET_ADV_ADDR_T:
			if (a->p1_type!=STR_ST){
				LOG(L_CRIT, "BUG: do_action: bad set_advertised_address() "
						"type %d\n", a->p1_type);
				ret=E_BUG;
				break;
			}
			msg->set_global_address=*((str*)a->p1.data);
			ret=1; /* continue processing */
			break;
		case SET_ADV_PORT_T:
			if (a->p1_type!=STR_ST){
				LOG(L_CRIT, "BUG: do_action: bad set_advertised_port() "
						"type %d\n", a->p1_type);
				ret=E_BUG;
				break;
			}
			msg->set_global_port=*((str*)a->p1.data);
			ret=1; /* continue processing */
			break;
		default:
			LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
	}
/*skip:*/
	return ret;
	
error_uri:
	LOG(L_ERR, "ERROR: do_action: set*: uri too long\n");
	if (new_uri) pkg_free(new_uri);
	return E_UNSPEC;
error_fwd_uri:
	/*free_uri(&uri); -- not needed anymore, using msg->parsed_uri*/
	return ret;
}
Exemple #3
0
/*
** parse_vararg: read & check a attribute value
*/
STRPTR parse_vararg( HSCVAR *var, INFILE *inpf )
{
    STRPTR str_vararg = NULL;          /* return value */
    int    ch;                         /* char read from input */

    /* TODO: handle "<>" (reset var->text to NULL) */

    infskip_ws( inpf );

    /* disable log */
    inflog_disable( inpf );

    /* read var->quote char */
    ch = infgetc( inpf );
    if ( !strchr( VQ_STR_QUOTE, ch ) )
        if ( ch != EOF )
            var->quote = VQ_NO_QUOTE;
        else
            err_eof( inpf, "reading attribute" );
    else
        var->quote = ch;

    /* warning if no quote */
    if ( ( var->quote == VQ_NO_QUOTE )
         && !( var->varflag & VF_NOQUOTE ) )
    {

        message( MSG_ARG_NO_QUOTE, inpf );
        errstr( "Argument without quote\n" );

    }

    /* read arg string */
    if ( var->quote == '<' ) {

        /*
        ** get arg from other var
        */
        STRPTR nw = infgetw( inpf );

        if ( nw ) {

            HSCVAR *refvar = find_varname( vars, nw );

            if ( refvar ) {

                /* TODO: type checking */
                var->quote = refvar->quote;
                str_vararg = refvar->text;

                /* check empty/circular reference */
                if ( !str_vararg ) {

                    message( MSG_EMPTY_SYMB_REF, inpf );
                    errstr( "Empty reference to" );
                    errsym( var->name );
                    errlf();

                }

                /* debugging message */
                DDA( fprintf( stderr, "**    %s refers to <%s>\n",
                              var->name, refvar->name ) );

            } else {

                /* reference to unknown var */
                message( MSG_UNKN_SYMB_REF, inpf );
                errstr( "reference to unknown" );
                errsym( nw );
                errlf();

            }

            if ( (!refvar) || (!str_vararg ) ) {

                /* return empty var */
                var->quote = '"';
                str_vararg = "";
            }

            parse_gt( inpf );

        } else
            err_eof( inpf, "reading attribute" );

    } else if ( var->quote != EOF ) {

        /*
        ** get arg from input file
        */
        BOOL   end = FALSE;

        /* clear vararg or set with first char read */
        if ( var->quote == VQ_NO_QUOTE )
            end = !set_estr( vararg, ch2str( ch ) );
        else
            end = !clr_estr( vararg );
        if ( end )
            err_mem( inpf );

        /*
        ** read next char from input file until a
        ** closing quote if found.
        ** if the arg had no quote, a white space
        ** or a '>' is used to detect end of arg.
        ** if a LF is found, view error message
        */
        while ( !end ) {

            ch = infgetc( inpf );

            end = TRUE;

            if ( ch == EOF )
                err_eof( inpf, "reading attribute" );
            else if ( (ch==var->quote)
                      || ( ch==CH_LF )
                      || ( (var->quote==VQ_NO_QUOTE)
                           && ( inf_isws(ch,inpf) || ( ch=='>' ) ) )
                    )
            {

                /* end of arg reached */
                str_vararg = estr2str( vararg );
                if ( var->quote == VQ_NO_QUOTE ) {

                    if ( ch==CH_LF )
                        err_streol( inpf );
                    inungetc( ch, inpf );

                }

            } else {

                /* append next char to vararg */
                if ( !app_estrch( vararg, ch ) )
                    err_mem( inpf );
                else
                    end = FALSE; /* continue loop */

            }
        }
    }

    if ( str_vararg && var )
        /*
        ** check enum type
        */
        if (var->vartype == VT_ENUM)
            check_enumstr( var, str_vararg, inpf );
        /*
        ** parse uri (only if no macro-attr)
        ** (convert abs.uris, check existence)
        */
        else if (var->vartype == VT_URI )

            if ( !(var->varflag & VF_MACRO) )
                str_vararg = parse_uri( str_vararg, inpf );
            else {

                DDA( fprintf( stderr, "**    didn't parse uri \"%s\"\n",
                              str_vararg ) );

            }

    /* update and enable log */
    if ( !fatal_error ) {

        BOOL ok = TRUE;

        if ( var->quote != VQ_NO_QUOTE )                   
            ok &= inflog_app( inpf, ch2str( var->quote ) );/* append quote */
        inflog_app( inpf, str_vararg );                    /* append arg */
        if ( var->quote != VQ_NO_QUOTE )
            ok &= inflog_app( inpf, ch2str( var->quote ) );/* append quote */
        inflog_enable( inpf );                             /* enable log */

        if ( !ok )
            err_mem( NULL );
    }

    return ( str_vararg );
}
Exemple #4
0
int zmq::socket_base_t::term_endpoint (const char *addr_)
{
    ENTER_MUTEX ();

    //  Check whether the library haven't been shut down yet.
    if (unlikely (ctx_terminated)) {
        errno = ETERM;
        EXIT_MUTEX ();
        return -1;
    }

    //  Check whether endpoint address passed to the function is valid.
    if (unlikely (!addr_)) {
        errno = EINVAL;
        EXIT_MUTEX ();
        return -1;
    }

    //  Process pending commands, if any, since there could be pending unprocessed process_own()'s
    //  (from launch_child() for example) we're asked to terminate now.
    int rc = process_commands (0, false);
    if (unlikely(rc != 0)) {
        EXIT_MUTEX ();
        return -1;
    }

    //  Parse addr_ string.
    std::string protocol;
    std::string address;
    if (parse_uri(addr_, protocol, address) || check_protocol(protocol)) {
        EXIT_MUTEX ();
        return -1;
    }

    // Disconnect an inproc socket
    if (protocol == "inproc") {
        if (unregister_endpoint (std::string(addr_), this) == 0) {
            EXIT_MUTEX ();
            return 0;
        }
        std::pair <inprocs_t::iterator, inprocs_t::iterator> range = inprocs.equal_range (std::string (addr_));
        if (range.first == range.second) {
            errno = ENOENT;
            EXIT_MUTEX ();
            return -1;
        }

        for (inprocs_t::iterator it = range.first; it != range.second; ++it)
            it->second->terminate (true);
        inprocs.erase (range.first, range.second);
        EXIT_MUTEX ();
        return 0;
    }

    std::string resolved_addr = std::string (addr_);
    std::pair <endpoints_t::iterator, endpoints_t::iterator> range;

    // The resolved last_endpoint is used as a key in the endpoints map.
    // The address passed by the user might not match in the TCP case due to
    // IPv4-in-IPv6 mapping (EG: tcp://[::ffff:127.0.0.1]:9999), so try to
    // resolve before giving up. Given at this stage we don't know whether a
    // socket is connected or bound, try with both.
    if (protocol == "tcp") {
        range = endpoints.equal_range (resolved_addr);
        if (range.first == range.second) {
            tcp_address_t *tcp_addr = new (std::nothrow) tcp_address_t ();
            alloc_assert (tcp_addr);
            rc = tcp_addr->resolve (address.c_str (), false, options.ipv6);

            if (rc == 0) {
                tcp_addr->to_string (resolved_addr);
                range = endpoints.equal_range (resolved_addr);

                if (range.first == range.second) {
                    rc = tcp_addr->resolve (address.c_str (), true, options.ipv6);
                    if (rc == 0) {
                        tcp_addr->to_string (resolved_addr);
                    }
                }
            }
            LIBZMQ_DELETE(tcp_addr);
        }
    }

    //  Find the endpoints range (if any) corresponding to the addr_ string.
    range = endpoints.equal_range (resolved_addr);
    if (range.first == range.second) {
        errno = ENOENT;
        EXIT_MUTEX ();
        return -1;
    }

    for (endpoints_t::iterator it = range.first; it != range.second; ++it) {
        //  If we have an associated pipe, terminate it.
        if (it->second.second != NULL)
            it->second.second->terminate (false);
        term_child (it->second.first);
    }
    endpoints.erase (range.first, range.second);
    EXIT_MUTEX ();
    return 0;
}
Exemple #5
0
/* Params: 
 *   str1 - as unsigned int - can be CPL_RUN_INCOMING or CPL_RUN_OUTGOING 
 *   str2 - as unsigned int - flags regarding state(less)|(ful) 
 *   str3 - URI in SPVE structure
 */
static int cpl_invoke_script3(struct sip_msg* msg, char* str1, char* str2, char *str3)
{
	struct cpl_interpreter  *cpl_intr;
	str  username = {0,0};
	str  domain = {0,0};
	str  uri = {0,0};
	sip_uri_t puri;
	str  loc;
	str  script;

	/* get the user_name */
	if(str3==NULL) {
		if ( ((unsigned long)str1)&CPL_RUN_INCOMING ) {
			/* if it's incoming -> get the destination user name */
			if (get_dest_user( msg, &username, &domain)==-1)
				goto error0;
		} else {
			/* if it's outgoing -> get the origin user name */
			if (get_orig_user( msg, &username, &domain)==-1)
				goto error0;
		}
	} else {
		if(fixup_get_svalue(msg, (gparam_p)str3, &uri)!=0)
		{
			LM_ERR("invalid uri parameter");
			goto error0;
		}
		if (parse_uri(uri.s, uri.len, &puri) || !puri.user.len) {
			LM_ERR("unable to extract user name from URI param\n");
			return -1;
		}
		username = puri.user;
		domain = puri.host;
	}

	/* get the script for this user */
	if (get_user_script(&username, cpl_env.use_domain?&domain:0,
	&script, &cpl_bin_col)==-1)
		goto error0;

	/* has the user a non-empty script? if not, return normally, allowing the
	 * script execution to continue */
	if ( !script.s || !script.len )
		return 1;

	/* build a new script interpreter */
	if ( (cpl_intr=new_cpl_interpreter(msg,&script))==0 )
		goto error1;
	/* set the flags */
	cpl_intr->flags =(unsigned int)((unsigned long)str1)|((unsigned long)str2);
	/* build user AOR */
	if (build_user_AOR( &username, &domain, &(cpl_intr->user), 0)!=0 )
		goto error2;
	/* for OUTGOING we need also the destination user for init. with him
	 * the location set */
	if ( ((unsigned long)str1)&CPL_RUN_OUTGOING ) {
		/* build user initial location -> get the destination user name */
		if (get_dest_user( msg, &username, &domain)==-1)
			goto error2;
		if (build_user_AOR( &username, &domain, &loc, 1)!=0 )
			goto error2;
		if (add_location( &(cpl_intr->loc_set), &loc, 0, 10, 0/*no dup*/)==-1)
			goto error2;
	}

	/* run the script */
	switch (cpl_run_script( cpl_intr )) {
		case SCRIPT_DEFAULT:
			free_cpl_interpreter( cpl_intr );
			return 1; /* execution of ser's script will continue */
		case SCRIPT_END:
			free_cpl_interpreter( cpl_intr );
		case SCRIPT_TO_BE_CONTINUED:
			return 0; /* break the SER script */
		case SCRIPT_RUN_ERROR:
		case SCRIPT_FORMAT_ERROR:
			goto error2;
	}

	return 1;
error2:
	free_cpl_interpreter( cpl_intr );
	return -1;
error1:
	shm_free(script.s);
error0:
	return -1;
}
Exemple #6
0
void uac_reg_tm_callback( struct cell *t, int type, struct tmcb_params *ps)
{
	char *uuid;
	str suuid;
	reg_uac_t *ri = NULL;
	contact_t* c;
	int expires;
	struct sip_uri puri;
	struct hdr_field *hdr;
	HASHHEX response;
	str *new_auth_hdr = NULL;
	static struct authenticate_body auth;
	struct uac_credential cred;
	char  b_ruri[MAX_URI_SIZE];
	str   s_ruri;
#ifdef UAC_OLD_AUTH
	char  b_turi[MAX_URI_SIZE];
	str   s_turi;
#endif
	char  b_hdrs[MAX_UACH_SIZE];
	str   s_hdrs;
	uac_req_t uac_r;
	str method = {"REGISTER", 8};
	int ret;
	dlg_t tmdlg;

	if(ps->param==NULL || *ps->param==0)
	{
		LM_DBG("uuid not received\n");
		return;
	}
	uuid = *((char**)ps->param);
	LM_DBG("completed with status %d [uuid: %s]\n",
			ps->code, uuid);
	suuid.s = uuid;
	suuid.len = strlen(suuid.s);
	ri = reg_ht_get_byuuid(&suuid);

	if(ri==NULL)
	{
		LM_DBG("no user with uuid %s\n", uuid);
		goto done;
	}

	if(ps->code == 200)
	{
		if (parse_headers(ps->rpl, HDR_EOH_F, 0) == -1)
		{
			LM_ERR("failed to parse headers\n");
			goto error;
		}
		if (ps->rpl->contact==NULL)
		{
			LM_ERR("no Contact found\n");
			goto error;
		}
		if (parse_contact(ps->rpl->contact) < 0)
		{
			LM_ERR("failed to parse Contact HF\n");
			goto error;
		}
		if (((contact_body_t*)ps->rpl->contact->parsed)->star)
		{
			LM_DBG("* Contact found\n");
			goto done;
		}

		if (contact_iterator(&c, ps->rpl, 0) < 0)
			goto done;
		while(c)
		{
			if(parse_uri(c->uri.s, c->uri.len, &puri)!=0)
			{
				LM_ERR("failed to parse c-uri\n");
				goto error;
			}
			if(suuid.len==puri.user.len
					&& (strncmp(puri.user.s, suuid.s, suuid.len)==0))
			{
				/* calculate expires */
				expires=0;
				if(c->expires==NULL || c->expires->body.len<=0)
				{
					if(ps->rpl->expires!=NULL && ps->rpl->expires->body.len>0)
						expires = atoi(ps->rpl->expires->body.s);
				} else {
					str2int(&c->expires->body, (unsigned int*)(&expires));
				}
				ri->timer_expires = ri->timer_expires + expires;
				ri->flags |= UAC_REG_ONLINE;
				goto done;
			}
			if (contact_iterator(&c, ps->rpl, c) < 0)
			{
				LM_DBG("local contact not found\n");
				goto done;
			}
		}
	}

	if(ps->code == 401 || ps->code == 407)
	{
		if(ri->flags & UAC_REG_AUTHSENT)
		{
			LM_ERR("authentication failed for <%.*s>\n",
					ri->l_uuid.len, ri->l_uuid.s);
			goto error;
		}
		hdr = get_autenticate_hdr(ps->rpl, ps->code);
		if (hdr==0)
		{
			LM_ERR("failed to extract authenticate hdr\n");
			goto error;
		}

		LM_DBG("auth header body [%.*s]\n",
				hdr->body.len, hdr->body.s);

		if (parse_authenticate_body(&hdr->body, &auth)<0)
		{
			LM_ERR("failed to parse auth hdr body\n");
			goto error;
		}
		if (ri->realm.len>0) {
			/* only check if realms match if it is non-empty */
			if(auth.realm.len!=ri->realm.len
					|| strncmp(auth.realm.s, ri->realm.s, ri->realm.len)!=0)
			{
				LM_ERR("realms do not match. requested realm: [%.*s]\n",
						auth.realm.len, auth.realm.s);
				goto error;
			}
		}
		cred.realm = auth.realm;
		cred.user = ri->auth_username; 
		cred.passwd = ri->auth_password;
		cred.next = NULL;

		snprintf(b_ruri, MAX_URI_SIZE, "sip:%.*s",
				ri->r_domain.len, ri->r_domain.s);
		s_ruri.s = b_ruri; s_ruri.len = strlen(s_ruri.s);

		do_uac_auth(&method, &s_ruri, &cred, &auth, response);
		new_auth_hdr=build_authorization_hdr(ps->code, &s_ruri, &cred,
				&auth, response);
		if (new_auth_hdr==0)
		{
			LM_ERR("failed to build authorization hdr\n");
			goto error;
		}

#ifdef UAC_OLD_AUTH
		snprintf(b_turi, MAX_URI_SIZE, "sip:%.*s@%.*s",
				ri->r_username.len, ri->r_username.s,
				ri->r_domain.len, ri->r_domain.s);
		s_turi.s = b_turi; s_turi.len = strlen(s_turi.s);
#endif
		snprintf(b_hdrs, MAX_UACH_SIZE,
				"Contact: <sip:%.*s@%.*s>\r\n"
				"Expires: %d\r\n"
				"%.*s",
				ri->l_uuid.len, ri->l_uuid.s,
				reg_contact_addr.len, reg_contact_addr.s,
				ri->expires,
				new_auth_hdr->len, new_auth_hdr->s);
		s_hdrs.s = b_hdrs; s_hdrs.len = strlen(s_hdrs.s);
		pkg_free(new_auth_hdr->s);

		memset(&uac_r, 0, sizeof(uac_r));
		if(uac_reg_tmdlg(&tmdlg, ps->rpl)<0)
		{
			LM_ERR("failed to build tm dialog\n");
			goto error;
		}
		tmdlg.rem_target = s_ruri;
		if(ri->auth_proxy.len)
			tmdlg.dst_uri = ri->auth_proxy;
		uac_r.method = &method;
		uac_r.headers = &s_hdrs;
		uac_r.dialog = &tmdlg;
		uac_r.cb_flags = TMCB_LOCAL_COMPLETED;
		/* Callback function */
		uac_r.cb  = uac_reg_tm_callback;
		/* Callback parameter */
		uac_r.cbp = (void*)uuid;
#ifdef UAC_OLD_AUTH
		ret = uac_tmb.t_request(&uac_r,  /* UAC Req */
				&s_ruri, /* Request-URI */
				&s_turi, /* To */
				&s_turi, /* From */
				(ri->auth_proxy.len)?&ri->auth_proxy:NULL /* outbound uri */
				);
#endif
		ret = uac_tmb.t_request_within(&uac_r);

		if(ret<0) {
			LM_ERR("failed to send request with authentication for [%.*s]",
					ri->l_uuid.len, ri->l_uuid.s);
			goto error;
		}

		ri->flags |= UAC_REG_AUTHSENT;
		return;
	} else
	{
		LM_ERR("got sip response %d while registering [%.*s]\n",
				ps->code, ri->l_uuid.len, ri->l_uuid.s);
		goto error;
	}

error:
	if(reg_retry_interval) {
		ri->timer_expires = time(NULL) + reg_retry_interval;
	} else {
		ri->flags |= UAC_REG_DISABLED;
		counter_inc(regdisabled);
	}
done:
	if(ri)
		ri->flags &= ~(UAC_REG_ONGOING|UAC_REG_AUTHSENT);
	shm_free(uuid);
	counter_inc(regactive);
}
Exemple #7
0
int zmq::socket_base_t::bind (const char *addr_)
{
    ENTER_MUTEX ();

    if (unlikely (ctx_terminated)) {
        errno = ETERM;
        EXIT_MUTEX ();
        return -1;
    }

    //  Process pending commands, if any.
    int rc = process_commands (0, false);
    if (unlikely (rc != 0)) {
        EXIT_MUTEX ();
        return -1;
    }

    //  Parse addr_ string.
    std::string protocol;
    std::string address;
    if (parse_uri (addr_, protocol, address) || check_protocol (protocol)) {
        EXIT_MUTEX ();
        return -1;
    }

    if (protocol == "inproc") {
        const endpoint_t endpoint = { this, options };
        rc = register_endpoint (addr_, endpoint);
        if (rc == 0) {
            connect_pending (addr_, this);
            last_endpoint.assign (addr_);
            options.connected = true;
        }
        EXIT_MUTEX ();
        return rc;
    }

    if (protocol == "pgm" || protocol == "epgm" || protocol == "norm" || protocol == "udp") {
        //  For convenience's sake, bind can be used interchangeable with
        //  connect for PGM, EPGM, NORM and UDP transports.
        EXIT_MUTEX ();
        rc = connect (addr_);
        if (rc != -1)
            options.connected = true;
        return rc;
    }

    //  Remaining transports require to be run in an I/O thread, so at this
    //  point we'll choose one.
    io_thread_t *io_thread = choose_io_thread (options.affinity);
    if (!io_thread) {
        errno = EMTHREAD;
        EXIT_MUTEX ();
        return -1;
    }

    if (protocol == "tcp") {
        tcp_listener_t *listener = new (std::nothrow) tcp_listener_t (
            io_thread, this, options);
        alloc_assert (listener);
        rc = listener->set_address (address.c_str ());
        if (rc != 0) {
            LIBZMQ_DELETE(listener);
            event_bind_failed (address, zmq_errno());
            EXIT_MUTEX ();
            return -1;
        }

        // Save last endpoint URI
        listener->get_address (last_endpoint);

        add_endpoint (last_endpoint.c_str (), (own_t *) listener, NULL);
        options.connected = true;
        EXIT_MUTEX ();
        return 0;
    }

#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS
    if (protocol == "ipc") {
        ipc_listener_t *listener = new (std::nothrow) ipc_listener_t (
            io_thread, this, options);
        alloc_assert (listener);
        int rc = listener->set_address (address.c_str ());
        if (rc != 0) {
            LIBZMQ_DELETE(listener);
            event_bind_failed (address, zmq_errno());
            EXIT_MUTEX ();
            return -1;
        }

        // Save last endpoint URI
        listener->get_address (last_endpoint);

        add_endpoint (last_endpoint.c_str (), (own_t *) listener, NULL);
        options.connected = true;
        EXIT_MUTEX ();
        return 0;
    }
#endif
#if defined ZMQ_HAVE_TIPC
    if (protocol == "tipc") {
         tipc_listener_t *listener = new (std::nothrow) tipc_listener_t (
              io_thread, this, options);
         alloc_assert (listener);
         int rc = listener->set_address (address.c_str ());
         if (rc != 0) {
             LIBZMQ_DELETE(listener);
             event_bind_failed (address, zmq_errno());
             EXIT_MUTEX ();
             return -1;
         }

        // Save last endpoint URI
        listener->get_address (last_endpoint);

        add_endpoint (addr_, (own_t *) listener, NULL);
        options.connected = true;
        EXIT_MUTEX ();
        return 0;
    }
#endif
#if defined ZMQ_HAVE_VMCI
    if (protocol == "vmci") {
        vmci_listener_t *listener = new (std::nothrow) vmci_listener_t (
            io_thread, this, options);
        alloc_assert (listener);
        int rc = listener->set_address (address.c_str ());
        if (rc != 0) {
            LIBZMQ_DELETE(listener);
            event_bind_failed (address, zmq_errno ());
            EXIT_MUTEX ();
            return -1;
        }

        listener->get_address (last_endpoint);

        add_endpoint (last_endpoint.c_str(), (own_t *) listener, NULL);
        options.connected = true;
        EXIT_MUTEX ();
        return 0;
    }
#endif

    EXIT_MUTEX ();
    zmq_assert (false);
    return -1;
}
Exemple #8
0
/**
 * _remove - Delete an entire AOR entry or just one or more of its Contacts
 * Parameter format: _remove(domain, AOR[, Contact URI or plain hostname])
 *
 * @udomain:     (udomain_t *)
 * @aor_gp:      address-of-record as a SIP URI (plain string or pvar)
 * @contact_gp:  contact to be deleted or domain in front of multiple contacts
 *
 * @return:      1 on success, negative on failure
 */
int _remove(struct sip_msg *msg, char *udomain, char *aor_gp, char *contact_gp)
{
	static struct sip_uri puri;

	struct hostent delete_he, *he;
	urecord_t *record;
	ucontact_t *contact, *it;
	str uri, aor_user, delete_user = { NULL, 0 };
	int err, count = 0;
	int delete_by_hostname = 0;
	unsigned short delete_port;

	memset(&delete_he, 0, sizeof delete_he);

	if (fixup_get_svalue(msg, (gparam_p)aor_gp, &uri) != 0) {
		LM_ERR("failed to get gparam_t value\n");
		return E_UNSPEC;
	}

	if (parse_uri(uri.s, uri.len, &puri) != 0) {
		LM_ERR("failed to parse aor: '%.*s'\n", uri.len, uri.s);
		return E_BAD_URI;
	}

	aor_user = puri.user;

	ul.lock_udomain((udomain_t *)udomain, &aor_user);

	if (ul.get_urecord((udomain_t *)udomain, &aor_user, &record) != 0) {
		LM_DBG("no record '%.*s' found!\n", aor_user.len, aor_user.s);
		err = 1;
		goto out_unlock;
	}

	/* if no contact uri param is given, delete the whole urecord entry */
	if (!contact_gp) {
		if (ul.delete_urecord((udomain_t *)udomain, &aor_user, record, 0) != 0) {
			LM_ERR("failed to delete urecord for aor '%.*s'\n",
			        aor_user.len, aor_user.s);
			err = E_UNSPEC;
			goto out_unlock;
		}

		err = 1;
		goto out_unlock;
	}

	if (fixup_get_svalue(msg, (gparam_p)contact_gp, &uri) != 0) {
		LM_ERR("failed to retrieve value of contact pv\n");
		err = E_UNSPEC;
		goto out_unlock;
	}

	/* minimum two-letters for the domain name */
	if (uri.len < 5) {
		LM_ERR("Invalid domain given: '%.*s'\n", uri.len, uri.s);
		err = E_INVALID_PARAMS;
		goto out_unlock;
	}

	/* a domain/IP address was given instead of a SIP contact URI */
	if (uri.s[0] != 's' || uri.s[1] != 'i' ||
	    uri.s[2] != 'p' || (uri.s[3] != ':' &&
	                        (uri.s[3] != 's' || uri.s[4] != ':'))) {

		delete_by_hostname = 1;

		he = sip_resolvehost(&uri, &delete_port, &puri.proto, 0, NULL);
		if (!he) {
			LM_ERR("cannot resolve given host: '%.*s'\n", uri.len, uri.s);
			err = E_UNSPEC;
			goto out_unlock;
		}

		LM_DBG("Delete by host: '%s'\n",
		        inet_ntoa(*(struct in_addr *)(he->h_addr_list[0])));
	} else {
		LM_DBG("parsing uri: %.*s\n", uri.len, uri.s);

		if (parse_uri(uri.s, uri.len, &puri) != 0) {
			LM_ERR("failed to parse contact uri: '%.*s'\n",
			        uri.len, uri.s);
			err = E_BAD_URI;
			goto out_unlock;
		}

		delete_user = puri.user;

		he = sip_resolvehost(&puri.host, &delete_port, &puri.proto, 0, NULL);
		if (!he) {
			LM_ERR("cannot resolve given uri: '%.*s'\n", uri.len, uri.s);
			err = E_UNSPEC;
			goto out_unlock;
		}

		if (puri.port_no > 0)
			delete_port  = puri.port_no;

		LM_DBG("Delete by contact: [ User %.*s | Host %s | Port %d ]\n",
		        delete_user.len, delete_user.s,
		        inet_ntoa(*(struct in_addr *)(he->h_addr_list[0])),
				delete_port);
	}

	if (hostent_cpy(&delete_he, he) != 0) {
		LM_ERR("no more pkg mem\n");
		err = E_OUT_OF_MEM;
		goto out_unlock;
	}

	for (it = record->contacts; it; ) {
		contact = it;
		it = it->next;
		count++;

		LM_DBG("parsing contact uri '%.*s'\n", contact->c.len, contact->c.s);

		if (parse_uri(contact->c.s, contact->c.len, &puri) != 0) {
			LM_ERR("failed to parse contact uri: '%.*s'\n",
			        contact->c.len, contact->c.s);
			err = E_BAD_URI;
			goto out_unlock;
		}

		/* if necessary, solve the next_hop towards the contact */
		he = sip_resolvehost(&contact->next_hop.name,
		                     &contact->next_hop.port,
		                     &contact->next_hop.proto, 0, NULL);
		if (!he) {
			LM_ERR("failed to resolve next hop of contact '%.*s'\n",
			        contact->c.len, contact->c.s);
			continue;
		}

		LM_DBG("Contact: [ User %.*s | Host %s | Port %d ]\n",
		        puri.user.len, puri.user.s,
		        inet_ntoa(*(struct in_addr *)(he->h_addr_list[0])),
				puri.port_no);

		if (delete_by_hostname) {
			if (!memcmp(delete_he.h_addr_list[0],
			            he->h_addr_list[0], he->h_length))
			{
				ul.delete_ucontact(record, contact, 0);
				count--;
			}
		} else {
			if (delete_user.len == puri.user.len &&
			    delete_port == puri.port_no &&
			    !memcmp(delete_he.h_addr_list[0],
			            he->h_addr_list[0], he->h_length)
				&& !memcmp(delete_user.s, puri.user.s, puri.user.len))
			{
				ul.delete_ucontact(record, contact, 0);
				count--;
			}
		}
	}

	err = 1;

	/* remove the AOR if no more contacts are attached */
	if (count == 0) {
		if (ul.delete_urecord((udomain_t *)udomain, &aor_user, record, 0) != 0) {
			LM_ERR("failed to delete urecord for aor '%.*s'\n",
			        aor_user.len, aor_user.s);
			err = 1;
		}
	}

out_unlock:
	ul.unlock_udomain((udomain_t *)udomain, &aor_user);
	free_hostent(&delete_he);

	return err;
}
Exemple #9
0
/*! \brief
 * Message contained some contacts, but record with same address
 * of record was not found so we have to create a new record
 * and insert all contacts from the message that have expires
 * > 0
 */
static inline int insert_contacts(struct sip_msg* _m, contact_t* _c,
								udomain_t* _d, str* _a, struct save_ctx *_sctx)
{
	ucontact_info_t* ci;
	urecord_t* r;
	ucontact_t* c;
	unsigned int cflags;
	int num;
	int e;
	int e_max;
	int tcp_check;
	struct sip_uri uri;

	cflags = (_sctx->flags&REG_SAVE_MEMORY_FLAG)?FL_MEM:FL_NONE;
	if (is_tcp_based_proto(_m->rcv.proto) && (_m->flags&tcp_persistent_flag)) {
		e_max = 0;
		tcp_check = 1;
	} else {
		e_max = tcp_check = 0;
	}

	for( num=0,r=0,ci=0 ; _c ; _c = get_next_contact(_c) ) {
		/* calculate expires */
		calc_contact_expires(_m, _c->expires, &e, _sctx);
		/* Skip contacts with zero expires */
		if (e == 0)
			continue;

		if (_sctx->max_contacts && (num >= _sctx->max_contacts)) {
			if (_sctx->flags&REG_SAVE_FORCE_REG_FLAG) {
				/* we are overflowing the number of maximum contacts,
				   so remove the first (oldest) one to prevent this */
				if (r==NULL || r->contacts==NULL) {
					LM_CRIT("BUG - overflow detected with r=%p and "
						"contacts=%p\n",r,r->contacts);
					goto error;
				}
				if (ul.delete_ucontact( r, r->contacts, 0)!=0) {
					LM_ERR("failed to remove contact\n");
					goto error;
				}
			} else {
				LM_INFO("too many contacts (%d) for AOR <%.*s>, max=%d\n",
						num, _a->len, _a->s, _sctx->max_contacts);
				rerrno = R_TOO_MANY;
				goto error;
			}
		} else {
			num++;
		}

		if (r==0) {
			if (ul.insert_urecord(_d, _a, &r, 0) < 0) {
				rerrno = R_UL_NEW_R;
				LM_ERR("failed to insert new record structure\n");
				goto error;
			}
		}

		/* pack the contact_info */
		if ( (ci=pack_ci( (ci==0)?_m:0, _c, e, cflags, _sctx->flags))==0 ) {
			LM_ERR("failed to extract contact info\n");
			goto error;
		}

		if ( r->contacts==0 ||
		ul.get_ucontact(r, &_c->uri, ci->callid, ci->cseq+1, &c)!=0 ) {
			if (ul.insert_ucontact( r, &_c->uri, ci, &c, 0) < 0) {
				rerrno = R_UL_INS_C;
				LM_ERR("failed to insert contact\n");
				goto error;
			}
		} else {
			if (ul.update_ucontact( r, c, ci, 0) < 0) {
				rerrno = R_UL_UPD_C;
				LM_ERR("failed to update contact\n");
				goto error;
			}
		}

		if (tcp_check) {
			/* parse contact uri to see if transport is TCP */
			if (parse_uri( _c->uri.s, _c->uri.len, &uri)<0) {
				LM_ERR("failed to parse contact <%.*s>\n",
						_c->uri.len, _c->uri.s);
			} else if ( is_tcp_based_proto(uri.proto) ) {
				if (e_max) {
					LM_WARN("multiple TCP contacts on single REGISTER\n");
					if (e>e_max) e_max = e;
				} else {
					e_max = e;
				}
			}
		}
	}

	if (r) {
		if (r->contacts) {
			build_contact(r->contacts,_m);
		}
		ul.release_urecord(r, 0);
	}

	if ( tcp_check && e_max>0 ) {
		e_max -= act_time;
		trans_set_dst_attr( &_m->rcv, DST_FCNTL_SET_LIFETIME,
			(void*)(long)(e_max + 10) );
	}

	return 0;
error:
	if (r)
		ul.delete_urecord(_d, _a, r, 0);
	return -1;
}
Exemple #10
0
int zmq::socket_base_t::term_endpoint (const char *addr_)
{
    ENTER_MUTEX();

    //  Check whether the library haven't been shut down yet.
    if (unlikely (ctx_terminated)) {
        errno = ETERM;
        EXIT_MUTEX();
        return -1;
    }

    //  Check whether endpoint address passed to the function is valid.
    if (unlikely (!addr_)) {
        errno = EINVAL;
        EXIT_MUTEX();
        return -1;
    }

    //  Process pending commands, if any, since there could be pending unprocessed process_own()'s
    //  (from launch_child() for example) we're asked to terminate now.
    int rc = process_commands (0, false);
    if (unlikely(rc != 0)) {
        EXIT_MUTEX();
        return -1;
    }

    //  Parse addr_ string.
    std::string protocol;
    std::string address;
    if (parse_uri(addr_, protocol, address) || check_protocol(protocol)) {
        EXIT_MUTEX();
        return -1;
    }

    // Disconnect an inproc socket
    if (protocol == "inproc") {
        if (unregister_endpoint (std::string(addr_), this) == 0) {
            EXIT_MUTEX();
            return 0;
        }
        std::pair <inprocs_t::iterator, inprocs_t::iterator> range = inprocs.equal_range (std::string (addr_));
        if (range.first == range.second) {
            errno = ENOENT;
            EXIT_MUTEX();
            return -1;
        }

        for (inprocs_t::iterator it = range.first; it != range.second; ++it)
            it->second->terminate (true);
        inprocs.erase (range.first, range.second);
        EXIT_MUTEX();
        return 0;
    }

    //  Find the endpoints range (if any) corresponding to the addr_ string.
    std::pair <endpoints_t::iterator, endpoints_t::iterator> range = endpoints.equal_range (std::string (addr_));
    if (range.first == range.second) {
        errno = ENOENT;
        EXIT_MUTEX();
        return -1;
    }

    for (endpoints_t::iterator it = range.first; it != range.second; ++it) {
        //  If we have an associated pipe, terminate it.
        if (it->second.second != NULL)
            it->second.second->terminate (false);
        term_child (it->second.first);
    }
    endpoints.erase (range.first, range.second);
    EXIT_MUTEX();
    return 0;
}
Exemple #11
0
/*
 * Calculate dialog hooks
 * @return:
 *  negative : error
 *  0 : no routes present
 *  F_RB_NH_LOOSE : routes present, next hop is loose router
 *  F_RB_NH_STRICT: next hop is strict.
 */
static inline int calculate_hooks(dlg_t* _d)
{
	str* uri;
	struct sip_uri puri;
	int nhop;

	/* we might re-calc. some existing hooks =>
	 * reset all the hooks to 0 */
	memset(&_d->hooks, 0, sizeof(_d->hooks));
	if (_d->route_set) {
		uri = &_d->route_set->nameaddr.uri;
		if (parse_uri(uri->s, uri->len, &puri) < 0) {
			LOG(L_ERR, "calculate_hooks(): Error while parsing URI\n");
			return -1;
		}
		
		if (puri.lr.s) {
			if (_d->rem_target.s) _d->hooks.request_uri = &_d->rem_target;
			else _d->hooks.request_uri = &_d->rem_uri;
			_d->hooks.next_hop = &_d->route_set->nameaddr.uri;
			_d->hooks.first_route = _d->route_set;
			nhop = F_RB_NH_LOOSE;
		} else {
			_d->hooks.request_uri = &_d->route_set->nameaddr.uri;
			_d->hooks.next_hop = _d->hooks.request_uri;
			_d->hooks.first_route = _d->route_set->next;
			if (_d->rem_target.len > 0) 
				_d->hooks.last_route = &_d->rem_target;
			else 
				_d->hooks.last_route = NULL; /* ? */
			nhop = F_RB_NH_STRICT;
		}
	} else {
		if (_d->rem_target.s) _d->hooks.request_uri = &_d->rem_target;
		else _d->hooks.request_uri = &_d->rem_uri;
		
		if (_d->dst_uri.s) _d->hooks.next_hop = &_d->dst_uri;
		else _d->hooks.next_hop = _d->hooks.request_uri;

		nhop = 0;
		/*
		 * the routes in the hooks need to be reset because if the route_set 
		 * was dropped somewhere else then these will remain set without the
		 * actual routes existing any more
		 */
		_d->hooks.first_route = 0;
		_d->hooks.last_route = 0;
	}

	if ((_d->hooks.request_uri) && (_d->hooks.request_uri->s) && (_d->hooks.request_uri->len)) {
		_d->hooks.ru.s = _d->hooks.request_uri->s;
		_d->hooks.ru.len = _d->hooks.request_uri->len;
		_d->hooks.request_uri = &_d->hooks.ru;
		get_raw_uri(_d->hooks.request_uri);
	}
	if ((_d->hooks.next_hop) && (_d->hooks.next_hop->s) && (_d->hooks.next_hop->len)) {
		_d->hooks.nh.s = _d->hooks.next_hop->s;
		_d->hooks.nh.len = _d->hooks.next_hop->len;
		_d->hooks.next_hop = &_d->hooks.nh;
		get_raw_uri(_d->hooks.next_hop);
	}

	return nhop;
}
Exemple #12
0
static void
standard_request_handler(void *cls,
                        struct SPDY_Request * request,
                        uint8_t priority,
                        const char *method,
                        const char *path,
                        const char *version,
                        const char *host,
                        const char *scheme,
                        struct SPDY_NameValue * headers)
{
	(void)cls;
	(void)priority;
	(void)host;
	(void)scheme;
	
	struct Proxy *proxy;
	int ret;
  struct URI *uri;
  struct SPDY_Session *session;
	
	PRINT_VERBOSE2("received request for '%s %s %s'\n", method, path, version);
  
	if(NULL == (proxy = malloc(sizeof(struct Proxy))))
        DIE("No memory");
	memset(proxy, 0, sizeof(struct Proxy));
  
  session = SPDY_get_session_for_request(request);
  assert(NULL != session);
  proxy->session_alive = SPDY_get_cls_from_session(session);
  assert(NULL != proxy->session_alive);
  
	proxy->request = request;
	if(NULL == (proxy->headers = SPDY_name_value_create()))
        DIE("No memory");
  
  if(glob_opt.transparent)
  {
    if(NULL != glob_opt.http_backend) //use always same host
      ret = asprintf(&(proxy->url),"%s://%s%s", scheme, glob_opt.http_backend, path);
    else //use host header
      ret = asprintf(&(proxy->url),"%s://%s%s", scheme, host, path);
    if(-1 == ret)
        DIE("No memory");
        
    ret = parse_uri(&uri_preg, proxy->url, &uri);
    if(ret != 0)
      DIE("parsing built uri failed");
  }
  else
  {
    ret = parse_uri(&uri_preg, path, &uri);
    PRINT_INFO2("path %s '%s' '%s'", path, uri->scheme, uri->host);
    if(ret != 0 || !strlen(uri->scheme) || !strlen(uri->host))
      DIE("parsing received uri failed");
      
    if(NULL != glob_opt.http_backend) //use backend host
    {
      ret = asprintf(&(proxy->url),"%s://%s%s", uri->scheme, glob_opt.http_backend, uri->path_and_more);
      if(-1 == ret)
        DIE("No memory");
    }
    else //use request path
      if(NULL == (proxy->url = strdup(path)))
        DIE("No memory");
  }
  
  free_uri(uri);
  
  PRINT_VERBOSE2("curl will request '%s'", proxy->url);
    
  SPDY_name_value_iterate(headers, &iterate_cb, proxy);
	
	if(NULL == (proxy->curl_handle = curl_easy_init()))
    {
		PRINT_INFO("curl_easy_init failed");
		abort();
	}
	
	if(glob_opt.curl_verbose)
    CURL_SETOPT(proxy->curl_handle, CURLOPT_VERBOSE, 1);
	CURL_SETOPT(proxy->curl_handle, CURLOPT_URL, proxy->url);
	if(glob_opt.http10)
		CURL_SETOPT(proxy->curl_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
	CURL_SETOPT(proxy->curl_handle, CURLOPT_WRITEFUNCTION, curl_write_cb);
	CURL_SETOPT(proxy->curl_handle, CURLOPT_WRITEDATA, proxy);
	CURL_SETOPT(proxy->curl_handle, CURLOPT_HEADERFUNCTION, curl_header_cb);
	CURL_SETOPT(proxy->curl_handle, CURLOPT_HEADERDATA, proxy);
	CURL_SETOPT(proxy->curl_handle, CURLOPT_PRIVATE, proxy);
	CURL_SETOPT(proxy->curl_handle, CURLOPT_HTTPHEADER, proxy->curl_headers);
  CURL_SETOPT(proxy->curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
  CURL_SETOPT(proxy->curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);
  if(glob_opt.ipv4 && !glob_opt.ipv6)
    CURL_SETOPT(proxy->curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
  else if(glob_opt.ipv6 && !glob_opt.ipv4)
    CURL_SETOPT(proxy->curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
	
	if(CURLM_OK != (ret = curl_multi_add_handle(multi_handle, proxy->curl_handle)))
	{
		PRINT_INFO2("curl_multi_add_handle failed (%i)", ret);
		abort();
	}
    
  //~5ms additional latency for calling this
	if(CURLM_OK != (ret = curl_multi_perform(multi_handle, &still_running))
		&& CURLM_CALL_MULTI_PERFORM != ret)
	{
		PRINT_INFO2("curl_multi_perform failed (%i)", ret);
		abort();
	}
  
  call_curl_run = true;
}
Exemple #13
0
/* This function extracts meta-info from the sip_msg structure and
 * formats it so that it can be used to rapidly access the message structured
 * parts.
 *
 * RETURNS: LENGTH of structure on success, <0 if failure
 * if there was failure, you don't need to pkg_free the payload (it is done inside).
 * if there was success, you __NEED_TO_PKG_FREE_THE_PAYLOAD__ from the calling function.
 *
 * The encoded meta-info is composed by 3 sections:
 *
 * MSG_META_INFO:
 * 2: short int in network-byte-order, if <100, the msg is a REQUEST and the int
 * is the code of the METHOD. if >100, it is a RESPONSE and the int is the code
 * of the response.
 * 2: short int in NBO: payload-start based pointer (index) to where the SIP MSG starts.
 * 2: short int in NBO: the sip-message length
 * 2: METHOD or CODE string SIP-START-based pointer and length
 * 2: R-URI or REASON PHRASE string SIP-START-based pointer and length
 * 2: VERSION string SIP-START-based pointer and length
 * 2: short int in NBO: start of the content of the SIP message
 * [1+N]: in case this is a request, the length of the encoded-uri and the encoded-uri
 * 1: how many present headers have been found.
 *
 * MSG_HEADERS_INDEX:
 * N*3: groups of 3 bytes, each one describing a header struct: the first byte
 * is a letter that corresponds to a header type, the second and third bytes are a NBO
 * inidex to where this struct begins within the HEADERS_META_INFO section.
 *
 * HEADERS_META_INFO:
 * M: all the codified headers meta info structs one after another
 *
 * SIP_MSG:
 * the SIP message as it has been received.
 *
 * The length of the structure, will be ((short*)payload)[1] + ((short*)payload)[2]
 *
 * TODO: msg->parsed_uri msg->parsed_orig_uri_ok, msg->first_line->u.request.uri
 * buggy and little bit fuzzy
 */
int encode_msg(struct sip_msg *msg,char *payload,int len)
{
   int i,j,k,u,request;
   unsigned short int h;
   struct hdr_field* hf;
   struct msg_start* ms;
   struct sip_uri miuri;
   char *myerror=NULL;
   ptrdiff_t diff;
   str body = {NULL,0};

   if(len < MAX_ENCODED_MSG + MAX_MESSAGE_LEN)
      return -1;
   if(parse_headers(msg,HDR_EOH_F,0)<0){
      myerror="in parse_headers";
      goto error;
   }
   memset(payload,0,len);
   ms=&msg->first_line;
	if(ms->type == SIP_REQUEST)
		request=1;
	else if(ms->type == SIP_REPLY)
		request=0;
	else{
		myerror="message is neither request nor response";
		goto error;
	}
	if(request) {
		for(h=0,j=1;h<32;j=(0x01<<h),h++)
			if(j & ms->u.request.method_value)
				break;
	} else {
		h=(unsigned short)(ms->u.reply.statuscode);
	}
   if(h==32){/*statuscode wont be 32...*/
      myerror="unknown message type\n";
      goto error;
   }
   h=htons(h);
   /*first goes the message code type*/
   memcpy(payload,&h,2);
   h=htons((unsigned short int)msg->len);
   /*then goes the message start idx, but we'll put it later*/
   /*then goes the message length (we hope it to be less than 65535 bytes...)*/
   memcpy(&payload[MSG_LEN_IDX],&h,2);
   /*then goes the content start index (starting from SIP MSG START)*/
   if (get_body(msg,&body) < 0) {
      myerror="body parsing failed";
      goto error;
   }
   if(0>(diff=(body.s-msg->buf))){
      myerror="body starts before the message (uh ?)";
      goto error;
   }else
      h=htons((unsigned short int)diff);
   memcpy(payload+CONTENT_IDX,&h,2);
   payload[METHOD_CODE_IDX]=(unsigned char)(request?
	 (ms->u.request.method.s-msg->buf):
	 (ms->u.reply.status.s-msg->buf));
   payload[METHOD_CODE_IDX+1]=(unsigned char)(request?
	 (ms->u.request.method.len):
	 (ms->u.reply.status.len));
   payload[URI_REASON_IDX]=(unsigned char)(request?
	 (ms->u.request.uri.s-msg->buf):
	 (ms->u.reply.reason.s-msg->buf));
   payload[URI_REASON_IDX+1]=(unsigned char)(request?
	 (ms->u.request.uri.len):
	 (ms->u.reply.reason.len));
   payload[VERSION_IDX]=(unsigned char)(request?
	 (ms->u.request.version.s-msg->buf):
	 (ms->u.reply.version.s-msg->buf));
   if(request){
      if (parse_uri(ms->u.request.uri.s,ms->u.request.uri.len, &miuri)<0){
	 LM_ERR("<%.*s>\n",ms->u.request.uri.len,ms->u.request.uri.s);
	 myerror="while parsing the R-URI";
	 goto error;
      }
      if(0>(j=encode_uri2(msg->buf,
		  ms->u.request.method.s-msg->buf+ms->len,
		  ms->u.request.uri,&miuri,
		  (unsigned char*)&payload[REQUEST_URI_IDX+1])))
      {
	    myerror="ENCODE_MSG: ERROR while encoding the R-URI";
	    goto error;
      }
      payload[REQUEST_URI_IDX]=(unsigned char)j;
      k=REQUEST_URI_IDX+1+j;
   }else
      k=REQUEST_URI_IDX;
   u=k;
   k++;
   for(i=0,hf=msg->headers;hf;hf=hf->next,i++);
   i++;/*we do as if there was an extra header, that marks the end of
	 the previous header in the headers hashtable(read below)*/
   j=k+3*i;
   for(i=0,hf=msg->headers;hf;hf=hf->next,k+=3){
      payload[k]=(unsigned char)(hf->type & 0xFF);
      h=htons(j);
      /*now goes a payload-based-ptr to where the header-code starts*/
      memcpy(&payload[k+1],&h,2);
      /*TODO fix this... fixed with k-=3?*/
      if(0>(i=encode_header(msg,hf,(unsigned char*)(payload+j),MAX_ENCODED_MSG+MAX_MESSAGE_LEN-j))){
	 LM_ERR("encoding header %.*s\n",hf->name.len,hf->name.s);
	 goto error;
	 /* XXX: not sure if this should be considered or not, but the code is
	  * not executed anyway; commenting it for now.
	 k-=3;
	 continue;
	 */
      }
      j+=(unsigned short int)i;
   }
   /*now goes the number of headers that have been found, right after the meta-msg-section*/
   payload[u]=(unsigned char)((k-u-1)/3);
   j=htons(j);
   /*now copy the number of bytes that the headers-meta-section has occupied,right afther
    * headers-meta-section(the array with ['v',[2:where],'r',[2:where],'R',[2:where],...]
    * this is to know where the LAST header ends, since the length of each header-struct
    * is calculated substracting the nextHeaderStart - presentHeaderStart
    * the k+1 is because payload[k] is usually the letter*/
   memcpy(&payload[k+1],&j,2);
   k+=3;
   j=ntohs(j);
   /*now we copy the headers-meta-section after the msg-headers-meta-section*/
   /*memcpy(&payload[k],payload2,j);*/
   /*j+=k;*/
   /*pkg_free(payload2);*/
   /*now we copy the actual message after the headers-meta-section*/
   memcpy(&payload[j],msg->buf,msg->len);
   LM_DBG("msglen = %d,msg starts at %d\n",msg->len,j);
   j=htons(j);
   /*now we copy at the beginning, the index to where the actual message starts*/
   memcpy(&payload[MSG_START_IDX],&j,2);
   return GET_PAY_SIZE( payload );
error:
   LM_ERR("%s\n",myerror);
   return -1;
}
Exemple #14
0
int ds_load_list(char *lfile)
{
	char line[256], *p;
	FILE *f = NULL;
	int id, i, j, setn;
	str uri;
	struct sip_uri puri;
	ds_dest_p dp = NULL, dp0 = NULL;
	ds_set_p  sp = NULL, sp0 = NULL;
	ds_setidx_p si = NULL, si0 = NULL;
	
	if(lfile==NULL || strlen(lfile)<=0)
	{
		LOG(L_ERR, "DISPATCHER:ds_load_list: bad list file\n");
		return -1;
	}

	f = fopen(lfile, "r");
	if(f==NULL)
	{
		LOG(L_ERR, "DISPATCHER:ds_load_list: can't open list file [%s]\n",
				lfile);
		return -1;
		
	}

	id = setn = 0;
	p = fgets(line, 256, f);
	while(p)
	{
		/* eat all white spaces */
		while(*p && (*p==' ' || *p=='\t' || *p=='\r' || *p=='\n'))
			p++;
		if(*p=='\0' || *p=='#')
			goto next_line;
		
		/* get set id */
		id = 0;
		while(*p>='0' && *p<='9')
		{
			id = id*10+ (*p-'0');
			p++;
		}
		
		/* eat all white spaces */
		while(*p && (*p==' ' || *p=='\t' || *p=='\r' || *p=='\n'))
			p++;
		if(*p=='\0' || *p=='#')
		{
			LOG(L_ERR, "DISPATCHER:ds_load_list: bad line [%s]\n", line);
			goto error;
		}

		/* get uri */
		uri.s = p;
		while(*p && *p!=' ' && *p!='\t' && *p!='\r' && *p!='\n' && *p!='#')
			p++;
		uri.len = p-uri.s;

		/* check uri */
		if(parse_uri(uri.s, uri.len, &puri)!=0)
		{
			LOG(L_ERR, "DISPATCHER:ds_load_list: bad uri [%.*s]\n",
					uri.len, uri.s);
			goto error;
		}
		
		/* check index */
		si = _ds_index;
		while(si)
		{
			if(si->id == id)
				break;
			si = si->next;
		}

		if(si==NULL)
		{
			si = (ds_setidx_p)pkg_malloc(sizeof(ds_setidx_t));
			if(si==NULL)
			{
				LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory\n");
				goto error;
			}
			memset(si, 0, sizeof(ds_setidx_t));
			si->id = id;
			si->next = _ds_index;
			if(_ds_index!=NULL)
				si->index = _ds_index->index + 1;
			
			_ds_index = si;
		}
		
		/* get dest set */
		sp = _ds_list;
		while(sp)
		{
			if(sp->id == id)
				break;
			sp = sp->next;
		}

		if(sp==NULL)
		{
			sp = (ds_set_p)pkg_malloc(sizeof(ds_set_t));
			if(sp==NULL)
			{
				LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory.\n");
				goto error;
			}
			memset(sp, 0, sizeof(ds_set_t));
			sp->next = _ds_list;
			_ds_list = sp;
			setn++;
		}
		sp->id = id;
		sp->nr++;
		sp->index = si->index;

		/* store uri */
		dp = (ds_dest_p)pkg_malloc(sizeof(ds_dest_t));
		if(dp==NULL)
		{
			LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory!\n");
			goto error;
		}
		memset(dp, 0, sizeof(ds_dest_t));

		dp->uri.s = (char*)pkg_malloc(uri.len+1);
		if(dp->uri.s==NULL)
		{
			LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory!!\n");
			pkg_free(dp);
			goto error;
		}
		strncpy(dp->uri.s, uri.s, uri.len);
		dp->uri.s[uri.len]='\0';
		dp->uri.len = uri.len;

		dp->next = sp->dlist;
		sp->dlist = dp;
		DBG("DISPATCHER:ds_load_list: dest [%d/%d/%d] <%.*s>\n", sp->index,
				sp->id, sp->nr, dp->uri.len, dp->uri.s);
		
next_line:
		p = fgets(line, 256, f);
	}
		
	fclose(f);
	f = NULL;
	
	DBG("DISPATCHER:ds_load_list: found [%d] dest sets\n", setn);
	
	/* re-index destination sets for fast access */
	sp0 = (ds_set_p)pkg_malloc(setn*sizeof(ds_set_t));
	if(sp0==NULL)
	{
		LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory!!\n");
		goto error;
	}
	memset(sp0, 0, setn*sizeof(ds_set_t));
	sp = _ds_list;
	for(i=setn-1; i>=0; i--)
	{
		memcpy(&sp0[i], sp, sizeof(ds_set_t));
		if(i==setn-1)
			sp0[i].next = NULL;
		else
			sp0[i].next = &sp0[i+1];
		dp0 = (ds_dest_p)pkg_malloc(sp0[i].nr*sizeof(ds_dest_t));
		if(dp0==NULL)
		{
			LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory!\n");
			ds_destroy_list();
			goto error;
		}
		memset(dp0, 0, sp0[i].nr*sizeof(ds_dest_t));
		dp = sp0[i].dlist;
		for(j=sp0[i].nr-1; j>=0; j--)
		{
			memcpy(&dp0[j], dp, sizeof(ds_dest_t));
			if(j==sp0[j].nr-1)
				dp0[j].next = NULL;
			else
				dp0[j].next = &dp0[j+1];
			dp = dp->next;
		}
		sp0[i].dlist = dp0;
		sp = sp->next;
	}
	
	sp = _ds_list;
	_ds_list = sp0;
	while(sp)
	{
		dp = sp->dlist;
		while(dp)
		{
			dp0 = dp;
			dp = dp->next;
			pkg_free(dp0);
		}
		sp0 = sp;
		sp = sp->next;
		pkg_free(sp0);
	}
	
	return 0;

error:
	if(f!=NULL)
		fclose(f);

	si = _ds_index;
	while(si)
	{
		si0 = si;
		si = si->next;
		pkg_free(si0);
	}
	_ds_index = NULL;

	sp = _ds_list;
	while(sp)
	{
		dp = sp->dlist;
		while(dp)
		{
			if(dp->uri.s!=NULL)
				pkg_free(dp->uri.s);
			dp->uri.s=NULL;
			dp0 = dp;
			dp = dp->next;
			pkg_free(dp0);
		}
		sp0 = sp;
		sp = sp->next;
		pkg_free(sp0);
	}
	return -1;
}
Exemple #15
0
static int ki_xcaps_put(sip_msg_t* msg, str* uri, str* path,
		str* pbody)
{
	struct sip_uri turi;
	str body = {0, 0};
	str etag = {0, 0};
	str etag_hdr = {0, 0};
	str tbuf;
	str nbuf = {0, 0};
	str allow = {0, 0};
	xcap_uri_t xuri;

	if(uri->s==NULL || uri->len == 0)
	{
		LM_ERR("invalid uri parameter\n");
		goto error;
	}

	if(path->s==NULL || path->len == 0)
	{
		LM_ERR("invalid path parameter\n");
		return -1;
	}

	if(parse_uri(uri->s, uri->len, &turi)!=0)
	{
		LM_ERR("parsing uri parameter [%.*s]\n", uri->len, uri->s);
		goto error;
	}

	if(xcap_parse_uri(path, &xcaps_root, &xuri)<0)
	{
		LM_ERR("cannot parse xcap uri [%.*s]\n", path->len, path->s);
		goto error;
	}

	switch(xuri.type)
	{
	case DIRECTORY:
	case XCAP_CAPS:
		allow.s = xcaps_hdr_buf;
		allow.len = snprintf(allow.s, XCAPS_HDR_SIZE, "Allow: GET\r\n");
		xcaps_send_reply(msg, 405, &xcaps_str_notallowed, &allow, NULL, NULL);
		break;
	case SEARCH:
		allow.s = xcaps_hdr_buf;
		allow.len = snprintf(allow.s, XCAPS_HDR_SIZE, "Allow: POST\r\n");
		xcaps_send_reply(msg, 405, &xcaps_str_notallowed, &allow, NULL, NULL);
		break;
	default:
		if(pbody->len <= 0)
		{
			LM_ERR("invalid body parameter\n");
			goto error;
		}
		body.s = (char*)pkg_malloc(pbody->len+1);
		if(body.s==NULL)
		{
			LM_ERR("no more pkg\n");
			goto error;
		}
		memcpy(body.s, pbody->s, pbody->len);
		body.len = pbody->len;
		body.s[body.len] = '\0';

		xcaps_get_db_etag(&turi.user, &turi.host, &xuri, &etag);
		if(check_preconditions(msg, etag)!=1)
		{
			xcaps_send_reply(msg, 412, &xcaps_str_precon, NULL, NULL, NULL);

			pkg_free(body.s);
			return -2;
		}

		if(xuri.nss!=NULL && xuri.node.len>0)
		{
			/* partial document upload
			 *   - fetch, update, delete and store
			 */
			if(xcaps_get_db_doc(&turi.user, &turi.host, &xuri, &tbuf) != 0)
			{
				LM_ERR("could not fetch xcap document\n");
				goto error;
			}
			if(xcaps_xpath_hack(&tbuf, 0)<0)
			{
				LM_ERR("could not hack xcap document\n");
				goto error;
			}
			if(xcaps_xpath_set(&tbuf, &xuri.node, &body, &nbuf)<0)
			{
				LM_ERR("could not update xcap document\n");
				goto error;
			}
			if(nbuf.len<=0)
			{
				LM_ERR("no new content\n");
				goto error;
			}
			pkg_free(body.s);
			body = nbuf;
			if(xcaps_xpath_hack(&body, 1)<0)
			{
				LM_ERR("could not hack xcap document\n");
				goto error;
			}
		}

		if(xcaps_generate_etag_hdr(&etag_hdr)<0)
		{
			LM_ERR("could not generate etag\n");
			goto error;
		}
		etag.s = etag_hdr.s + 7; /* 'ETag: "' */
		etag.len = etag_hdr.len - 10; /* 'ETag: "  "\r\n' */
		if(xcaps_put_db(&turi.user, &turi.host,
					&xuri, &etag, &body)<0)
		{
			LM_ERR("could not store document\n");
			goto error;
		}
		xcaps_send_reply(msg, 200, &xcaps_str_ok, &etag_hdr,
					NULL, NULL);

		if(body.s!=NULL)
			pkg_free(body.s);

		break;
	}

	return 1;

error:
	xcaps_send_reply(msg, 500, &xcaps_str_srverr, NULL, NULL, NULL);
	if(body.s!=NULL)
		pkg_free(body.s);
	return -1;
}
Exemple #16
0
/*! \brief
 * Message contained some contacts and appropriate
 * record was found, so we have to walk through
 * all contacts and do the following:
 * 1) If contact in usrloc doesn't exists and
 *    expires > 0, insert new contact
 * 2) If contact in usrloc exists and expires
 *    > 0, update the contact
 * 3) If contact in usrloc exists and expires
 *    == 0, delete contact
 */
static inline int update_contacts(struct sip_msg* _m, urecord_t* _r,
										contact_t* _c, struct save_ctx *_sctx)
{
	ucontact_info_t *ci;
	ucontact_t *c, *c_last, *c_it;
	int e;
	unsigned int cflags;
	int ret;
	int num;
	int e_max;
	int tcp_check;
	struct sip_uri uri;

	/* mem flag */
	cflags = (_sctx->flags&REG_SAVE_MEMORY_FLAG)?FL_MEM:FL_NONE;

	/* pack the contact_info */
	if ( (ci=pack_ci( _m, 0, 0, cflags, _sctx->flags))==0 ) {
		LM_ERR("failed to initial pack contact info\n");
		goto error;
	}

	/* count how many contacts we have right now */
	num = 0;
	if (_sctx->max_contacts) {
		c = _r->contacts;
		while(c) {
			if (VALID_CONTACT(c, act_time)) num++;
			c = c->next;
		}
	}

	if (is_tcp_based_proto(_m->rcv.proto) && (_m->flags&tcp_persistent_flag)) {
		e_max = -1;
		tcp_check = 1;
	} else {
		e_max = tcp_check = 0;
	}

	for( ; _c ; _c = get_next_contact(_c) ) {
		/* calculate expires */
		calc_contact_expires(_m, _c->expires, &e, _sctx);

		/* search for the contact*/
		ret = ul.get_ucontact( _r, &_c->uri, ci->callid, ci->cseq, &c);
		if (ret==-1) {
			LM_ERR("invalid cseq for aor <%.*s>\n",_r->aor.len,_r->aor.s);
			rerrno = R_INV_CSEQ;
			goto error;
		} else if (ret==-2) {
			continue;
		}

		if ( ret > 0 ) {
			/* Contact not found -> expired? */
			if (e==0)
				continue;

			/* we need to add a new contact -> too many ?? */
			while (_sctx->max_contacts && num>=_sctx->max_contacts) {
				if (_sctx->flags&REG_SAVE_FORCE_REG_FLAG) {
					/* we are overflowing the number of maximum contacts,
					   so remove the oldest valid one to prevent this */
					for( c_it=_r->contacts,c_last=NULL ; c_it ;
					c_it=c_it->next )
						if (VALID_CONTACT(c_it, act_time))
							c_last=c_it;
					if (c_last==NULL) {
						LM_CRIT("BUG - overflow detected but no valid "
							"contacts found :( \n");
						goto error;
					}
					LM_DBG("overflow on inserting new contact -> removing "
						"<%.*s>\n", c_last->c.len, c_last->c.s);
					if (ul.delete_ucontact( _r, c_last, 0)!=0) {
						LM_ERR("failed to remove contact\n");
						goto error;
					}
					num--;
				} else {
					LM_INFO("too many contacts for AOR <%.*s>, max=%d\n",
						_r->aor.len, _r->aor.s, _sctx->max_contacts);
					rerrno = R_TOO_MANY;
					return -1;
				}
			}

			/* pack the contact_info */
			if ( (ci=pack_ci( 0, _c, e, 0, _sctx->flags))==0 ) {
				LM_ERR("failed to extract contact info\n");
				goto error;
			}

			if (ul.insert_ucontact( _r, &_c->uri, ci, &c, 0) < 0) {
				rerrno = R_UL_INS_C;
				LM_ERR("failed to insert contact\n");
				goto error;
			}
		} else {
			/* Contact found */
			if (e == 0) {
				/* it's expired */
				if (_sctx->flags&REG_SAVE_MEMORY_FLAG) {
					c->flags |= FL_MEM;
				} else {
					c->flags &= ~FL_MEM;
				}

				if (ul.delete_ucontact(_r, c, 0) < 0) {
					rerrno = R_UL_DEL_C;
					LM_ERR("failed to delete contact\n");
					goto error;
				}
			} else {
				/* do update */
				/* if the contact to be updated is not valid, it will be after
				 * update, so need to compensate the total number of contact */
				if ( !VALID_CONTACT(c,act_time) )
					num++;
				while ( _sctx->max_contacts && num>_sctx->max_contacts ) {
					if (_sctx->flags&REG_SAVE_FORCE_REG_FLAG) {
						/* we are overflowing the number of maximum contacts,
						   so remove the first (oldest) one to prevent this 
						   (but not the one to be updated !) */
						for( c_it=_r->contacts,c_last=NULL ; c_it ;
						c_it=c_it->next )
							if (VALID_CONTACT(c_it, act_time) && c_it!=c)
								c_last=c_it;
						if (c_last==NULL) {
							LM_CRIT("BUG - overflow detected but no "
								"valid contacts found :( \n");
							goto error;
						}
						LM_DBG("overflow on update -> removing contact "
							"<%.*s>\n", c_last->c.len, c_last->c.s);
						if (ul.delete_ucontact( _r, c_last, 0)!=0) {
							LM_ERR("failed to remove contact\n");
							goto error;
						}
						num--;
					} else {
						LM_INFO("too many contacts for AOR <%.*s>, max=%d\n",
							_r->aor.len, _r->aor.s, _sctx->max_contacts);
						rerrno = R_TOO_MANY;
						return -1;
					}
				}

				/* pack the contact specific info */
				if ( (ci=pack_ci( 0, _c, e, 0, _sctx->flags))==0 ) {
					LM_ERR("failed to pack contact specific info\n");
					goto error;
				}

				if (ul.update_ucontact(_r, c, ci, 0) < 0) {
					rerrno = R_UL_UPD_C;
					LM_ERR("failed to update contact\n");
					goto error;
				}
			}
		}
		if (tcp_check) {
			/* parse contact uri to see if transport is TCP */
			if (parse_uri( _c->uri.s, _c->uri.len, &uri)<0) {
				LM_ERR("failed to parse contact <%.*s>\n",
						_c->uri.len, _c->uri.s);
			} else if (is_tcp_based_proto(uri.proto)) {
				if (e_max>0) {
					LM_WARN("multiple TCP contacts on single REGISTER\n");
				}
				if (e>e_max) e_max = e;
			}
		}
	}

	if ( tcp_check && e_max>-1 ) {
		if (e_max) e_max -= act_time;
		trans_set_dst_attr( &_m->rcv, DST_FCNTL_SET_LIFETIME,
			(void*)(long)(e_max + 10) );
	}

	return 0;
error:
	return -1;
}
Exemple #17
0
int uac_reg_request_to(struct sip_msg *msg, str *src, unsigned int mode)
{
	char ruri[MAX_URI_SIZE];
	struct sip_uri puri;
	reg_uac_t *reg = NULL;
	pv_value_t val;
	struct action act;
	struct run_act_ctx ra_ctx;

	switch(mode)
	{
		case 0:
			reg = reg_ht_get_byuuid(src);
			break;
		case 1:
			if(reg_use_domain)
			{
				if (parse_uri(src->s, src->len, &puri)!=0)
				{
					LM_ERR("failed to parse uri\n");
					return -2;
				}
				reg = reg_ht_get_byuser(&puri.user, &puri.host);
			} else {
				reg = reg_ht_get_byuser(src, NULL);
			}
			break;
		default:
			LM_ERR("unknown mode: %d\n", mode);
			return -1;
	}

	if(reg==NULL)
	{
		LM_DBG("no user: %.*s\n", src->len, src->s);
		return -1;
	}

	// Set uri ($ru)
	snprintf(ruri, MAX_URI_SIZE, "sip:%.*s@%.*s",
			reg->r_username.len, reg->r_username.s,
			reg->r_domain.len, reg->r_domain.s);
	memset(&act, 0, sizeof(act));
	act.type = SET_URI_T;
	act.val[0].type = STRING_ST;
	act.val[0].u.string = ruri;
	init_run_actions_ctx(&ra_ctx);
	if (do_action(&ra_ctx, &act, msg) < 0) {
		LM_ERR("error while setting request uri\n");
		return -1;
	}

	// Set auth_proxy ($du)
	if (set_dst_uri(msg, &reg->auth_proxy) < 0) {
		LM_ERR("error while setting outbound proxy\n");
		return -1;
	}

	memset(&val, 0, sizeof(pv_value_t));
	val.flags |= PV_VAL_STR;

	// Set auth_realm
	val.rs = reg->realm;
	if(pv_set_spec_value(msg, &auth_realm_spec, 0, &val)!=0) {
		LM_ERR("error while setting auth_realm\n");
		return -1;
	}

	// Set auth_username
	val.rs = reg->auth_username;
	if(pv_set_spec_value(msg, &auth_username_spec, 0, &val)!=0) {
		LM_ERR("error while setting auth_username\n");
		return -1;
	}

	// Set auth_password
	val.rs = reg->auth_password;
	if(pv_set_spec_value(msg, &auth_password_spec, 0, &val)!=0) {
		LM_ERR("error while setting auth_password\n");
		return -1;
	}

	return 1;
}
Exemple #18
0
/* Authorize digest credentials */
int authorize(struct sip_msg* msg, pv_elem_t* realm, int hftype)
{
	auth_diam_result_t ret;
	struct hdr_field* h;
	auth_body_t* cred = NULL;
	str* uri;
	struct sip_uri puri;
	str  domain;

	if (realm) {
		if (pv_printf_s(msg, realm, &domain)!=0) {
			LM_ERR("pv_printf_s failed\n");
			return AUTH_ERROR;
		}
	} else {
		domain.len = 0;
		domain.s = 0;
	}

	/* see what is to do after a first look at the message */
	ret = diam_pre_auth(msg, &domain, hftype, &h);

	switch(ret) 
	{
		case NO_CREDENTIALS:   cred = NULL;
							   break;

		case DO_AUTHORIZATION: cred = (auth_body_t*)h->parsed;
							   break;
		default:               return ret;
	}

	if (get_uri(msg, &uri) < 0) 
	{
		LM_ERR("From/To URI not found\n");
		return AUTH_ERROR;
	}
	
	if (parse_uri(uri->s, uri->len, &puri) < 0) 
	{
		LM_ERR("failed to parse From/To URI\n");
		return AUTH_ERROR;
	}
//	user.s = (char *)pkg_malloc(puri.user.len);
//	un_escape(&(puri.user), &user);
	
	/* parse the ruri, if not yet */
	if(msg->parsed_uri_ok==0 && parse_sip_msg_uri(msg)<0)
	{
		LM_ERR("failed to parse the Request-URI\n");
		return AUTH_ERROR;
	}
	
	/* preliminary check */
	if(cred)
	{
		if (puri.host.len != cred->digest.realm.len) 
		{
			LM_DBG("credentials realm and URI host do not match\n");  
			return AUTH_ERROR;
		}
	
		if (strncasecmp(puri.host.s, cred->digest.realm.s, puri.host.len) != 0) 
		{
			LM_DBG("credentials realm and URI host do not match\n");
			return AUTH_ERROR;
		}
	}
	
	if( diameter_authorize(cred?h:NULL, &msg->first_line.u.request.method,
					puri, msg->parsed_uri, msg->id, rb) != 1)
	{
		send_resp(msg, 500, &dia_500_err, NULL, 0);
		return AUTH_ERROR;
	}
	
	if( srv_response(msg, rb, hftype) != 1 )
		return AUTH_ERROR;

	mark_authorized_cred(msg, h);

	return AUTHORIZED;
}
Exemple #19
0
int main(int argc, char *argv[])
{
	FILE	*pf;
	char	buff[BUFSIZE];
	int		c, i, port;
	unsigned int tsp;
	char	*scheme, *user, *host, *backup;
	pid_t 	pid;
	struct 	timespec ts;
	int 	upp;

#ifdef HAVE_GETOPT_LONG
	int option_index = 0;
	static struct option l_opts[] = {
		{"help", 0, 0, 'X'},
		{"version", 0, 0, 'V'},
		{"filename", 1, 0, 'f'},
		{"sip-uri", 1, 0, 's'},
		{"traceroute-mode", 0, 0, 'T'},
		{"usrloc-mode", 0, 0, 'U'},
		{"invite-mode", 0, 0, 'I'},
		{"message-mode", 0, 0, 'M'},
		{"contact", 1, 0, 'C'},
		{"appendix-begin", 1, 0, 'b'},
		{"appendix-end", 1, 0, 'e'},
		{"sleep", 1, 0, 'o'},
		{"expires", 1, 0, 'x'},
		{"remove-bindings", 1, 0, 'z'},
		{"flood-mode", 0, 0, 'F'},
		{"random-mode", 0, 0, 'R'},
		{"trash-chars", 1, 0, 't'},
		{"local-port", 1, 0, 'l'},
		{"remote-port", 1, 0, 'r'},
		{"outbound-proxy", 1, 0, 'p'},
		{"hostname", 1, 0, 'H'},
		{"max-fowards", 1, 0, 'm'},
		{"numeric", 0, 0, 'n'},
		{"no-via", 0, 0, 'i'},
		{"password", 1, 0, 'a'},
		{"ignore-redirects", 0, 0, 'd'},
		{"verbose", 0, 0, 'v'},
		{"extract-ip", 0, 0, 'w'},
		{"replace-string", 0, 0, 'g'},
		{"replace", 0, 0, 'G'},
		{"nagios-code", 0, 0, 'N'},
		{"nagios-warn", 1, 0, 'W'},
		{"search", 1, 0, 'q'},
		{"message-body", 1, 0, 'B'},
		{"disposition", 1, 0, 'O'},
		{"processes", 1, 0, 'P'},
		{"auth-username", 1, 0, 'u'},
		{"no-crlf", 0, 0, 'L'},
		{"timing", 0, 0, 'A'},
		{"symmetric", 0, 0, 'S'},
		{"from", 1, 0, 'c'},
		{"timeout-factor", 1, 0, 'D'},
		{"transport", 1, 0, 'E'},
		{0, 0, 0, 0}
	};
#endif
	/* some initialisation to be shure */
	file_b=uri_b=trace=lport=usrloc=flood=verbose=randtrash=trashchar = 0;
	warning_ext=rand_rem=nonce_count=replace_b=invite=message = 0;
	sleep_ms=empty_contact=nagios_warn=timing=outbound_proxy=symmetric = 0;
	namebeg=nameend=maxforw= -1;
	numeric=via_ins=redirects=fix_crlf=processes = 1;
	username=password=replace_str=hostname=contact_uri=mes_body = NULL;
	con_dis=auth_username=from_uri = NULL;
	scheme = user = host = backup = req = rep = rec = NULL;
	re = NULL;
	address= 0;
	transport=tsp = 0;
	rport = port = 0;
	expires_t = USRLOC_EXP_DEF;
	inv_final = 64 * SIP_T1;
	memset(buff, 0, BUFSIZE);
	memset(fqdn, 0, FQDN_SIZE);

	if (argc==1) {
		print_help();
	}

	/* lots of command line switches to handle*/
#ifdef HAVE_GETOPT_LONG
	while ((c=getopt_long(argc, argv, "a:Ab:B:c:C:dD:e:E:f:Fg:GhH:iIl:Lm:MnNo:O:p:P:q:r:Rs:St:Tu:UvVwW:x:Xz:", l_opts, &option_index)) != EOF){
#else
	while ((c=getopt(argc, argv, "a:Ab:B:c:C:dD:e:E:f:Fg:GhH:iIl:Lm:MnNo:O:p:P:q:r:Rs:St:Tu:UvVwW:x:z:")) != EOF){
#endif
		switch(c){
			case 'a':
				password=str_alloc(strlen(optarg) + 1);
				strncpy(password, optarg, strlen(optarg));
				break;
			case 'A':
				timing=1;
				break;
			case 'b':
				namebeg=str_to_int(optarg);
				break;
			case 'B':
				mes_body=str_alloc(strlen(optarg) + 1);
				strncpy(mes_body, optarg, strlen(optarg));
				break;
			case 'c':
				backup=str_alloc(strlen(optarg)+1);
				strncpy(backup, optarg, strlen(optarg));
				parse_uri(backup, &scheme, &user, &host, &port);
				if (scheme  == NULL) {
					fprintf(stderr, "error: missing scheme in From URI\n");
					exit_code(2);
				}
				else if (user == NULL) {
					fprintf(stderr, "error: missing username in From URI\n");
					exit_code(2);
				}
				else if (host == NULL) {
					fprintf(stderr, "error: missing host in From URI\n");
					exit_code(2);
				}
				else {
					from_uri=str_alloc(strlen(optarg)+1);
					strncpy(from_uri, optarg, strlen(optarg));
				}
				free(backup);
				break;
			case 'C':
				if ((strlen(optarg) == 5 && STRNCASECMP(optarg, "empty", 5) == 0) || 
					(strlen(optarg) == 4 && STRNCASECMP(optarg, "none", 4) == 0)) {
					empty_contact = 1;
				}
				else if (strlen(optarg) == 1 && STRNCASECMP(optarg, "*", 1) == 0) {
					contact_uri=str_alloc(strlen(optarg)+1);
					strncpy(contact_uri, optarg, strlen(optarg));
				}
				else {
					backup=str_alloc(strlen(optarg)+1);
					strncpy(backup, optarg, strlen(optarg));
					parse_uri(backup, &scheme, &user, &host, &port);
					if (scheme == NULL) {
					    fprintf(stderr, "error: REGISTER Contact uri doesn't not contain "
						   "sip:, sips:, *, or is not empty\n");
				    	exit_code(2);
					}
					else if (user == NULL) {
						fprintf(stderr, "error: missing username in Contact uri\n");
						exit_code(2);
					}
					else if (host == NULL) {
						fprintf(stderr, "error: missing host in Contact uri\n");
						exit_code(2);
					}
					else {
						contact_uri=str_alloc(strlen(optarg)+1);
						strncpy(contact_uri, optarg, strlen(optarg));
					}
					free(backup);
				}
				break;
			case 'd':
				redirects=0;
				break;
			case 'D':
				inv_final = str_to_int(optarg) * SIP_T1;
				break;
			case 'e':
				nameend=str_to_int(optarg);
				break;
			case 'E':
				if (strlen(optarg) == 3 && 
					STRNCASECMP(optarg, "udp", 3) == 0) {
					transport = SIP_UDP_TRANSPORT;
				}
				else if (strlen(optarg) == 3 &&
						STRNCASECMP(optarg, "tcp", 3) == 0) {
					transport = SIP_TCP_TRANSPORT;
				}
				else if (strlen(optarg) == 3 &&
						STRNCASECMP(optarg, "tls", 3) == 0) {
					fprintf(stderr, "error: TLS is not supported yet, supported values: udp, tcp\n");
					exit_code(2);
					transport = SIP_TLS_TRANSPORT;
				}
				else {
					fprintf(stderr, "error: unsupported transport '%s', supported values: udp, tcp\n", optarg);
					exit_code(2);
				}
				break;
			case 'F':
				flood=1;
				break;
			case 'f':
				if (strlen(optarg) != 1 && STRNCASECMP(optarg, "-", 1) != 0) {
					/* file is opened in binary mode so that the cr-lf is 
					   preserved */
					pf = fopen(optarg, "rb");
					if (!pf){
						fprintf(stderr, "error: unable to open the file '%s'.\n", optarg);
						exit_code(2);
					}
					if (fread(buff, 1, sizeof(buff), pf) >= sizeof(buff)){
						fprintf(stderr, "error:the file is too big. try files of less "
							"than %i bytes.\n", BUFSIZE);
						fprintf(stderr, "      or recompile the program with bigger "
							"BUFSIZE defined.\n");
						exit_code(2);
					}
					fclose(pf);
				}
				else if (strlen(optarg) == 1 && STRNCASECMP(optarg, "-", 1) == 0) {
					if (read_stdin(&buff[0], sizeof(buff)) == 0) {
						exit_code(0);
					}
				}
				else {
					fprintf(stderr, "error: unable to handle input file name: %s\n", optarg);
					exit_code(2);
				}
				file_b=1;
				break;
			case 'g':
				replace_str=optarg;
				break;
			case 'G':
				replace_b=1;
				break;
			case 'h':
				print_help();
				break;
			case 'H':
				hostname=optarg;
				break;
			case 'i':
				via_ins=0;
				break;
			case 'I':
				invite=1;
				break;
			case 'l':
				lport=str_to_int(optarg);
				break;
			case 'L':
				fix_crlf=0;
				break;
			case 'm':
				maxforw=str_to_int(optarg);
				break;
			case 'M':
				message=1;
				break;
			case 'n':
				numeric = 0;
				break;
			case 'N':
				exit_mode=EM_NAGIOS;
				break;
			case 'o':
				sleep_ms = 0;
				if (strlen(optarg) == 4 && STRNCASECMP(optarg, "rand", 4) == 0) {
					sleep_ms = -2;
				}
				else {
					sleep_ms = str_to_int(optarg);
				}
				break;
			case 'O':
				con_dis=str_alloc(strlen(optarg) + 1);
				strncpy(con_dis, optarg, strlen(optarg));
				break;
			case 'p':
				parse_uri(optarg, &scheme, &user, &host, &rport);
				if (host == NULL) {
					fprintf(stderr, "error: missing in host in outbound proxy\n");
					exit_code(2);
				}
				if (is_ip(host)) {
					address = getaddress(host);
					if (transport == 0)
						transport = SIP_UDP_TRANSPORT;
				}
				else {
					if (!rport) {
						address = getsrvadr(host, &rport, &tsp);
						if (tsp != 0)
							transport = tsp;
					}
					if (!address) {
						address = getaddress(host);
						if (address && verbose > 1)
							printf("using A record: %s\n", host);
					}
					if (!address){
						fprintf(stderr, "error:unable to determine the outbound proxy "
							"address\n");
						exit_code(2);
					}
				}
				outbound_proxy=1;
				break;
			case 'P':
				processes=str_to_int(optarg);
				break;
			case 'q':
				if (re) {
					/* previously allocated -- free */
					regfree(re);
				} else {
					/* never tried -- allocate */
					re=malloc(sizeof(regex_t));
				};
				if (!re) {
					fprintf(stderr, "Error: can't allocate RE\n");
					exit_code(2);
				};
				if (regcomp(re, optarg, REG_EXTENDED|REG_ICASE|REG_NEWLINE )!=0) {
					fprintf(stderr, "Error: compiling RE: %s\n", optarg );
					exit_code(2);
				};
				break;
			case 'r':
				port = 0;
				port=str_to_int(optarg);
				if (rport) {
					fprintf(stderr, "warning: you are overwritting the destination port with the r argument\n");
				}
				rport = port;
				break;
			case 'R':
				randtrash=1;
				break;
			case 's':
				parse_uri(optarg, &scheme, &user, &host, &port);
				if (scheme == NULL) {
					fprintf(stderr, "error: missing scheme in sip uri\n");
					exit_code(2);
				}
				if (strlen(optarg) == 4 && STRNCASECMP(optarg,"sips",4) == 0){
					fprintf(stderr, "error: sips is not supported yet\n");
					exit_code(2);
				}
				else if (strlen(optarg) != 3 || STRNCASECMP(optarg,"sip",3) != 0){
					fprintf(stderr, "error: scheme of sip uri has to be sip\n");
					exit_code(2);
				}
				if (user != NULL) {
					username = user;
				}
				if (host != NULL) {
					domainname = host;
				}
				else {
					fprintf(stderr, "error: missing hostname in sip uri\n");
					exit_code(2);
				}
				if (port && !rport) {
					rport = port;
				}
				if (is_ip(domainname)) {
					address = getaddress(domainname);
					if (transport == 0)
						transport = SIP_UDP_TRANSPORT;
				}
				else {
					if (!rport && !address) {
						address = getsrvadr(domainname, &rport, &tsp);
						if (tsp != 0)
							transport = tsp;
					}
					if (!address) {
						address = getaddress(domainname);
						if (address && verbose > 1)
							printf("using A record: %s\n", domainname);
					}
					if (!address){
						fprintf(stderr, "error:unable to determine the IP address for: %s\n", domainname);
						exit_code(2);
					}
				}
				if (port != 0) {
					backup = str_alloc(strlen(domainname)+1+6);
					snprintf(backup, strlen(domainname)+6, "%s:%i", domainname, port);
					domainname = backup;
				}
				uri_b=1;
				break;
			case 'S':
				fprintf(stderr, "warning: symmetric does not work with a-symmetric servers\n");
				symmetric=1;
				break;
			case 't':
				trashchar=str_to_int(optarg);
				break;
			case 'T':
				trace=1;
				break;
			case 'U':
				usrloc=1;
				break;
			case 'u':
				auth_username=str_alloc(strlen(optarg) + 1);
				strncpy(auth_username, optarg, strlen(optarg));
				break;
			case 'v':
				verbose++;
				break;
			case 'V':
				printf("sipsak %s  by Nils Ohlmeier\n Copyright (C) 2002-2004"
						" FhG Fokus\n Copyright (C) 2004-2005 Nils Ohlmeier\n", 
						SIPSAK_VERSION);
				printf(" compiled with DEFAULT_TIMEOUT=%i, FQDN_SIZE=%i",
						DEFAULT_TIMEOUT, FQDN_SIZE);
#ifdef RAW_SUPPORT
				printf(", RAW_SUPPORT");
#endif
#ifdef HAVE_GETOPT_LONG
				printf(", LONG_OPTS");
#endif
#ifdef HAVE_GNUTLS
				printf(", GNUTLS_MD5");
#else
# ifdef HAVE_FULL_OPENSSL
				printf(", OPENSSL_MD5");
# else
				printf(", INTERNAL_MD5");
# endif
#endif
#ifdef HAVE_CARES_H
				printf(", SRV_SUPPORT(ARES)");
#else
# ifdef HAVE_RULI_H
				printf(", SRV_SUPPORT(RULI)");
# endif
#endif
#ifdef HAVE_STRCASESTR
				printf(", STR_CASE_INSENSITIVE");
#endif
#ifdef HAVE_STRNCASECMP
				printf(", CMP_CASE_INSENSITIVE");
#endif
				printf("\n");
				exit_code(0);
				break;
			case 'w':
				warning_ext=1;
				break;
			case 'W':
				nagios_warn = str_to_int(optarg);
				break;
			case 'x':
				expires_t=str_to_int(optarg);
				break;
#ifdef HAVE_GETOPT_LONG
			case 'X':
				print_long_help();
				break;
#endif
			case 'z':
				rand_rem=str_to_int(optarg);
				if (rand_rem < 0 || rand_rem > 100) {
					fprintf(stderr, "error: z option must between 0 and 100\n");
					exit_code(2);
				}
				break;
			default:
				fprintf(stderr, "error: unknown parameter %c\n", c);
				exit_code(2);
				break;
		}
	}

	if (rport == 0) {
		rport =  5060;
	}
	if (rport > 65535 || rport <= 0) {
		fprintf(stderr, "error: invalid remote port: %i\n", rport);
		exit_code(2);
	}
	if (transport == 0) {
		transport = SIP_UDP_TRANSPORT;
	}

	/* replace LF with CRLF if we read from a file */
	if ((file_b) && (fix_crlf)) {
		insert_cr(buff);
	}
	/* lots of conditions to check */
	if (trace) {
		if (usrloc || flood || randtrash) {
			fprintf(stderr, "error: trace can't be combined with usrloc, random or "
				"flood\n");
			exit_code(2);
		}
		if (!uri_b) {
			fprintf(stderr, "error: for trace mode a SIPURI is realy needed\n");
			exit_code(2);
		}
		if (file_b) {
			fprintf(stderr, "warning: file will be ignored for tracing.");
		}
		if (!username) {
			fprintf(stderr, "error: for trace mode without a file the SIPURI have to "
				"contain a username\n");
			exit_code(2);
		}
		if (!via_ins){
			fprintf(stderr, "warning: Via-Line is needed for tracing. Ignoring -i\n");
			via_ins=1;
		}
		if (!warning_ext) {
			fprintf(stderr, "warning: IP extract from warning activated to be more "
				"informational\n");
			warning_ext=1;
		}
		if (maxforw==-1) maxforw=255;
	}
	else if (usrloc || invite || message) {
		if (trace || flood || randtrash) {
			fprintf(stderr, "error: usrloc can't be combined with trace, random or "
				"flood\n");
			exit_code(2);
		}
		if (!username || !uri_b) {
			fprintf(stderr, "error: for the USRLOC mode you have to give a SIPURI with "
				"a username\n       at least\n");
			exit_code(2);
		}
		if (namebeg>0 && nameend==-1) {
			fprintf(stderr, "error: if a starting numbers is given also an ending "
				"number have to be specified\n");
			exit_code(2);
		}
		if (invite && message) {
			fprintf(stderr, "error: invite and message tests are XOR\n");
			exit_code(2);
		}
		if (!usrloc && invite && !lport) {
			fprintf(stderr, "warning: Do NOT use the usrloc invite mode without "
				"registering sipsak before.\n         See man page for "
				"details.\n");
			exit_code(2);
		}
		if (contact_uri!=NULL) {
			if (invite || message) {
				fprintf(stderr, "error: Contact uri is not support for invites or "
					"messages\n");
				exit_code(2);
			}
			if (nameend!=-1 || namebeg!=-1) {
				fprintf(stderr, "warning: ignoring starting or ending number if Contact"
					" is given\n");
				nameend=namebeg=0;
			}
			if (rand_rem) {
				fprintf(stderr, "warning: ignoring -z option when Contact is given\n");
				rand_rem=0;
			}
		}
		if (via_ins) {
			fprintf(stderr, "warning: ignoring -i option when in usrloc mode\n");
			via_ins=0;
		}
		if (nameend==-1)
			nameend=0;
		if (namebeg==-1)
			namebeg=0;
	}
	else if (flood) {
		if (trace || usrloc || randtrash) {
			fprintf(stderr, "error: flood can't be combined with trace, random or "
				"usrloc\n");
			exit_code(2);
		}
		if (!uri_b) {
			fprintf(stderr, "error: we need at least a sip uri for flood\n");
			exit_code(2);
		}
		if (redirects) {
			fprintf(stderr, "warning: redirects are not expected in flood. "
				"disableing\n");
			redirects=0;
		}
	}
	else if (randtrash) {
		if (trace || usrloc || flood) {
			fprintf(stderr, "error: random can't be combined with trace, flood or "
				"usrloc\n");
			exit_code(2);
		}
		if (!uri_b) {
			fprintf(stderr, "error: need at least a sip uri for random\n");
			exit_code(2);
		}
		if (redirects) {
			fprintf(stderr, "warning: redirects are not expected in random. "
				"disableing\n");
			redirects=0;
		}
		if (verbose) {
			fprintf(stderr, "warning: random characters may destroy your terminal "
				"output\n");
		}
	}
	else if (mes_body) {
		if (!message) {
			fprintf(stderr, "warning: to send a message mode (-M) is required. activating\n");
			message=1;
		}
		if (!uri_b) {
			fprintf(stderr, "error: need at least a sip uri to send a meesage\n");
			exit_code(2);
		}
		if (nameend==-1)
			nameend=0;
		if (namebeg==-1)
			namebeg=0;
	}
	else {
		if (!uri_b) {
			fprintf(stderr, "error: a spi uri is needed at least\n");
			exit_code(2);
		}
	}

	switch (transport) {
		case SIP_TLS_TRANSPORT:
			transport_str = TRANSPORT_TLS_STR;
			break;
		case SIP_TCP_TRANSPORT:
			transport_str = TRANSPORT_TCP_STR;
			break;
		case SIP_UDP_TRANSPORT:
			transport_str = TRANSPORT_UDP_STR;
			break;
		default:
			fprintf(stderr, "unknown transport: %i\n", transport);
			exit_code(2);
	}

	/* determine our hostname */
	get_fqdn();
	
	/* this is not a cryptographic random number generator,
	   but hey this is only a test-tool => should be satisfying*/
	srand(time(0) ^ getpid());
	
	if (processes > 1) {
		if (signal(SIGCHLD , sigchld_handler)  == SIG_ERR ) {
			fprintf(stderr, "error: Could not install SIGCHLD handler\n");
			exit_code(2);
		}
	}

	for(i = 0; i < processes - 1; i++) {
		if ((pid = fork()) < 0) {
			fprintf(stderr, "error: Cannot fork\n");
			exit_code(2);
		}
		
		if (pid == 0){
	    	/* child */
			upp = (nameend - namebeg + 1) / processes;
			namebeg = namebeg + upp * i;
			nameend = namebeg + upp;
			shoot(&buff[0], sizeof(buff));
		} else {
			if (lport) {
				lport++;
			}
		}
		
		/* Delay execution of children so that the
		 * time of the first transmission gets spread over
		 * the retransmission interval evenly
		 */
		ts.tv_sec = 0;
		ts.tv_nsec = (float)DEFAULT_TIMEOUT / (float)processes * (float)1000 * (float)1000;
		nanosleep(&ts, 0);
	}

	/* here we go...*/
	if (processes > 1) {
		upp = (nameend - namebeg + 1) / processes;
		namebeg = namebeg + upp * i;
		nameend = namebeg + upp;
	}
	shoot(&buff[0], sizeof(buff));

	/* normaly we won't come back here, but to satisfy the compiler */
	return 0;
}
Exemple #20
0
/*! \brief
 * Extract Address of Record
 * In case of public GRUUs, also populates sip_instance
 * In case of temp GRUUs, also populates call_id
 */
int extract_aor(str* _uri, str* _a,str *sip_instance,str *call_id)
{
	static char aor_buf[MAX_AOR_LEN];
	memset(aor_buf, 0, MAX_AOR_LEN);

	str tmp;
	struct sip_uri puri;
	int user_len,tgruu_len,dec_size,i;
	str *magic;

	if (parse_uri(_uri->s, _uri->len, &puri) < 0) {
		rerrno = R_AOR_PARSE;
		LM_ERR("failed to parse Address of Record\n");
		return -1;
	}

	/* if have ;gr param and func caller is interested in 
	 * potentially extracting the sip instance */
	if ((puri.gr.s && puri.gr.len) && sip_instance)
	{
		LM_DBG("has gruu\n");

		/* ;gr param detected */
		if (memcmp(puri.user.s,TEMP_GRUU,TEMP_GRUU_SIZE) == 0)
		{
			LM_DBG("temp gruu\n");
			/* temp GRUU, decode and extract aor, sip_instance
			 * and call_id */
			tgruu_len = puri.user.len - TEMP_GRUU_SIZE;
			memcpy(tgruu_dec,puri.user.s+TEMP_GRUU_SIZE,tgruu_len);

			if (gruu_secret.s != NULL)
				magic = &gruu_secret;
			else
				magic = &default_gruu_secret;

			dec_size = base64decode((unsigned char *)tgruu_dec,
					(unsigned char *)tgruu_dec,tgruu_len);

			for (i=0;i<tgruu_len;i++)
				tgruu_dec[i] ^= magic->s[i%magic->len];

			LM_DBG("decoded [%.*s]\n",dec_size,tgruu_dec);
			/* extract aor - skip tgruu generation time at 
			 * the beggining */
			_a->s = (char *)memchr(tgruu_dec,' ',dec_size) + 1;
			if (_a->s == NULL) {
				rerrno = R_AOR_PARSE;
				LM_ERR("failed to parse Address of Record\n");
				return -1;
			}
			_a->len = (char *)memchr(_a->s,' ',dec_size - (_a->s-tgruu_dec)) - _a->s;
			if (_a->len < 0) { 
				rerrno = R_AOR_PARSE;
				LM_ERR("failed to parse Address of Record\n");
				return -1;
			}

			sip_instance->s = _a->s+_a->len+1; /* skip ' ' */
			if (sip_instance->s >= tgruu_dec + dec_size) {
				rerrno = R_AOR_PARSE;
				LM_ERR("failed to parse Address of Record\n");
				return -1;
			}
			sip_instance->len = (char *)memchr(sip_instance->s,' ',
					dec_size-(sip_instance->s-tgruu_dec)) - sip_instance->s;
			if (sip_instance->len < 0) { 
				rerrno = R_AOR_PARSE;
				LM_ERR("failed to parse Address of Record\n");
				return -1;
			}

			call_id->s = sip_instance->s + sip_instance->len + 1;
			if (call_id->s >= tgruu_dec + dec_size) {
				rerrno = R_AOR_PARSE;
				LM_ERR("failed to parse Address of Record\n");
				return -1;
			}
			call_id->len = (tgruu_dec+dec_size) - call_id->s -1;

			LM_DBG("extracted aor [%.*s] and instance [%.*s] and callid [%.*s]\n",_a->len,_a->s,
					sip_instance->len,sip_instance->s,call_id->len,call_id->s);

			/* skip checks - done at save() */
			return 0;
		}
		else
		{
			LM_DBG("public gruu\n");
			*sip_instance = puri.gr_val;
		}
	}
	
	if ( (puri.user.len + puri.host.len + 1) > MAX_AOR_LEN
	|| puri.user.len > USERNAME_MAX_SIZE
	||  puri.host.len > DOMAIN_MAX_SIZE ) {
		rerrno = R_AOR_LEN;
		LM_ERR("Address Of Record too long\n");
		return -2;
	}

	_a->s = aor_buf;
	_a->len = puri.user.len;

	if (un_escape(&puri.user, _a) < 0) {
		rerrno = R_UNESCAPE;
		LM_ERR("failed to unescape username\n");
		return -3;
	}

	user_len = _a->len;

	if (reg_use_domain) {
		if (user_len)
			aor_buf[_a->len++] = '@';
		/* strip prefix (if defined) */
		if (realm_prefix.len && realm_prefix.len<puri.host.len &&
		(memcmp(realm_prefix.s, puri.host.s, realm_prefix.len)==0) ) {
			memcpy(aor_buf + _a->len, puri.host.s + realm_prefix.len,
					puri.host.len - realm_prefix.len);
			_a->len += puri.host.len - realm_prefix.len;
		} else {
			memcpy(aor_buf + _a->len, puri.host.s, puri.host.len);
			_a->len += puri.host.len;
		}
	}

	if (case_sensitive && user_len) {
		tmp.s = _a->s + user_len + 1;
		tmp.len = _a->s + _a->len - tmp.s;
		strlower(&tmp);
	} else {
		strlower(_a);
	}

	return 0;
}
Exemple #21
0
int zmq::socket_base_t::connect (const char *addr_)
{
    ENTER_MUTEX ();

    if (unlikely (ctx_terminated)) {
        errno = ETERM;
        EXIT_MUTEX ();
        return -1;
    }

    //  Process pending commands, if any.
    int rc = process_commands (0, false);
    if (unlikely (rc != 0)) {
        EXIT_MUTEX ();
        return -1;
    }

    //  Parse addr_ string.
    std::string protocol;
    std::string address;
    if (parse_uri (addr_, protocol, address) || check_protocol (protocol)) {
        EXIT_MUTEX ();
        return -1;
    }

    if (protocol == "inproc") {

        //  TODO: inproc connect is specific with respect to creating pipes
        //  as there's no 'reconnect' functionality implemented. Once that
        //  is in place we should follow generic pipe creation algorithm.

        //  Find the peer endpoint.
        endpoint_t peer = find_endpoint (addr_);

        // The total HWM for an inproc connection should be the sum of
        // the binder's HWM and the connector's HWM.
        int sndhwm = 0;
        if (peer.socket == NULL)
            sndhwm = options.sndhwm;
        else if (options.sndhwm != 0 && peer.options.rcvhwm != 0)
            sndhwm = options.sndhwm + peer.options.rcvhwm;
        int rcvhwm = 0;
        if (peer.socket == NULL)
            rcvhwm = options.rcvhwm;
        else
        if (options.rcvhwm != 0 && peer.options.sndhwm != 0)
            rcvhwm = options.rcvhwm + peer.options.sndhwm;

        //  Create a bi-directional pipe to connect the peers.
        object_t *parents [2] = {this, peer.socket == NULL ? this : peer.socket};
        pipe_t *new_pipes [2] = {NULL, NULL};

        bool conflate = options.conflate &&
            (options.type == ZMQ_DEALER ||
             options.type == ZMQ_PULL ||
             options.type == ZMQ_PUSH ||
             options.type == ZMQ_PUB ||
             options.type == ZMQ_SUB);

        int hwms [2] = {conflate? -1 : sndhwm, conflate? -1 : rcvhwm};
        bool conflates [2] = {conflate, conflate};
        rc = pipepair (parents, new_pipes, hwms, conflates);
        if (!conflate) {
            new_pipes[0]->set_hwms_boost(peer.options.sndhwm, peer.options.rcvhwm);
            new_pipes[1]->set_hwms_boost(options.sndhwm, options.rcvhwm);
        }

        errno_assert (rc == 0);

        if (!peer.socket) {
            //  The peer doesn't exist yet so we don't know whether
            //  to send the identity message or not. To resolve this,
            //  we always send our identity and drop it later if
            //  the peer doesn't expect it.
            msg_t id;
            rc = id.init_size (options.identity_size);
            errno_assert (rc == 0);
            memcpy (id.data (), options.identity, options.identity_size);
            id.set_flags (msg_t::identity);
            bool written = new_pipes [0]->write (&id);
            zmq_assert (written);
            new_pipes [0]->flush ();

            const endpoint_t endpoint = {this, options};
            pend_connection (std::string (addr_), endpoint, new_pipes);
        }
        else {
            //  If required, send the identity of the local socket to the peer.
            if (peer.options.recv_identity) {
                msg_t id;
                rc = id.init_size (options.identity_size);
                errno_assert (rc == 0);
                memcpy (id.data (), options.identity, options.identity_size);
                id.set_flags (msg_t::identity);
                bool written = new_pipes [0]->write (&id);
                zmq_assert (written);
                new_pipes [0]->flush ();
            }

            //  If required, send the identity of the peer to the local socket.
            if (options.recv_identity) {
                msg_t id;
                rc = id.init_size (peer.options.identity_size);
                errno_assert (rc == 0);
                memcpy (id.data (), peer.options.identity, peer.options.identity_size);
                id.set_flags (msg_t::identity);
                bool written = new_pipes [1]->write (&id);
                zmq_assert (written);
                new_pipes [1]->flush ();
            }

            //  Attach remote end of the pipe to the peer socket. Note that peer's
            //  seqnum was incremented in find_endpoint function. We don't need it
            //  increased here.
            send_bind (peer.socket, new_pipes [1], false);
        }

        //  Attach local end of the pipe to this socket object.
        attach_pipe (new_pipes [0]);

        // Save last endpoint URI
        last_endpoint.assign (addr_);

        // remember inproc connections for disconnect
        inprocs.insert (inprocs_t::value_type (std::string (addr_), new_pipes [0]));

        options.connected = true;
        EXIT_MUTEX ();
        return 0;
    }
    bool is_single_connect = (options.type == ZMQ_DEALER ||
                              options.type == ZMQ_SUB ||
                              options.type == ZMQ_REQ);
    if (unlikely (is_single_connect)) {
        const endpoints_t::iterator it = endpoints.find (addr_);
        if (it != endpoints.end ()) {
            // There is no valid use for multiple connects for SUB-PUB nor
            // DEALER-ROUTER nor REQ-REP. Multiple connects produces
            // nonsensical results.
            EXIT_MUTEX ();
            return 0;
        }
    }

    //  Choose the I/O thread to run the session in.
    io_thread_t *io_thread = choose_io_thread (options.affinity);
    if (!io_thread) {
        errno = EMTHREAD;
        EXIT_MUTEX ();
        return -1;
    }

    address_t *paddr = new (std::nothrow) address_t (protocol, address, this->get_ctx ());
    alloc_assert (paddr);

    //  Resolve address (if needed by the protocol)
    if (protocol == "tcp") {
        //  Do some basic sanity checks on tcp:// address syntax
        //  - hostname starts with digit or letter, with embedded '-' or '.'
        //  - IPv6 address may contain hex chars and colons.
        //  - IPv6 link local address may contain % followed by interface name / zone_id
        //    (Reference: https://tools.ietf.org/html/rfc4007)
        //  - IPv4 address may contain decimal digits and dots.
        //  - Address must end in ":port" where port is *, or numeric
        //  - Address may contain two parts separated by ':'
        //  Following code is quick and dirty check to catch obvious errors,
        //  without trying to be fully accurate.
        const char *check = address.c_str ();
        if (isalnum (*check) || isxdigit (*check) || *check == '[') {
            check++;
            while (isalnum  (*check)
                || isxdigit (*check)
                || *check == '.' || *check == '-' || *check == ':' || *check == '%'
                || *check == ';' || *check == ']' || *check == '_'
            ) {
                check++;
            }
        }
        //  Assume the worst, now look for success
        rc = -1;
        //  Did we reach the end of the address safely?
        if (*check == 0) {
            //  Do we have a valid port string? (cannot be '*' in connect
            check = strrchr (address.c_str (), ':');
            if (check) {
                check++;
                if (*check && (isdigit (*check)))
                    rc = 0;     //  Valid
            }
        }
        if (rc == -1) {
            errno = EINVAL;
            LIBZMQ_DELETE(paddr);
            EXIT_MUTEX ();
            return -1;
        }
        //  Defer resolution until a socket is opened
        paddr->resolved.tcp_addr = NULL;
    }
#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS
    else
    if (protocol == "ipc") {
        paddr->resolved.ipc_addr = new (std::nothrow) ipc_address_t ();
        alloc_assert (paddr->resolved.ipc_addr);
        int rc = paddr->resolved.ipc_addr->resolve (address.c_str ());
        if (rc != 0) {
            LIBZMQ_DELETE(paddr);
            EXIT_MUTEX ();
            return -1;
        }
    }
#endif

if (protocol  == "udp") {
    paddr->resolved.udp_addr = new (std::nothrow) udp_address_t ();
    alloc_assert (paddr->resolved.udp_addr);
    rc = paddr->resolved.udp_addr->resolve (address.c_str());
    if (rc != 0) {
        LIBZMQ_DELETE(paddr);
        EXIT_MUTEX ();
        return -1;
    }
}

// TBD - Should we check address for ZMQ_HAVE_NORM???

#ifdef ZMQ_HAVE_OPENPGM
    if (protocol == "pgm" || protocol == "epgm") {
        struct pgm_addrinfo_t *res = NULL;
        uint16_t port_number = 0;
        int rc = pgm_socket_t::init_address(address.c_str(), &res, &port_number);
        if (res != NULL)
            pgm_freeaddrinfo (res);
        if (rc != 0 || port_number == 0) {
          EXIT_MUTEX ();
          return -1;
        }
    }
#endif
#if defined ZMQ_HAVE_TIPC
    else
    if (protocol == "tipc") {
        paddr->resolved.tipc_addr = new (std::nothrow) tipc_address_t ();
        alloc_assert (paddr->resolved.tipc_addr);
        int rc = paddr->resolved.tipc_addr->resolve (address.c_str());
        if (rc != 0) {
            LIBZMQ_DELETE(paddr);
            EXIT_MUTEX ();
            return -1;
        }
    }
#endif
#if defined ZMQ_HAVE_VMCI
    else
    if (protocol == "vmci") {
        paddr->resolved.vmci_addr = new (std::nothrow) vmci_address_t (this->get_ctx ());
        alloc_assert (paddr->resolved.vmci_addr);
        int rc = paddr->resolved.vmci_addr->resolve (address.c_str ());
        if (rc != 0) {
            LIBZMQ_DELETE(paddr);
            EXIT_MUTEX ();
            return -1;
        }
    }
#endif

    //  Create session.
    session_base_t *session = session_base_t::create (io_thread, true, this,
        options, paddr);
    errno_assert (session);

    //  PGM does not support subscription forwarding; ask for all data to be
    //  sent to this pipe. (same for NORM, currently?)
    bool subscribe_to_all = protocol == "pgm" || protocol == "epgm" || protocol == "norm" || protocol == "udp";
    pipe_t *newpipe = NULL;

    if (options.immediate != 1 || subscribe_to_all) {
        //  Create a bi-directional pipe.
        object_t *parents [2] = {this, session};
        pipe_t *new_pipes [2] = {NULL, NULL};

        bool conflate = options.conflate &&
            (options.type == ZMQ_DEALER ||
             options.type == ZMQ_PULL ||
             options.type == ZMQ_PUSH ||
             options.type == ZMQ_PUB ||
             options.type == ZMQ_SUB);

        int hwms [2] = {conflate? -1 : options.sndhwm,
            conflate? -1 : options.rcvhwm};
        bool conflates [2] = {conflate, conflate};
        rc = pipepair (parents, new_pipes, hwms, conflates);
        errno_assert (rc == 0);

        //  Attach local end of the pipe to the socket object.
        attach_pipe (new_pipes [0], subscribe_to_all);
        newpipe = new_pipes [0];

        //  Attach remote end of the pipe to the session object later on.
        session->attach_pipe (new_pipes [1]);
    }

    //  Save last endpoint URI
    paddr->to_string (last_endpoint);

    add_endpoint (addr_, (own_t *) session, newpipe);
    EXIT_MUTEX ();
    return 0;
}
Exemple #22
0
/*
 * search for P-CSCF contact in usrloc
 * @udomain_t* _d - domain to search in
 * @str* _contact - contact to search for - should be a SIP URI
 * @struct pontact** _c - contact to return to if found (null if not found)
 * @return 0 if found <>0 if not
 */
int get_pcontact(udomain_t* _d, str* _contact, str* _received_host, int received_port, struct pcontact** _c) {
	unsigned int sl, i, aorhash;
	struct pcontact* c;
	ppublic_t* impu;
	struct sip_uri needle_uri, impu_uri;
	int port_match = 0;
	str alias_host = {0, 0};
	struct sip_uri contact_uri;
	
	if (parse_uri(_contact->s, _contact->len, &needle_uri) != 0 ) {
		LM_ERR("failed to parse search URI [%.*s]\n", _contact->len, _contact->s);
		return 1;
	}

	LM_DBG("Searching for contact in P-CSCF usrloc [%.*s]\n",
				_contact->len,
				_contact->s);
	
	/* search in cache */
	aorhash = get_aor_hash(_d, _contact, _received_host, received_port);
	sl = aorhash & (_d->size - 1);
	c = _d->table[sl].first;

	for (i = 0; i < _d->table[sl].n; i++) {

		if ((c->aorhash == aorhash) && (c->aor.len == _contact->len)
				&& !memcmp(c->aor.s, _contact->s, _contact->len)) {
			*_c = c;
			return 0;
		}
		
		if(match_contact_host_port) {
		    LM_DBG("Comparing needle user@host:port [%.*s@%.*s:%d] and contact_user@contact_host:port [%.*s@%.*s:%d]\n", needle_uri.user.len, needle_uri.user.s, 
			    needle_uri.host.len, needle_uri.host.s, needle_uri.port_no,
			    c->contact_user.len, c->contact_user.s, c->contact_host.len, c->contact_host.s, c->contact_port);

		    if((needle_uri.user.len == c->contact_user.len && (memcmp(needle_uri.user.s, c->contact_user.s, needle_uri.user.len) ==0)) &&
			    (needle_uri.host.len == c->contact_host.len && (memcmp(needle_uri.host.s, c->contact_host.s, needle_uri.host.len) ==0)) &&
			    (needle_uri.port_no == c->contact_port)) {
			LM_DBG("Match!!\n");
			*_c = c;
			return 0;
		    }
		}
		
		LM_DBG("Searching for [%.*s] and comparing to [%.*s]\n", _contact->len, _contact->s, c->aor.len, c->aor.s);

		/* hosts HAVE to match */
		if (lookup_check_received && ((needle_uri.host.len != c->received_host.len) || (memcmp(needle_uri.host.s, c->received_host.s, needle_uri.host.len)!=0))) {
			//can't possibly match
			LM_DBG("Lookup failed for [%.*s <=> %.*s]\n", needle_uri.host.len, needle_uri.host.s, c->received_host.len, c->received_host.s);
			c = c->next;
			continue;
		}

		/* one of the ports must match, either the initial registered port, the received port, or one if the security ports (server) */
		if ((needle_uri.port_no != c->contact_port) && (needle_uri.port_no != c->received_port)) {
			//check security ports
			if (c->security) {
				switch (c->security->type) {
				case SECURITY_IPSEC: {
					ipsec_t* ipsec = c->security->data.ipsec;
					if (ipsec) {
						LM_DBG("security server port is %d\n", ipsec->port_us);
						LM_DBG("security client port is %d\n", ipsec->port_uc);
						if (ipsec->port_us == needle_uri.port_no) {
							LM_DBG("security port mathes contact\n");
							port_match = 1;
						}
					}
					break;
				}
				case SECURITY_TLS:
				case SECURITY_NONE:
					LM_WARN("not implemented\n");
					break;
				}
			}
			if (!port_match && c->security_temp) {
				switch (c->security_temp->type) {
				case SECURITY_IPSEC: {
					ipsec_t* ipsec = c->security_temp->data.ipsec;
					if (ipsec) {
						LM_DBG("temp security server port is %d\n", ipsec->port_us);
						LM_DBG("temp security client port is %d\n", ipsec->port_uc);
						if (ipsec->port_us == needle_uri.port_no) {
							LM_DBG("temp security port mathes contact\n");
							port_match = 1;
						}
					}
					break;
				}
				case SECURITY_TLS:
				case SECURITY_NONE:
					LM_WARN("not implemented\n");
					break;
				}
			}
		} else {
			port_match = 1;
		}

		if (!port_match){
			LM_DBG("Port don't match: %d (contact) %d (received) != %d!\n",
		c->contact_port, c->received_port, needle_uri.port_no);
			c = c->next;
			continue;
		}

		/* user parts must match (if not wildcarded) with either primary contact OR with any userpart in the implicit set (associated URIs).. */
		if((needle_uri.user.len == c->contact_user.len) && (memcmp(needle_uri.user.s, c->contact_user.s,needle_uri.user.len) == 0)) {
		    LM_DBG("Needle user part matches contact user part therefore this is a match\n");
		    *_c = c;
		    return 0;
		} else if ((needle_uri.user.len == 1) && (memcmp(needle_uri.user.s, "*", 1) == 0)) { /*wild card*/
		    LM_DBG("This a wild card user part - we must check if hosts match or needle host matches alias\n");
		    if(memcmp(needle_uri.host.s, c->contact_host.s, needle_uri.host.len) == 0) {
			LM_DBG("Needle host matches contact host therefore this is a match\n");
			*_c = c;
			return 0;
		    } else if ((parse_uri(c->aor.s, c->aor.len, &contact_uri) == 0) && ((get_alias_host_from_contact(&contact_uri.params, &alias_host)) == 0) &&
			    (memcmp(needle_uri.host.s, alias_host.s, alias_host.len) == 0)) {
			LM_DBG("Needle host matches contact alias therefore this is a match\n");
			*_c = c;
			return 0;
			
		    }
		}

		/* check impus user parts */
		impu = c->head;
		while (impu) {
			if (parse_uri(impu->public_identity.s, impu->public_identity.len, &impu_uri) != 0) {
				LM_ERR("failed to parse IMPU URI [%.*s]...continuing\n", impu->public_identity.len, impu->public_identity.s);
				impu = impu->next;
				continue;
			}
			LM_DBG("comparing first %d chars of impu [%.*s] for contact userpart [%.*s]\n",
					needle_uri.user.len,
					impu->public_identity.len, impu->public_identity.s,
					needle_uri.user.len, needle_uri.user.s);
			if (needle_uri.user.len == impu_uri.user.len && (memcmp(needle_uri.user.s, impu_uri.user.s, impu_uri.user.len)==0)) {
				*_c = c;
				return 0;
			}
			impu = impu->next;
		}

		c = c->next;
	}
	return 1; /* Nothing found */
}
Exemple #23
0
/*
 * handle HTTP request/response transaction of a thread
 * clinet-----(request)----->server
 *       <------(data)-------
 */
void *doit(void *connfd) {
    int fd = *(int *)connfd;
    int fd_server;
    /* detach thread */
    Pthread_detach(pthread_self());

    rio_t rio;
    char buf[MAXLINE], object_buf[MAX_OBJECT_SIZE];
    char method[MAXLINE], uri[MAXLINE], version[MAXLINE];

    /* uri info */
    char host[MAXLINE];
    int port;
    char filename[MAXLINE];

    /* Read request line and headers */
    Rio_readinitb(&rio, fd);
    Rio_readlineb(&rio, buf, MAXLINE);
    sscanf(buf, "%s %s %s", method, uri, version);

    /* request method is not GET */
    if (strcmp(method, "GET")) {
        printerror(fd, method, "501", "Not Implemented",
            "tianqiw's proxy does not implement this method");
        Close(fd);
        return NULL;
    }

    /* request method is GET
     * look for the object in cache */
    cache_block *block = cache_match(cache_ptr, uri);

    if (block != NULL) {
        /* cache hit */
        Rio_writen(fd, block->object, block->object_size);
    }
    else {
        /* cache miss */
        parse_uri(uri, host, &port, filename);

        /* construct the request header */
        char request_buf[MAXLINE];
        requestHdr(&rio, request_buf, host, filename);

        /* send request to server */
        if ((fd_server = open_clientfd_r(host, port)) < 0) {
            /* server connection error */
            char longmsg[MAXBUF];
            sprintf(longmsg, "Cannot open connection to server at <%s, %d>", host, port);
            printerror(fd, "Connection Failed", "404", "Not Found", longmsg);
            Close(fd);
            return NULL;
        }

        /* reset rio for server use */
        memset(&rio, 0, sizeof(rio_t));
        Rio_readinitb(&rio, fd_server);
        Rio_writen(fd_server, request_buf, strlen(request_buf));

        /* get data from server and send to client */
        size_t object_size = 0;
        size_t buflen;
        int is_exceed = 0;

        while ((buflen = Rio_readlineb(&rio, buf, MAXLINE))) {
            Rio_writen(fd, buf, buflen);

            /* size of the buffer exceeds the max object size
             * discard the buffer */
            if ((object_size + buflen) > MAX_OBJECT_SIZE) {
                is_exceed = 1;
            }
            else {
                memcpy(object_buf + object_size, buf, buflen);
                object_size += buflen;
            }
        }

        /* if not exceed the max object size, insert to cache */
        if (!is_exceed) {
            cache_insert(cache_ptr, uri, object_buf, object_size);
        }

        /* clear the buffer */
        Close(fd_server);
    }

    Close(fd);
    return NULL;
}
Exemple #24
0
/* it checks if a user is member of a group */
int diameter_is_user_in(struct sip_msg* _m, char* _hf, char* _group)
{
	str *grp, user_name, user, domain, uri;
	dig_cred_t* cred = 0;
	int hf_type;
	struct hdr_field* h;
	struct sip_uri puri;
	AAAMessage *req;
	AAA_AVP *avp; 
	int ret;
	unsigned int tmp;
	char *p = NULL;

	grp = (str*)_group; /* via fixup */

	hf_type = (int)(long)_hf;

	uri.s = 0;
	uri.len = 0;

	/* extract the uri according with the _hf parameter */
	switch(hf_type) 
	{
		case 1: /* Request-URI */
			uri = *(GET_RURI(_m));
		break;

		case 2: /* To */
			if (get_to_uri(_m, &uri) < 0) 
			{
				LM_ERR("failed to extract To\n");
				return -2;
			}
			break;

		case 3: /* From */
			if (get_from_uri(_m, &uri) < 0) 
			{
				LM_ERR("failed to extract From URI\n");
				return -3;
			}
			break;

		case 4: /* Credentials */
			get_authorized_cred(_m->authorization, &h);
			if (!h) 	
			{
				get_authorized_cred(_m->proxy_auth, &h);
				if (!h) 
				{
					LM_ERR("no authorized credentials found "
							"(error in scripts)\n");
					return -4;
				}
			}
			cred = &((auth_body_t*)(h->parsed))->digest;
			break;
	}

	if (hf_type != 4) 
	{
		if (parse_uri(uri.s, uri.len, &puri) < 0) 
		{
			LM_ERR("failed to parse URI\n");
			return -5;
		}
		user = puri.user;
		domain = puri.host;
	} 
	else
	{
		user = cred->username.user;
		domain = cred->realm;
	}
	
	/* user@domain mode */
	if (use_domain)
	{
		user_name.s = 0;
		user_name.len = user.len + domain.len;
		if(user_name.len>0)
		{
			user_name.len++;
			p = (char*)pkg_malloc(user_name.len);
			if (!p)
			{
				LM_ERR("no pkg memory left\n");
				return -6;
			}
			user_name.s = p;
		
			memcpy(user_name.s, user.s, user.len);
			if(user.len>0)
			{
				user_name.s[user.len] = '@';
				memcpy(user_name.s + user.len + 1, domain.s, domain.len);
			}
			else
				memcpy(user_name.s, domain.s, domain.len);
		}
	} 
	else 
		user_name = user;
	
	
	if ( (req=AAAInMessage(AA_REQUEST, AAA_APP_NASREQ))==NULL)
	{
		LM_ERR("can't create new AAA message!\n");
		if(p) pkg_free(p);
		return -1;
	}
	
	/* Username AVP */
	if( (avp=AAACreateAVP(AVP_User_Name, 0, 0, user_name.s,
				user_name.len, AVP_DUPLICATE_DATA)) == 0)
	{
		LM_ERR("no more pkg memory!\n");
		goto error;
	}
	if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
	{
		LM_ERR("avp not added \n");
		goto error1;
	}

	/* Usergroup AVP */
	if( (avp=AAACreateAVP(AVP_User_Group, 0, 0, grp->s,
				grp->len, AVP_DUPLICATE_DATA)) == 0)
	{
		LM_ERR("no more pkg memory!\n");
		goto error;
	}
	if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
	{
		LM_ERR("avp not added \n");
		goto error1;
	}

	/* SIP_MSGID AVP */
	LM_DBG("******* m_id=%d\n", _m->id);
	tmp = _m->id;
	if( (avp=AAACreateAVP(AVP_SIP_MSGID, 0, 0, (char*)(&tmp), 
				sizeof(tmp), AVP_DUPLICATE_DATA)) == 0)
	{
		LM_ERR("no more pkg memory!\n");
		goto error;
	}
	if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
	{
		LM_ERR("avp not added \n");
		goto error1;
	}

	
	/* ServiceType AVP */
	if( (avp=AAACreateAVP(AVP_Service_Type, 0, 0, SIP_GROUP_CHECK, 
				SERVICE_LEN, AVP_DUPLICATE_DATA)) == 0)
	{
		LM_ERR("no more pkg memory!\n");
		goto error;
	}
	if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
	{
		LM_ERR("avp not added \n");
		goto error1;
	}
	

	/* Destination-Realm AVP */
	uri = *(GET_RURI(_m));
	parse_uri(uri.s, uri.len, &puri);
	if( (avp=AAACreateAVP(AVP_Destination_Realm, 0, 0, puri.host.s,
						puri.host.len, AVP_DUPLICATE_DATA)) == 0)
	{
		LM_ERR("no more pkg memory!\n");
		goto error;
	}
	
	if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
	{
		LM_ERR("avp not added \n");
		goto error1;
	}
	
#ifdef DEBUG
	AAAPrintMessage(req);
#endif

	/* build a AAA message buffer */
	if(AAABuildMsgBuffer(req) != AAA_ERR_SUCCESS)
	{
		LM_ERR("message buffer not created\n");
		goto error;
	}

	if(sockfd==AAA_NO_CONNECTION)
	{
		sockfd = init_mytcp(diameter_client_host, diameter_client_port);
		if(sockfd==AAA_NO_CONNECTION)
		{
			LM_ERR("failed to reconnect to Diameter client\n");
			goto error;
		}
	}

	ret =tcp_send_recv(sockfd, req->buf.s, req->buf.len, rb, _m->id);

	if(ret == AAA_CONN_CLOSED)
	{
		LM_NOTICE("connection to Diameter client closed."
				"It will be reopened by the next request\n");
		close(sockfd);
		sockfd = AAA_NO_CONNECTION;
		goto error;
	}
	if(ret != AAA_USER_IN_GROUP)
	{
		LM_ERR("message sending to the DIAMETER backend authorization server"
				"failed or user is not in group\n");
		goto error;
	}
	
	AAAFreeMessage(&req);
	return 1;

error1:
	AAAFreeAVP(&avp);
error:
	AAAFreeMessage(&req);
	return -1;

}
Exemple #25
0
/*
 * Check from Radius if a user belongs to a group. User-Name is digest
 * username or digest username@realm, SIP-Group is group, and Service-Type
 * is Group-Check.  SIP-Group is SER specific attribute and Group-Check is
 * SER specific service type value.
 */
int radius_is_user_in(struct sip_msg* _m, char* _hf, char* _group)
{
	str *grp, user_name, user, domain, uri;
	dig_cred_t* cred = 0;
	int hf_type;
	UINT4 service;
	VALUE_PAIR *send, *received;
	static char msg[4096];
	struct hdr_field* h;
	struct sip_uri puri;

	grp = (str*)_group; /* via fixup */
	send = received = 0;

	hf_type = (int)(long)_hf;

	uri.s = 0;
	uri.len = 0;

	switch(hf_type) {
	case 1: /* Request-URI */
		if (get_request_uri(_m, &uri) < 0) {
			LOG(L_ERR, "radius_is_user_in(): Error while extracting Request-URI\n");
			return -1;
		}
		break;

	case 2: /* To */
		if (get_to_uri(_m, &uri) < 0) {
			LOG(L_ERR, "radius_is_user_in(): Error while extracting To\n");
			return -2;
		}
		break;

	case 3: /* From */
		if (get_from_uri(_m, &uri) < 0) {
			LOG(L_ERR, "radius_is_user_in(): Error while extracting From\n");
			return -3;
		}
		break;

	case 4: /* Credentials */
		get_authorized_cred(_m->authorization, &h);
		if (!h) {
			get_authorized_cred(_m->proxy_auth, &h);
			if (!h) {
				LOG(L_ERR, "radius_is_user_in(): No authorized credentials found (error in scripts)\n");
				return -4;
			}
		}
		cred = &((auth_body_t*)(h->parsed))->digest;
		break;
	}

	if (hf_type != 4) {
		if (parse_uri(uri.s, uri.len, &puri) < 0) {
			LOG(L_ERR, "radius_is_user_in(): Error while parsing URI\n");
			return -5;
		}
		user = puri.user;
		domain = puri.host;
	} else {
		user = cred->username.user;
		domain = *GET_REALM(cred);
	}
		

	if (use_domain) {
		user_name.len = user.len + domain.len + 1;
		user_name.s = (char*)pkg_malloc(user_name.len);
		if (!user_name.s) {
			LOG(L_ERR, "radius_is_user_in(): No memory left\n");
			return -6;
		}
		
		memcpy(user_name.s, user.s, user.len);
		user_name.s[user.len] = '@';
		memcpy(user_name.s + user.len + 1, domain.s, domain.len);
	} else {
		user_name = user;
	}

	if (!rc_avpair_add(rh, &send, attrs[A_USER_NAME].v, user_name.s, user_name.len, 0)) {
		LOG(L_ERR, "radius_is_user_in(): Error adding User-Name attribute\n");
		rc_avpair_free(send);
		if (use_domain) pkg_free(user_name.s);
		return -7;
	}

	if (use_domain) pkg_free(user_name.s);

	if (!rc_avpair_add(rh, &send, attrs[A_SIP_GROUP].v, grp->s, grp->len, 0)) {
		LOG(L_ERR, "radius_is_user_in(): Error adding Sip-Group attribute\n");
	 	return -8;  	
	}

	service = vals[V_GROUP_CHECK].v;
	if (!rc_avpair_add(rh, &send, attrs[A_SERVICE_TYPE].v, &service, -1, 0)) {
		LOG(L_ERR, "radius_is_user_in(): Error adding Service-Type attribute\n");
		rc_avpair_free(send);
	 	return -9;  	
	}

	if (rc_auth(rh, 0, send, &received, msg) == OK_RC) {
		DBG("radius_is_user_in(): Success\n");
		rc_avpair_free(send);
		rc_avpair_free(received);
		return 1;
	} else {
		DBG("radius_is_user_in(): Failure\n");
		rc_avpair_free(send);
		rc_avpair_free(received);
		return -11;
	}
}
//
// Ref. RFC 3261 "12.2.1.1 Generating the Request"
//
int trans_layer::set_next_hop(list<sip_header*>& route_hdrs, 
			      cstring& r_uri, 
			      sockaddr_storage* remote_ip)
{
    string         next_hop;
    unsigned short next_port=0; 

    //assert(msg->type == SIP_REQUEST);

    int err=0;

    if(!route_hdrs.empty()){
	
	sip_header* fr = route_hdrs.front();
	
	sip_nameaddr na;
	const char* c = fr->value.s;
	if(parse_nameaddr(&na, &c, fr->value.len)<0) {
	    
	    DBG("Parsing name-addr failed\n");
	    return -1;
	}
	
	if(parse_uri(&na.uri,na.addr.s,na.addr.len) < 0) {
	    
	    DBG("Parsing route uri failed\n");
	    return -1;
	}

	bool is_lr = false;
	if(!na.uri.params.empty()){
	    
	    list<sip_avp*>::iterator it = na.uri.params.begin();
	    for(;it != na.uri.params.end(); it++){
		
		if( ((*it)->name.len == 2) && 
		    (!memcmp((*it)->name.s,"lr",2)) ) {

		    is_lr = true;
		    break;
		}
	    }

	}

	if (SipCtrlInterfaceFactory::outbound_host.empty()) {
	    next_hop  = c2stlstr(na.uri.host);
	    next_port = na.uri.port;
	} else {
	    next_hop = SipCtrlInterfaceFactory::outbound_host;
	    next_port = SipCtrlInterfaceFactory::outbound_port;
	}	    

	if(!is_lr){
	    
	    // detect beginning of next route

	    enum {
		RR_PARAMS=0,
		RR_QUOTED,
		RR_SEP_SWS,  // space(s) after ','
		RR_NXT_ROUTE
	    };

	    int st = RR_PARAMS;
	    const char* end = fr->value.s + fr->value.len;
	    for(;c<end;c++){
		
		switch(st){
		case RR_PARAMS:
		    switch(*c){
		    case SP:
		    case HTAB:
		    case CR:
		    case LF:
			break;
		    case COMMA:
			st = RR_SEP_SWS;
			break;
		    case DQUOTE:
			st = RR_QUOTED;
			break;
		    }
		    break;
		case RR_QUOTED:
		    switch(*c){
		    case BACKSLASH:
			c++;
			break;
		    case DQUOTE:
			st = RR_PARAMS;
			break;
		    }
		    break;
		case RR_SEP_SWS:
		    switch(*c){
		    case SP:
		    case HTAB:
		    case CR:
		    case LF:
			break;
		    default:
			st = RR_NXT_ROUTE;
			goto nxt_route;
		    }
		    break;
		}
	    }

	nxt_route:
	    
	    switch(st){
	    case RR_QUOTED:
	    case RR_SEP_SWS:
		DBG("Malformed first route header\n");
	    case RR_PARAMS:
		// remove current route header from message
		DBG("delete (fr=0x%p)\n",fr);
		delete fr; // route_hdrs.front();
		route_hdrs.pop_front();
		DBG("route_hdrs.length() = %i\n",(int)route_hdrs.size());
		break;
		
	    case RR_NXT_ROUTE:
		// remove current route from this header
		fr->value.s   = c;
		fr->value.len = end-c;
		break;
	    }

	    
	    // copy r_uri at the end of 
	    // the route set.
	    route_hdrs.push_back(new sip_header(0,"Route",r_uri));

	    r_uri = na.addr;
	}
	
    }
    else {

	if (SipCtrlInterfaceFactory::outbound_host.empty()) {
	    sip_uri parsed_r_uri;
	    err = parse_uri(&parsed_r_uri,r_uri.s,r_uri.len);
	    if(err < 0){
		ERROR("Invalid Request URI\n");
		return -1;
	    }
	    next_hop  = c2stlstr(parsed_r_uri.host);
	    next_port = parsed_r_uri.port;
	} else {
	    next_hop = SipCtrlInterfaceFactory::outbound_host;
	    next_port = SipCtrlInterfaceFactory::outbound_port;
	}
    }

    DBG("next_hop:next_port is <%s:%u>\n", next_hop.c_str(), next_port);
    
    err = resolver::instance()->resolve_name(next_hop.c_str(),
					     remote_ip,IPv4,UDP);
    if(err < 0){
	ERROR("Unresolvable Request URI\n");
	return -1;
    }

    ((sockaddr_in*)remote_ip)->sin_port = htons(next_port);
    
    return 0;
}
Exemple #27
0
/**
 * rewrites the request URI of msg by calculating a rule, using
 * crc32 for hashing. The request URI is used to determine tree node
 * the given _user is used to determine the routing tree.
 *
 * @param msg the current SIP message
 * @param _uri the URI to determine the route tree (string or pseudo-variable)
 * @param _domain the requested routing domain
 *
 * @return 1 on success, -1 on failure
 */
int user_route_uri(struct sip_msg * _msg, char * _uri, char * _domain) {
	pv_elem_t *model;
	str uri, user, str_domain, ruser, ruri;
	struct sip_uri puri;
	int carrier_id, domain, index;
	domain = (int)(long)_domain;
	struct rewrite_data * rd = NULL;
	struct carrier_tree * ct = NULL;

	if (!_uri) {
		LM_ERR("bad parameter\n");
		return -1;
	}
	
	if (parse_sip_msg_uri(_msg) < 0) {
		return -1;
	}

	/* Retrieve uri from parameter */
	model = (pv_elem_t*)_uri;
	if (pv_printf_s(_msg, model, &uri)<0)	{
		LM_ERR("cannot print the format\n");
		return -1;
	}

	if (parse_uri(uri.s, uri.len, &puri) < 0) {
		LM_ERR("Error while parsing URI\n");
		return -5;
	}
	user = puri.user;
	str_domain = puri.host;

	ruser.s = _msg->parsed_uri.user.s;
	ruser.len = _msg->parsed_uri.user.len;
	ruri.s = _msg->parsed_uri.user.s;
	ruri.len = _msg->parsed_uri.user.len;

	do {
		rd = get_data();
	} while (rd == NULL);

	if ((carrier_id = load_user_carrier(&user, &str_domain)) < 0) {
		release_data(rd);
		return -1;
	} else if (carrier_id == 0) {
		index = rd->default_carrier_index;
	} else {
		if ((ct = get_carrier_tree(carrier_id, rd)) == NULL) {
			if (fallback_default) {
				index = rd->default_carrier_index;
			} else {
				LM_ERR("desired routing tree with id %i doesn't exist\n",
					carrier_id);
				release_data(rd);
				return -1;
			}
		} else {
			index = ct->index;
		}
	}
	release_data(rd);
	return carrier_rewrite_msg(index, domain, &ruri, _msg, &ruser, shs_call_id, alg_crc32);
}
Exemple #28
0
static int ki_xcaps_get(sip_msg_t* msg, str* uri, str* path)
{
	struct sip_uri turi;
	str etag = {0, 0};
	str body = {0, 0};
	str new_body = {0, 0};
	int ret = 0;
	xcap_uri_t xuri;
	str *ctype;
	str allow;

	if(uri->s==NULL || uri->len == 0)
	{
		LM_ERR("invalid uri parameter\n");
		return -1;
	}

	if(path->s==NULL || path->len == 0)
	{
		LM_ERR("invalid path parameter\n");
		return -1;
	}

	if(parse_uri(uri->s, uri->len, &turi)!=0)
	{
		LM_ERR("parsing uri parameter [%.*s]\n", uri->len, uri->s);
		goto error;
	}

	if(xcap_parse_uri(path, &xcaps_root, &xuri)<0)
	{
		LM_ERR("cannot parse xcap uri [%.*s]\n", path->len, path->s);
		goto error;
	}

	switch(xuri.type)
	{
	case DIRECTORY:
		if (strncmp(xuri.file.s, "directory.xml", xuri.file.len) == 0)
		{
			if (xcaps_get_directory(msg, &turi.user, &turi.host, &body) < 0)
				goto error;

			xcaps_send_reply(msg, 200, &xcaps_str_ok, NULL, &xcaps_str_appdrxml, &body);
		}
		else
		{
			xcaps_send_reply(msg, 404, &xcaps_str_notfound, NULL, NULL, NULL);
		}
		break;
	case XCAP_CAPS:
		xcaps_send_reply(msg, 501, &xcaps_str_notimplemented, NULL, NULL, NULL);
		break;
	case SEARCH:
		allow.s = xcaps_hdr_buf;
		allow.len = snprintf(allow.s, XCAPS_HDR_SIZE, "Allow: POST\r\n");
		xcaps_send_reply(msg, 405, &xcaps_str_notallowed, &allow, NULL, NULL);
		break;
	default:
		if((ret=xcaps_get_db_etag(&turi.user, &turi.host, &xuri, &etag))<0)
		{ 
			LM_ERR("could not fetch etag for xcap document\n");
			goto error;
		}
		if (ret==1)
		{
			/* doc not found */
			xcaps_send_reply(msg, 404, &xcaps_str_notfound, NULL,
					NULL, NULL);
			return 1;
		}
	
		if((ret=check_preconditions(msg, etag))==-1)
		{
			xcaps_send_reply(msg, 412, &xcaps_str_precon, NULL,
					NULL, NULL);
			return -2;
		} else if (ret==-2) {
			xcaps_send_reply(msg, 304, &xcaps_str_notmod, NULL,
					NULL, NULL);
			return -2;
		}

		if((ret=xcaps_get_db_doc(&turi.user, &turi.host, &xuri, &body))<0)
		{
			LM_ERR("could not fetch xcap document\n");
			goto error;
		}
		if(ret!=0)
		{
			/* doc not found */
			xcaps_send_reply(msg, 404, &xcaps_str_notfound, NULL,
					NULL, NULL);
			break;
		}

		if(xuri.nss!=NULL && xuri.node.len>0)
		{
			if((new_body.s = pkg_malloc(body.len))==NULL)
			{
				LM_ERR("allocating package memory\n");
				goto error;
			}
			new_body.len = body.len;
			
			if(xcaps_xpath_hack(&body, 0)<0)
			{
				LM_ERR("could not hack xcap document\n");
				goto error;
			}
			if(xcaps_xpath_get(&body, &xuri.node, &new_body)<0)
			{
				LM_ERR("could not retrieve element from xcap document\n");
				goto error;
			}
			if(new_body.len<=0)
			{
				/* element not found */
				xcaps_send_reply(msg, 404, &xcaps_str_notfound, NULL,
					NULL, NULL);
				pkg_free(new_body.s);
				new_body.s = NULL;
				break;
			}
			if(xcaps_xpath_hack(&new_body, 1)<0)
			{
				LM_ERR("could not hack xcap document\n");
				goto error;
			}
			memcpy(body.s, new_body.s, new_body.len);
			body.len = new_body.len;
			pkg_free(new_body.s);
			new_body.s = NULL;
		}

		/* doc or element found */
		ctype = &xcaps_str_appxml;
		if(xuri.type==RESOURCE_LIST)
			ctype = &xcaps_str_apprlxml;
		else if(xuri.type==PRES_RULES)
			ctype = &xcaps_str_appapxml;
		else if(xuri.type==RLS_SERVICE)
			ctype = &xcaps_str_apprsxml;
		else if(xuri.type==USER_PROFILE)
			ctype = &xcaps_str_appupxml;
		else if(xuri.type==PRES_CONTENT)
			ctype = &xcaps_str_apppcxml;
		else if(xuri.type==PIDF_MANIPULATION)
			ctype = &xcaps_str_apppdxml;
		xcaps_send_reply(msg, 200, &xcaps_str_ok, &etag,
				ctype, &body);

		break;
	}

	return 1;

error:
	if (new_body.s) pkg_free(new_body.s);
	xcaps_send_reply(msg, 500, &xcaps_str_srverr, NULL,
				NULL, NULL);
	return -1;
}
Exemple #29
0
int add_cc_agent( struct cc_data *data, str *id, str *location,
				str *skills, unsigned int logstate, unsigned int last_call_end)
{
	struct cc_agent *agent, *prev_agent= 0;
	struct sip_uri uri;
	str skill;
	char *p;
	unsigned int n,skill_id;
#ifdef STATISTICS
	char *name;
	str s;
#endif

	/* is the agent a new one? - search by ID */
	agent = get_agent_by_name( data, id, &prev_agent);

	if (agent==NULL) {
		/* new agent -> create and populate one */
		agent = (struct cc_agent*)shm_malloc(sizeof(struct cc_agent)+id->len);
		if (agent==NULL) {
			LM_ERR("not enough shmem for a new agent\n");
			goto error;
		}
		memset( agent, 0, sizeof(struct cc_agent) );
		/* id */
		agent->id.s = (char*)(agent+1);
		memcpy( agent->id.s, id->s, id->len);
		agent->id.len = id->len;
		/* location */
		agent->location.s = (char*)shm_malloc(location->len);
		if (agent->location.s==NULL) {
			LM_ERR("not enough shmem for the location of the agent\n");
			goto error;
		}
		memcpy( agent->location.s, location->s, location->len);
		agent->location.len = location->len;
		if (parse_uri( agent->location.s, agent->location.len, &uri)<0) {
			LM_ERR("location of the agent is not a SIP URI\n");
			goto error;
		}
		agent->did = uri.user;
		/* LOG STATE */
		agent->loged_in = logstate;
		/* set of skills */
		if (skills && skills->len) {
			p = skills->s;
			while (p) {
				skill.s = p;
				p = q_memchr(skill.s, ',', skills->s+skills->len-skill.s);
				skill.len = p?(p-skill.s):(skills->s+skills->len-skill.s);
				trim(&skill);
				if (skill.len) {
					skill_id = get_skill_id(data,&skill);
					if (skill_id==0) {
						LM_ERR("cannot get skill id\n");
						goto error;
					}
					n = agent->no_skills++; 
					agent->skills[n] = skill_id;
				}
				if(p)
					p++;
			}
		}
		/* statistics */
#ifdef STATISTICS
		s.s = "cca_dist_incalls";s.len = 16 ;
		if ( (name=build_stat_name( &s, id->s))==0 || register_stat("call_center",
		name, &agent->st_dist_incalls, STAT_SHM_NAME)!=0 ) {
			LM_ERR("failed to add stat variable\n");
			goto error;
		}
		s.s = "cca_answ_incalls";s.len = 16 ;
		if ( (name=build_stat_name( &s, id->s))==0 || register_stat("call_center",
		name, &agent->st_answ_incalls, STAT_SHM_NAME)!=0 ) {
			LM_ERR("failed to add stat variable\n");
			goto error;
		}
		s.s = "cca_aban_incalls";s.len = 16 ;
		if ( (name=build_stat_name( &s, id->s))==0 || register_stat("call_center",
		name, &agent->st_aban_incalls, STAT_SHM_NAME)!=0 ) {
			LM_ERR("failed to add stat variable\n");
			goto error;
		}
		s.s = "cca_att";s.len = 7 ;
		if ( (name=build_stat_name( &s, id->s))==0 || register_stat2("call_center",
		name, (stat_var **)cc_agent_get_att, STAT_SHM_NAME|STAT_IS_FUNC,
		(void*)agent, 0)!=0) {
			LM_ERR("failed to add stat variable\n");
			goto error;
		}
#endif
		if(last_call_end && (last_call_end + wrapup_time < (int)time(NULL))) {
			agent->state = CC_AGENT_WRAPUP;
			agent->last_call_end = last_call_end - startup_time; /* it will be a negative value */
		}
		agent->is_new = 1;
		/* link the agent */
		add_cc_agent_top(data, agent);
		data->totalnr_agents++;
	} else {
		/* agent already exists -> update only */
		/* location - needs to be changed ? */
		if ( agent->location.len!=location->len ||
			memcmp(agent->location.s,location->s,location->len)!=0 ) {
			/* set new location */
			if (agent->location.len < location->len ){
				shm_free(agent->location.s);
				agent->location.s = (char*)shm_malloc(location->len);
				if (agent->location.s==NULL) {
					LM_ERR("not enough shmem for the location of the agent\n");
					goto error1;
				}
			}
			memcpy( agent->location.s, location->s, location->len);
			agent->location.len = location->len;
			if (parse_uri( agent->location.s, agent->location.len, &uri)<0) {
				LM_ERR("location of the agent is not a SIP URI\n");
				goto error1;
			}
			agent->did = uri.user;
		}
		/* if logstate changed - move between the lists TODO */
		if(logstate != agent->loged_in) {
			agent_switch_login(data, agent, prev_agent);
		}
		/* skills - needs to be changed ? */
		agent->no_skills = 0;
		if (skills && skills->len) {
			p = skills->s;
			while (p) {
				skill.s = p;
				p = q_memchr(skill.s, ',', skills->s+skills->len-skill.s);
				skill.len = p?(p-skill.s):(skills->s+skills->len-skill.s);
				trim(&skill);
				if (skill.len) {
					skill_id = get_skill_id(data,&skill);
					if (skill_id==0) {
						LM_ERR("cannot get skill id\n");
						goto error1;
					}
					n = agent->no_skills++; 
					agent->skills[n] = skill_id;
				}
				if(p)
					p++;
			}
		}
		agent->is_new = 1;
	}

	return 0;
error1:
	remove_cc_agent(data, agent, prev_agent);
error:
	if (agent)
		free_cc_agent(agent);
	return 0;
}
Exemple #30
0
int
encode2format (struct sip_msg* msg, str* uri, struct uri_format *format)
{
	int foo;
	char *string, *pos, *start, *end;
	struct sip_uri sipUri;
	int scheme_len;


	if (uri->s == NULL)
		return -1;
	string = uri->s;


	pos = q_memchr (string, '<', uri->len);
	if (pos != NULL)	/* we are only interested of chars inside <> */
	{
		start = q_memchr (string, ':', uri->len);
		if (start == NULL)	return -2;
		if (start - pos < 4) return -3;
		if ((*(start-1)|0x20)=='s' && (start-pos)>4)
			/* if it ends in s: it is a sips or tels uri */
			scheme_len=4;
		else
			scheme_len=3;
		start-=scheme_len;
		end = strchr (start, '>');
		if (end == NULL)
			return -4;	/* must be a match to < */
	}
	else			/* we do not have  <> */
	{
		pos=string;
		start = q_memchr (string, ':', uri->len);
		if (start == NULL)
			return -5;
		if (start - pos < 3)
			return -6;
		if ((*(start-1)|0x20)=='s' && (start-pos)>3)
			/* if it ends in s: it is a sips or tels uri */
			scheme_len=4;
		else
			scheme_len=3;
		start = start - scheme_len;
		end = string + uri->len;
	}
	memset(format,0,sizeof(struct uri_format));
	format->first = start - string + scheme_len+1 /* ':' */;
	format->second = end - string;
	/* --------------------------testing ------------------------------- */
	/* sip:gva@[email protected];;transport=udp>;expires=2 INCORECT BEHAVIOR OF parse_uri,myfunction works good */
	foo = parse_uri (start, end - start, &sipUri);
	if (foo != 0)
	{
		LOG(L_ERR,"ERROR: encode2format: parse_uri failed on [%.*s]."
				"Code %d \n", uri->len, uri->s, foo);
		return foo-10;
	}

	
	format->username = sipUri.user;
	format->password = sipUri.passwd;
	format->ip = sipUri.host;
	format->port = sipUri.port;
	format->protocol = sipUri.transport_val;
	format->transport=sipUri.transport; /* the whole transport header */
	format->rest.s = sipUri.port.s?(sipUri.port.s+sipUri.port.len):
						(sipUri.host.s+sipUri.host.len);
	format->rest.len = (int)(end-format->rest.s);
	format->rcv_ip.s=ip_addr2a(&msg->rcv.src_ip);
	format->rcv_ip.len=strlen(format->rcv_ip.s);
	if (msg->rcv.src_port!=SIP_PORT){
		format->rcv_port.s=
				int2str(msg->rcv.src_port, &format->rcv_port.len);
	}else{
		format->rcv_port.s=0;
		format->rcv_port.len=0;
	}
	if (msg->rcv.proto!=PROTO_UDP){
		switch(msg->rcv.proto){
			case PROTO_TCP:
				format->rcv_proto=s_tcp;
				break;
			case PROTO_TLS:
				format->rcv_proto=s_tls;
				break;
			case PROTO_SCTP:
				format->rcv_proto=s_sctp;
				break;
			default:
				BUG("unknown proto %d\n", msg->rcv.proto);
		}
	}else{
		format->rcv_proto.s=0;
		format->rcv_proto.len=0;
	}
	
#ifdef EXTRA_DEBUG	
	fprintf (stdout, "transport=[%.*s] transportval=[%.*s]\n", sipUri.transport.len,sipUri.transport.s,sipUri.transport_val.len,sipUri.transport_val.s);
	fprintf(stdout,"First %d,second %d\n",format->first,format->second);
	#endif
	
	return 0;

}