Exemple #1
0
int parse_config_lines(void)
{
	char *p,*start;
	int  i, k, step;
	int  mdm_nr, net_nr;

	nr_of_networks = 0;
	nr_of_modems = 0;

	step = 1;
	/* parsing modems configuration string */
	if ( (p = modems_config)==0) {
		LM_ERR("param \"modems\" not found\n");
		goto error;
	}
	while (*p)
	{
		eat_spaces(p);
		/*get modem's name*/
		start = p;
		while (*p!=' ' && *p!='\t' && *p!='[' && *p!=0)
			p++;
		if ( p==start || *p==0 )
			goto parse_error;
		memcpy(modems[nr_of_modems].name, start, p-start);
		modems[nr_of_modems].name[p-start] = 0;
		modems[nr_of_modems].smsc[0] = 0;
		modems[nr_of_modems].device[0] = 0;
		modems[nr_of_modems].pin[0] = 0;
		modems[nr_of_modems].mode = MODE_NEW;
		modems[nr_of_modems].retry = 4;
		modems[nr_of_modems].looping_interval = 20;
		modems[nr_of_modems].baudrate = B9600;
		modems[nr_of_modems].scan = SMS_BODY_SCAN;
		modems[nr_of_modems].to[0] = 0;
		memset(modems[nr_of_modems].net_list,0XFF,
			sizeof(modems[nr_of_modems].net_list) );
		/*get modem parameters*/
		eat_spaces(p);
		if (*p!='[')
			goto parse_error;
		p++;
		while (*p!=']')
		{
			eat_spaces(p);
			start = p;
			while(*p!=' ' && *p!='\t' && *p!=']' && *p!=';' && *p!=0)
				p++;
			if ( p==start || *p==0 )
				goto parse_error;
			if (set_modem_arg( &(modems[nr_of_modems]), start, p)==-1)
				goto error;
			eat_spaces(p);
			if (*p==';') {
				p++;
				eat_spaces(p);
			}
		}
		if (*p!=']')
			goto parse_error;
		p++;
		/* end of element */
		if (modems[nr_of_modems].device[0]==0) {
			LM_ERR("modem %s has no device associated\n",
					modems[nr_of_modems].name);
			goto error;
		}
		if (modems[nr_of_modems].smsc[0]==0) {
			LM_WARN("modem %s has no sms center associated -> using"
				" the default one from modem\n",modems[nr_of_modems].name);
		}
		nr_of_modems++;
		eat_spaces(p);
		if (*p==';') {
			p++;
			eat_spaces(p);
		}
	}
	if (nr_of_modems==0)
	{
		LM_ERR("failed to parse config modems - no modem found!\n");
		goto error;
	}

	step++;
	/* parsing networks configuration string */
	if ( (p = networks_config)==0) {
		LM_ERR("param \"networks\" not found\n");
		goto error;
	}
	while (*p)
	{
		eat_spaces(p);
		/*get network name*/
		start = p;
		while (*p!=' ' && *p!='\t' && *p!='[' && *p!=0)
			p++;
		if ( p==start || *p==0 )
			goto parse_error;
		memcpy(networks[nr_of_networks].name, start, p-start);
		networks[nr_of_networks].name[p-start] = 0;
		networks[nr_of_networks].max_sms_per_call = 10;
		/*get network parameters*/
		eat_spaces(p);
		if (*p!='[')
			goto parse_error;
		p++;
		while (*p!=']')
		{
			eat_spaces(p);
			start = p;
			while(*p!=' ' && *p!='\t' && *p!=']' && *p!=';' && *p!=0)
				p++;
			if ( p==start || *p==0 )
				goto parse_error;
			if (set_network_arg( &(networks[nr_of_networks]), start, p)==-1)
				goto error;
			eat_spaces(p);
			if (*p==';') {
				p++;
				eat_spaces(p);
			}
		}
		if (*p!=']')
			goto parse_error;
		p++;
		/* end of element */
		nr_of_networks++;
		eat_spaces(p);
		if (*p==';')
			p++;
		eat_spaces(p);
	}
	if (nr_of_networks==0)
	{
		LM_ERR("no network found!\n");
		goto error;
	}

	step++;
	/* parsing links configuration string */
	if ( (p = links_config)==0) {
		LM_ERR("param \"links\" not found\n");
		goto error;
	}
	while (*p)
	{
		eat_spaces(p);
		/*get modem's device*/
		start = p;
		while (*p!=' ' && *p!='\t' && *p!='[' && *p!=0)
			p++;
		if ( p==start || *p==0 )
			goto parse_error;
		/*looks for modem index*/
		for(mdm_nr=-1,i=0;i<nr_of_modems && mdm_nr==-1;i++)
			if (!strncasecmp(modems[i].name,start,p-start)&&
			modems[i].name[p-start]==0)
				mdm_nr = i;
		if (mdm_nr==-1) {
			LM_ERR("unknown modem %.*s \n,",(int)(p-start), start);
			goto error;
		}
		/*get associated networks list*/
		eat_spaces(p);
		if (*p!='[')
			goto parse_error;
		p++;
		k=0;
		while (*p!=']')
		{
			eat_spaces(p);
			start = p;
			while(*p!=' ' && *p!='\t' && *p!=']' && *p!=';' && *p!=0)
				p++;
			if ( p==start || *p==0 )
				goto parse_error;
			/* lookup for the network -> get its index */
			for(net_nr=-1,i=0;i<nr_of_networks&&net_nr==-1;i++)
				if (!strncasecmp(networks[i].name,start,p-start)
				&& networks[i].name[p-start]==0)
					net_nr = i;
			if (net_nr==-1) {
				LM_ERR("associated net <%.*s> not found in net list\n",
					(int)(p-start), start);
				goto error;
			}
			LM_DBG("linking net \"%s\" to modem \"%s\" on pos %d.\n",
					networks[net_nr].name,modems[mdm_nr].name,k);
			modems[mdm_nr].net_list[k++]=net_nr;
			eat_spaces(p);
			if (*p==';') {
				p++;
				eat_spaces(p);
			}
		}
		if (*p!=']')
			goto parse_error;
		p++;
		/* end of element */
		eat_spaces(p);
		if (*p==';') {
			p++;
			eat_spaces(p);
		}
	}

	/* resolving default network name - if any*/
	if (default_net_str) {
		for(net_nr=-1,i=0;i<nr_of_networks&&net_nr==-1;i++)
			if (!strcasecmp(networks[i].name,default_net_str))
				net_nr = i;
		if (net_nr==-1) {
			LM_ERR("network \"%s\" not found in net list!\n",default_net_str);
			goto error;
		}
		default_net = net_nr;
	}

	return 0;
parse_error:
	LM_ERR("SMS %s config: parse error before  chr %d [%.*s]\n",
		(step==1)?"modems":(step==2?"networks":"links"),
		(int)(p - ((step==1)?modems_config:
				   (step==2?networks_config:links_config))),
		(*p==0)?4:1,(*p==0)?"NULL":p );
error:
	return -1;
}
Exemple #2
0
int run_reg_tm_cback(void *e_data, void *data, void *r_data)
{
	struct sip_msg *msg;
	int statuscode = 0;
	unsigned int exp = 0;
	reg_record_t *rec = (reg_record_t*)e_data;
	struct hdr_field *c_ptr, *head_contact;
	struct uac_credential crd;
	contact_t *contact;
	struct authenticate_body *auth = NULL;
	static struct authenticate_nc_cnonce auth_nc_cnonce;
	HASHHEX response;
	str *new_hdr;
	struct reg_tm_cback_data *tm_cback_data = (struct reg_tm_cback_data*)data;
	struct cell *t;
	struct tmcb_params *ps;
	time_t now;
	reg_tm_cb_t *cb_param;

	cb_param = tm_cback_data->cb_param;
	if (rec!=cb_param->uac) {
		/* no action on current list elemnt */
		return 0; /* continue list traversal */
	}

	t = tm_cback_data->t;
	ps = tm_cback_data->ps;
	now = tm_cback_data->now;

	reg_print_record(rec);

	if (ps->rpl==FAKED_REPLY)
		memset(&rec->td.forced_to_su, 0, sizeof(union sockaddr_union));
	else if (rec->td.forced_to_su.s.sa_family == AF_UNSPEC)
		rec->td.forced_to_su = t->uac[0].request.dst.to;

	statuscode = ps->code;
	switch(statuscode) {
	case 200:
		msg = ps->rpl;
		if(msg==FAKED_REPLY) {
			LM_ERR("FAKED_REPLY\n");
			goto done;
		}
		if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
			LM_ERR("failed to parse headers\n");
			goto done;
		}
		if (msg->contact) {
			c_ptr = msg->contact;
			while(c_ptr) {
				if (c_ptr->type == HDR_CONTACT_T) {
					if (!c_ptr->parsed && (parse_contact(c_ptr)<0)) {
						LM_ERR("failed to parse Contact body\n");
						goto done;
					}
				}
				c_ptr = c_ptr->next;
			}
		} else {
			LM_ERR("No contact header in received 200ok\n");
			goto done;
		}
		head_contact = msg->contact;
		contact = ((contact_body_t*)msg->contact->parsed)->contacts;
		while (contact) {
			/* Check for binding */
			if (contact->uri.len==rec->contact_uri.len &&
				strncmp(contact->uri.s,rec->contact_uri.s,contact->uri.len)==0){
				if (contact->expires && contact->expires->body.len) {
					if (str2int(&contact->expires->body, &exp)<0) {
						LM_ERR("Unable to extract expires from [%.*s]"
							" for binding [%.*s]\n",
							contact->expires->body.len,
							contact->expires->body.s,
							contact->uri.len, contact->uri.s);
					}
				}
				break;
			}
					
			/* get the next contact */
			if (contact->next == NULL) {
				contact = NULL;
				c_ptr = head_contact->next;
				while(c_ptr) {
					if (c_ptr->type == HDR_CONTACT_T) {
						head_contact = c_ptr;
						contact = ((contact_body_t*)c_ptr->parsed)->contacts;
						break;
					}
					c_ptr = c_ptr->next;
				}
			} else {
				contact = contact->next;
			}
		}
		rec->state = REGISTERED_STATE;
		if (exp) rec->expires = exp;
		rec->registration_timeout = now + rec->expires - timer_interval;
		break;

	case WWW_AUTH_CODE:
	case PROXY_AUTH_CODE:
		msg = ps->rpl;
		if(msg==FAKED_REPLY) {
			LM_ERR("FAKED_REPLY\n");
			goto done;
		}

		if (rec->auth_user.s==NULL || rec->auth_user.len==0 ||
			rec->auth_password.s==NULL || rec->auth_password.len==0) {
			LM_ERR("Credentials not provisioned\n");
			rec->state = WRONG_CREDENTIALS_STATE;
			rec->registration_timeout = 0;
			/* action successfuly completed on current list element */
			return 1; /* exit list traversal */
		}

		if (statuscode==WWW_AUTH_CODE) {
			if (0 == parse_www_authenticate_header(msg))
				auth = get_www_authenticate(msg);
		} else if (statuscode==PROXY_AUTH_CODE) {
			if (0 == parse_proxy_authenticate_header(msg))
				auth = get_proxy_authenticate(msg);
		}
		if (auth == NULL) {
			LM_ERR("Unable to extract authentication info\n");
			goto done;
		}
		LM_DBG("flags=[%d] realm=[%.*s] domain=[%.*s] nonce=[%.*s]"
			" opaque=[%.*s] qop=[%.*s]\n",
			auth->flags,
			auth->realm.len, auth->realm.s,
			auth->domain.len, auth->domain.s,
			auth->nonce.len, auth->nonce.s,
			auth->opaque.len, auth->opaque.s,
			auth->qop.len, auth->qop.s);

		switch(rec->state) {
		case REGISTERING_STATE:
			break;
		case AUTHENTICATING_STATE:
			/* We already sent an authenticated REGISTER and we are still challanged! */
			LM_WARN("Wrong credentials for [%.*s]\n",
				rec->td.rem_uri.len, rec->td.rem_uri.s);
			rec->state = WRONG_CREDENTIALS_STATE;
			rec->registration_timeout = 0;
			/* action successfuly completed on current list element */
			return 1; /* exit list traversal */
		default:
			LM_ERR("Unexpected [%d] notification cb in state [%d]\n",
				statuscode, rec->state);
			goto done;
		}

		/* perform authentication */
		if (auth->realm.s && auth->realm.len) {
			crd.realm.s = auth->realm.s; crd.realm.len = auth->realm.len;
		} else {
			LM_ERR("No realm found\n");
			goto done;
		}
		crd.user.s = rec->auth_user.s; crd.user.len = rec->auth_user.len;
		crd.passwd.s = rec->auth_password.s; crd.passwd.len = rec->auth_password.len;

		memset(&auth_nc_cnonce, 0, sizeof(struct authenticate_nc_cnonce));
		uac_auth_api._do_uac_auth(&register_method, &rec->td.rem_target, &crd,
					auth, &auth_nc_cnonce, response);
		new_hdr = uac_auth_api._build_authorization_hdr(statuscode, &rec->td.rem_target,
					&crd, auth, &auth_nc_cnonce, response);
		if (!new_hdr) {
			LM_ERR("failed to build authorization hdr\n");
			goto done;
		}
		if(send_register(cb_param->hash_index, rec, new_hdr)==1) {
			rec->state = AUTHENTICATING_STATE;
		} else {
			rec->state = INTERNAL_ERROR_STATE;
		}
		pkg_free(new_hdr->s);
		new_hdr->s = NULL; new_hdr->len = 0;
		break;

	case 423: /* Interval Too Brief */
		msg = ps->rpl;
		if(msg==FAKED_REPLY) {
			LM_ERR("FAKED_REPLY\n");
			goto done;
		}
		if (0 == parse_min_expires(msg)) {
			rec->expires = (unsigned int)(long)msg->min_expires->parsed;
			if(send_register(cb_param->hash_index, rec, NULL)==1)
				rec->state = REGISTERING_STATE;
			else
				rec->state = INTERNAL_ERROR_STATE;
		} else {
			rec->state = REGISTRAR_ERROR_STATE;
			rec->registration_timeout = now + rec->expires - timer_interval;
		}
		break;

	case 408: /* Interval Too Brief */
		rec->state = REGISTER_TIMEOUT_STATE;
		rec->registration_timeout = now + rec->expires - timer_interval;
		break;

	default:
		if(statuscode<400 && statuscode>=300) {
			LM_ERR("Redirection not implemented yet\n");
			rec->state = INTERNAL_ERROR_STATE;
		} else {
			/* we got an error from the server */
			rec->state = REGISTRAR_ERROR_STATE;
			rec->registration_timeout = now + rec->expires - timer_interval;
			
		}
	}

	/* action successfuly completed on current list element */
	return 1; /* exit list traversal */
done:
	rec->state = INTERNAL_ERROR_STATE;
	rec->registration_timeout = now + rec->expires;
	return -1; /* exit list traversal */
}
/*
 * Send an SQL query to the server
 */
static int db_oracle_submit_query(const db_con_t* _h, const str* _s)
{
	OCIBind* bind[MAX_BIND_HANDLES];
	OCIDate odt[sizeof(bind)/sizeof(bind[0])];
	str tmps;
	sword status;
	int pass;
	ora_con_t* con = CON_ORA(_h);
	query_data_t* pqd = con->pqdata;
	size_t hc = pqd->_n + pqd->_nw;
	OCIStmt *stmthp;

	if (hc >= sizeof(bind)/sizeof(bind[0])) {
		LM_ERR("too many bound. Rebuild with MAX_BIND_HANDLES >= %u\n",
			(unsigned)hc);
		return -1;
	}
	
	if (!pqd->_rs) {
		/*
		 * This method is at ~25% faster as set OCI_COMMIT_ON_SUCCESS
		 * in StmtExecute
		 */
		tmps.len = snprintf(st_buf, sizeof(st_buf),
			"begin %.*s; commit write batch nowait; end;",
			_s->len, _s->s);
		if ((unsigned)tmps.len >= sizeof(st_buf))
			return sql_buf_small();
		tmps.s = st_buf;
		_s = &tmps;
	}

	pass = 1;
	if (!con->connected) {
		status = db_oracle_reconnect(con);
		if (status != OCI_SUCCESS) {
			LM_ERR("can't restore connection: %s\n", db_oracle_error(con, status));
			return -2;
		}
		LM_INFO("connection restored\n");
		--pass;
	}
repeat:
	stmthp = NULL;
	status = OCIHandleAlloc(con->envhp, (dvoid**)(dvoid*)&stmthp,
		    OCI_HTYPE_STMT, 0, NULL);
	if (status != OCI_SUCCESS)
		goto ora_err;
	status = OCIStmtPrepare(stmthp, con->errhp, (text*)_s->s, _s->len,
		OCI_NTV_SYNTAX, OCI_DEFAULT);
	if (status != OCI_SUCCESS)
		goto ora_err;

	if (hc) {
		bmap_t bmap;
		size_t pos = 1;
		int i;

		memset(bind, 0, hc*sizeof(bind[0]));
		for (i = 0; i < pqd->_n; i++) {
			if (db_oracle_val2bind(&bmap, &pqd->_v[i], &odt[pos]) < 0)
				goto bind_err;
			status = OCIBindByPos(stmthp, &bind[pos], con->errhp,
				pos, bmap.addr, bmap.size, bmap.type,
				NULL, NULL, NULL, 0, NULL, OCI_DEFAULT);
			if (status != OCI_SUCCESS)
				goto ora_err;
			++pos;
		}
		for (i = 0; i < pqd->_nw; i++) {
			if (db_oracle_val2bind(&bmap, &pqd->_w[i], &odt[pos]) < 0) {
bind_err:
				OCIHandleFree(stmthp, OCI_HTYPE_STMT);
				LM_ERR("can't map values\n");
				return -3;
			}
			status = OCIBindByPos(stmthp, &bind[pos], con->errhp,
				pos, bmap.addr, bmap.size, bmap.type,
				NULL, NULL, NULL, 0, NULL, OCI_DEFAULT);
			if (status != OCI_SUCCESS)
				goto ora_err;
			++pos;
		}
	}

	// timelimited operation
	status = begin_timelimit(con, 0);
	if (status != OCI_SUCCESS) goto ora_err;
	do status = OCIStmtExecute(con->svchp, stmthp, con->errhp,
		!pqd->_rs, 0, NULL, NULL,
		pqd->_rs ? OCI_STMT_SCROLLABLE_READONLY : OCI_DEFAULT);
	while (wait_timelimit(con, status));
	if (done_timelimit(con, status)) goto stop_exec;
	switch (status)	{
	case OCI_SUCCESS_WITH_INFO:
		LM_WARN("driver: %s\n", db_oracle_errorinfo(con));
		//PASS THRU
	case OCI_SUCCESS:
		if (pqd->_rs)
			*pqd->_rs = stmthp;
		else
			OCIHandleFree(stmthp, OCI_HTYPE_STMT);
		return 0;
	default:
	    pass = -pass;
	    break;
	}

ora_err:
	LM_ERR("driver: %s\n", db_oracle_error(con, status));
stop_exec:
	if (stmthp)
		OCIHandleFree(stmthp, OCI_HTYPE_STMT);
	if (pass == -1 && !con->connected) {
		/* Attemtp to reconnect */
		if (db_oracle_reconnect(con) == OCI_SUCCESS) {
			LM_NOTICE("attempt repeat after reconnect\n");
			pass = 0;
			goto repeat;
		}
		LM_ERR("connection loss\n");
	}
	return -4;
}
Exemple #4
0
/*!
 * \brief Create a new dialog from a sip message
 *
 * Create a new dialog from a SIP message, register a callback
 * to keep track of the dialog with help of the tm module.
 * This function is either called from the request callback, or
 * from the dlg_manage function in the configuration script.
 * \see dlg_onreq
 * \see w_dlg_manage
 * \param msg SIP message
 * \param t transaction
 * \return 0 on success, -1 on failure
 */
int dlg_new_dialog(struct sip_msg *req, struct cell *t, const int run_initial_cbs) {
    struct dlg_cell *dlg;
    str s;
    str callid;
    str ftag;
    str ttag;
    str req_uri;
    unsigned int dir;

    LM_DBG("starting dlg_new_dialog and method is [%.*s]\n", req->first_line.u.request.method.len, req->first_line.u.request.method.s);

    if (current_dlg_pointer != NULL)
        return -1;

    if (req->first_line.u.request.method_value == METHOD_CANCEL)
        return -1;

    if (pre_match_parse(req, &callid, &ftag, &ttag, 0) < 0) {
        LM_WARN("pre-matching failed\n");
        return -1;
    }

    if (ttag.s != 0 && ttag.len != 0)
        return -1;

    if (pv_printf_s(req, ruri_param_model, &req_uri) < 0) {
        LM_ERR("error - cannot print the r-uri format\n");
        return -1;
    }
    trim(&req_uri);

    if (detect_spirals) {
        if (spiral_detected == 1)
            return 0;

        dir = DLG_DIR_NONE;

        dlg = get_dlg(&callid, &ftag, &ttag, &dir);
        if (dlg) {
            LM_DBG("Callid '%.*s' found, must be a spiraled request\n",
                    callid.len, callid.s);
            spiral_detected = 1;

            if (run_initial_cbs)
                run_dlg_callbacks(DLGCB_SPIRALED, dlg, req, NULL, DLG_DIR_DOWNSTREAM, 0);

            //Add did to rr header for all spiralled requested INVITEs
            if (req->first_line.u.request.method_value == METHOD_INVITE) {
                if (add_dlg_rr_param(dlg, req, dlg->h_entry, dlg->h_id) < 0) {
                    LM_ERR("failed to add RR param\n");

                }
            }

            // get_dlg has incremented the ref count by 1
            unref_dlg(dlg, 1);
            goto finish;
        }
    }
    spiral_detected = 0;


    LM_DBG("Building new Dialog for call-id %.*s\n", callid.len, callid.s);
    LM_DBG("SIP Method: %.*s  \n", req->first_line.u.request.method.len, req->first_line.u.request.method.s);
    dlg = build_new_dlg(&callid /*callid*/,
            &(get_from(req)->uri) /*from uri*/,
            &ftag/*from_tag*/,
            &req_uri /*r-uri*/);

    if (dlg == 0) {
        LM_ERR("failed to create new dialog\n");
        return -1;
    }

    /* save caller's tag, cseq, contact and record route*/
    if (populate_leg_info(dlg, req, t, DLG_CALLER_LEG,
            &(get_from(req)->tag_value)) != 0) {
        LM_ERR("could not add further info to the dialog\n");
        lock_destroy(dlg->dlg_out_entries_lock);
        lock_dealloc(dlg->dlg_out_entries_lock);
        shm_free(dlg);
        return -1;
    }

    dlg->transaction = t;

    /* Populate initial varlist: */
    dlg->vars = get_local_varlist_pointer(req, 1);

    link_dlg(dlg, 0);
    if (run_initial_cbs) run_create_callbacks(dlg, req);

    //Dialog will *always* use DID cookie so no need for match mode anymore
    if (add_dlg_rr_param(dlg, req, dlg->h_entry, dlg->h_id) < 0) {
        LM_ERR("failed to add RR param\n");
        goto error;
    }

    if (d_tmb.register_tmcb(req, t,
            TMCB_RESPONSE_READY | TMCB_RESPONSE_FWDED | TMCB_RESPONSE_OUT,
            dlg_onreply, (void*) dlg, unref_new_dialog) < 0) {
        LM_ERR("failed to register TMCB\n");
        goto error;
    }
    // increase reference counter because of registered callback
    ref_dlg(dlg, 1);

    dlg->lifetime = get_dlg_timeout(req);
    s.s = _dlg_ctx.to_route_name;
    s.len = strlen(s.s);
    dlg_set_toroute(dlg, &s);
    dlg->sflags |= _dlg_ctx.flags;

    if (_dlg_ctx.to_bye != 0)
        dlg->dflags |= DLG_FLAG_TOBYE;

finish:
    if (t) {
        // transaction exists ==> keep ref counter large enough to
        // avoid premature cleanup and ensure proper dialog referencing
        if (store_dlg_in_tm(req, t, dlg) < 0) {
            LM_ERR("failed to store dialog in transaction\n");
            goto error;
        }
    } else {
        // no transaction exists ==> postpone work until we see the
        // request being forwarded statefully
        if (d_tmb.register_tmcb(req, NULL, TMCB_REQUEST_FWDED,
                store_dlg_in_tm_cb, (void*) dlg, NULL) < 0) {
            LM_ERR("failed to register callback for storing dialog in transaction\n");
            goto error;
        }
    }

    LM_DBG("Setting current dialog\n");
    set_current_dialog(req, dlg);
    _dlg_ctx.dlg = dlg;
    ref_dlg(dlg, 1);
    return 0;

error:
    LM_DBG("Error in build_new_dlg");
    if (!spiral_detected)
        unref_dlg(dlg, 1); // undo ref regarding linking
    return -1;
}
Exemple #5
0
/**
 * get PContact-Structure for message
 * (search only once per Request)
 */
pcontact_t * getContactP(struct sip_msg* _m, udomain_t* _d, enum pcontact_reg_states reg_state) {
	ppublic_t * p;
	contact_body_t *b = 0;
	contact_t *ct;
	pcontact_info_t search_ci;
	str received_host = {0, 0};
	char srcip[50];
	struct via_body *vb;
	unsigned short port, proto;
	str host;
	sip_uri_t contact_uri;
	int mustRetryViaSearch = 0;
	int mustRetryReceivedSearch = 0;

    b = cscf_parse_contacts(_m);

    if (_m->first_line.type == SIP_REPLY && _m->contact && _m->contact->parsed && b->contacts) {
		mustRetryViaSearch = 1;
		mustRetryReceivedSearch = 1;
        LM_DBG("This is a reply - to look for contact we favour the contact header above the via (b2bua)... if no contact we will use last via\n");
        ct = b->contacts;
        host = ct->uri;
        if (parse_uri(ct->uri.s, ct->uri.len, &contact_uri) != 0) {
            LM_WARN("Failed to parse contact [%.*s]\n", ct->uri.len, ct->uri.s);
            return NULL;
        }
        host = contact_uri.host;
        port = contact_uri.port_no ? contact_uri.port_no : 5060;
        proto = contact_uri.proto;
        if (proto == 0) {
            LM_DBG("Contact protocol not specified - using received\n");
            proto = _m->rcv.proto;
        }
    } else {
        if (_m->first_line.type == SIP_REPLY)
            LM_DBG("This is a reply but we are forced to use the via header\n");
        else
            LM_DBG("This is a request - using first via to find contact\n");

        vb = cscf_get_ue_via(_m);
        host = vb->host;
        port = vb->port ? vb->port : 5060;
        proto = vb->proto;
    }

    LM_DBG("searching for contact with host:port:proto contact [%d://%.*s:%d]\n", proto, host.len, host.s, port);

    received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof (srcip));
    received_host.s = srcip;

//    if (_m->id != current_msg_id) {
        current_msg_id = _m->id;
        c = NULL;
	//search_ci.reg_state = PCONTACT_REGISTERED;          //we can do this because this function is always called expecting a REGISTERED contact
        search_ci.reg_state = reg_state;
	search_ci.received_host.s = received_host.s;
	search_ci.received_host.len = received_host.len;
	search_ci.received_port = _m->rcv.src_port;
	search_ci.received_proto = _m->rcv.proto;
	search_ci.searchflag = SEARCH_RECEIVED;
	if (is_registered_fallback2ip == 1) {
		search_ci.searchflag = SEARCH_NORMAL;
	} 
	search_ci.via_host = host;
	search_ci.via_port = port;
	search_ci.via_prot = proto;
	search_ci.aor.s = 0;
	search_ci.aor.len = 0;

//	b = cscf_parse_contacts(_m);
tryagain:
	if (b && b->contacts) {
		for (ct = b->contacts; ct; ct = ct->next) {
			search_ci.aor = ct->uri;
			if (ul.get_pcontact(_d, &search_ci, &c) == 0) {
				if (checkcontact(_m, c) != 0) {
					c = NULL;
				} else {
					break;
				}
			}
		}
	} else {
		LM_WARN("No contact-header found...\n");
	}

	if ((c == NULL) && (is_registered_fallback2ip == 1)) {
		LM_INFO("Contact not found based on Contact-header, trying IP/Port/Proto\n");
		//			received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip));
		//			received_host.s = srcip;
		search_ci.searchflag = SEARCH_RECEIVED;
		if (ul.get_pcontact(_d, &search_ci, &c) == 1) {
			LM_DBG("No entry in usrloc for %.*s:%i (Proto %i) found!\n", received_host.len, received_host.s, _m->rcv.src_port, _m->rcv.proto);
		} else {
			if (checkcontact(_m, c) != 0) {
				c = NULL;
			}
		}
	}

	if ((c == NULL) && (is_registered_fallback2ip == 2)) {
		LM_INFO("Contact not found based on IP/Port/Proto, trying Contact-header\n");
		search_ci.searchflag = SEARCH_NORMAL;
		if (ul.get_pcontact(_d, &search_ci, &c) == 1) {
		} else {
			if (checkcontact(_m, c) != 0) {
				c = NULL;
			}
		}
	}

	asserted_identity = NULL;
	registration_contact = NULL;
	if (c) {
                LM_DBG("Trying to set asserted identity field");
		registration_contact = &c->contact_user;
		p = c->head;
		while (p) {
                        LM_DBG("Checking through contact users");
			if (p->is_default == 1) {
                            LM_DBG("Found default contact user so setting asserted identity");
                            asserted_identity = &p->public_identity;
                        }
			p = p->next;
		}
	}
        if (asserted_identity != NULL && asserted_identity->len > 0) {
            LM_DBG("Have set the asserted_identity param to [%.*s]\n", asserted_identity->len, asserted_identity->s);
        } else {
            LM_DBG("Asserted identity not set");
        }
            
    
//    LM_DBG("pcontact flag is [%d]\n", c->flags);
//    if (c && (c->flags & (1<<FLAG_READFROMDB)) != 0) {
//        LM_DBG("we have a contact that was read fresh from the DB....\n");
//    }
	if (!c && mustRetryViaSearch) {
		LM_DBG("This is a reply so we will search using the last via once more...\n");
		vb = cscf_get_ue_via(_m);
		search_ci.via_host = vb->host;
		search_ci.via_port = vb->port ? vb->port : 5060;
		search_ci.via_prot = vb->proto;
		mustRetryViaSearch = 0;
		goto tryagain;
	}
	
	if (!c && mustRetryReceivedSearch) {
		LM_DBG("This is a reply and we still don't have a match - will try src ip/port of message\n");
		search_ci.via_host = received_host;
		search_ci.via_port = _m->rcv.src_port;
		search_ci.via_prot = _m->rcv.proto;
		mustRetryReceivedSearch = 0;
		goto tryagain;
	}

    return c;
}
Exemple #6
0
static int is_peer_verified(struct sip_msg* msg, char* foo, char* foo2)
{
	struct tcp_connection *c;
	SSL *ssl;
	long ssl_verify;
	X509 *x509_cert;

	LM_DBG("started...\n");
	if (msg->rcv.proto != PROTO_TLS) {
		LM_ERR("proto != TLS --> peer can't be verified, return -1\n");
		return -1;
	}

	LM_DBG("trying to find TCP connection of received message...\n");
	/* what if we have multiple connections to the same remote socket? e.g. we can have
	   connection 1: localIP1:localPort1 <--> remoteIP:remotePort
	   connection 2: localIP2:localPort2 <--> remoteIP:remotePort
	   but I think the is very unrealistic */
	tcp_conn_get(0, &(msg->rcv.src_ip), msg->rcv.src_port, PROTO_TLS, &c, NULL/*fd*/);
	if (c==NULL) {
		LM_ERR("no corresponding TLS/TCP connection found."
				" This should not happen... return -1\n");
		return -1;
	}
	LM_DBG("corresponding TLS/TCP connection found. s=%d, fd=%d, id=%d\n",
			c->s, c->fd, c->id);

	if (!c->extra_data) {
		LM_ERR("no extra_data specified in TLS/TCP connection found."
				" This should not happen... return -1\n");
		goto error;
	}

	ssl = (SSL *) c->extra_data;

	ssl_verify = SSL_get_verify_result(ssl);
	if ( ssl_verify != X509_V_OK ) {
		LM_WARN("verification of presented certificate failed... return -1\n");
		goto error;
	}

	/* now, we have only valid peer certificates or peers without certificates.
	 * Thus we have to check for the existence of a peer certificate
	 */
	x509_cert = SSL_get_peer_certificate(ssl);
	if ( x509_cert == NULL ) {
		LM_WARN("tlsops:is_peer_verified: WARNING: peer did not presented "
				"a certificate. Thus it could not be verified... return -1\n");
		goto error;
	}

	X509_free(x509_cert);

	tcp_conn_release(c, 0);

	LM_DBG("tlsops:is_peer_verified: peer is successfully verified"
			"...done\n");
	return 1;
error:
	tcp_conn_release(c, 0);
	return -1;
}
Exemple #7
0
static int load_crl(SSL_CTX * ctx, char *crl_directory, int crl_check_all)
{
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
	DIR *d;
	struct dirent *dir;
	int crl_added = 0;
	LM_DBG("Loading CRL from directory\n");

	/*Get X509 store from SSL context*/
	X509_STORE *store = SSL_CTX_get_cert_store(ctx);
	if(!store) {
		LM_ERR("Unable to get X509 store from ssl context\n");
		return -1;
	}

	/*Parse directory*/
	d = opendir(crl_directory);
	if(!d) {
		LM_ERR("Unable to open crl directory '%s'\n", crl_directory);
		return -1;
	}

	while ((dir = readdir(d)) != NULL) {
		/*Skip if not regular file*/
		if (dir->d_type != DT_REG)
			continue;

		/*Create filename*/
		char* filename = (char*) pkg_malloc(sizeof(char)*(strlen(crl_directory)+strlen(dir->d_name)+2));
		if (!filename) {
			LM_ERR("Unable to allocate crl filename\n");
			closedir(d);
			return -1;
		}
		strcpy(filename,crl_directory);
		if(filename[strlen(filename)-1] != '/')
			strcat(filename,"/");
		strcat(filename,dir->d_name);

		/*Get CRL content*/
		FILE *fp = fopen(filename,"r");
		pkg_free(filename);
		if(!fp)
			continue;

		X509_CRL *crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL);
		fclose(fp);
		if(!crl)
			continue;

		/*Add CRL to X509 store*/
		if (X509_STORE_add_crl(store, crl) == 1)
			crl_added++;
		else
			LM_ERR("Unable to add crl to ssl context\n");

		X509_CRL_free(crl);
	}
	closedir(d);

	if (!crl_added) {
		LM_ERR("No suitable CRL files found in directory %s\n", crl_directory);
		return -1;
	}

	/*Enable CRL checking*/
	X509_VERIFY_PARAM *param;
	param = X509_VERIFY_PARAM_new();

	int flags =  X509_V_FLAG_CRL_CHECK;
	if(crl_check_all)
		flags |= X509_V_FLAG_CRL_CHECK_ALL;

	X509_VERIFY_PARAM_set_flags(param, flags);

	SSL_CTX_set1_param(ctx, param);
	X509_VERIFY_PARAM_free(param);

	return 0;
#else
	static int already_warned = 0;
	if (!already_warned) {
		LM_WARN("CRL not supported in %s\n", OPENSSL_VERSION_TEXT);
		already_warned = 1;
	}
	return 0;
#endif
}
Exemple #8
0
/*! \brief
 * Check if the originating REGISTER message was formed correctly
 * The whole message must be parsed before calling the function
 * _s indicates whether the contact was star
 */
int check_contacts(struct sip_msg* _m, int* _s)
{
	struct hdr_field* p;
	contact_t*  c;

	*_s = 0;
	/* Message without contacts is OK */
	if (_m->contact == 0) return 0;

	if (((contact_body_t*)_m->contact->parsed)->star == 1) {
		/* The first Contact HF is star */
		/* Expires must be zero */
		if (get_expires_hf(_m) != 0) {
			LM_WARN("expires must be 0 for star contact\n");
			rerrno = R_STAR_EXP;
			return 1;
		}

		/* Message must contain no contacts */
		if (((contact_body_t*)_m->contact->parsed)->contacts) {
			LM_WARN("star contact cannot be mixed with other contacts\n");
			rerrno = R_STAR_CONT;
			return 1;
		}

		/* Message must contain no other Contact HFs */
		p = _m->contact->next;
		while(p) {
			if (p->type == HDR_CONTACT_T) {
				LM_WARN("star contact cannot be mixed with other contacts\n");
				rerrno = R_STAR_CONT;
				return 1;
			}
			p = p->next;
		}

		*_s = 1;
	} else { /* The first Contact HF is not star */
		p = _m->contact;
		while(p) {
			if (p->type == HDR_CONTACT_T) {
				/* Message must contain no star Contact HF */
				if (((contact_body_t*)p->parsed)->star == 1) {
					LM_WARN("star contact cannot be mixed with other contacts\n");
					rerrno = R_STAR_CONT;
					return 1;
				}
				/* check also the length of all contacts */
				for(c=((contact_body_t*)p->parsed)->contacts ; c ; c=c->next) {
					if (c->uri.len > contact_max_size) {
						LM_WARN("contact uri is too long: [%.*s]\n", c->uri.len, c->uri.s);
						rerrno = R_CONTACT_LEN;
						return 1;
					}
					if (c->received && c->received->len>RECEIVED_MAX_SIZE) {
						LM_WARN("received attribute of contact is too long\n");
						rerrno = R_CONTACT_LEN;
						return 1;
					}
				}
			}
			p = p->next;
		}
	}

	return 0;
}
Exemple #9
0
static int append_fixed_vars(struct sip_msg *msg, struct hf_wrapper **list)
{
	static char tid[MD5_LEN];
	str *uri;
	struct sip_uri parsed_uri, oparsed_uri;
	char *val;
	int val_len;

	/* source ip */
	if (!append_var(EV_SRCIP, ip_addr2a(&msg->rcv.src_ip), 0, list)) {
		LM_ERR("append_var SRCIP failed \n");
		return 0;
	}
	/* request URI */
	uri=msg->new_uri.s && msg->new_uri.len ? 
		&msg->new_uri : &msg->first_line.u.request.uri;
	if (!append_var(EV_RURI, uri->s, uri->len, list )) {
		LM_ERR("append_var URI failed\n");
		return 0;
	}
	/* userpart of request URI */
	if (parse_uri(uri->s, uri->len, &parsed_uri)<0) {
		LM_WARN("uri not parsed\n");
	} else {
		if (!append_var(EV_USER, parsed_uri.user.s, 
					parsed_uri.user.len, list)) {
			LM_ERR("append_var USER failed\n");
			goto error;
		}
	}
	/* original URI */
	if (!append_var(EV_ORURI, msg->first_line.u.request.uri.s,
				msg->first_line.u.request.uri.len, list)) {
		LM_ERR("append_var O-URI failed\n");
		goto error;
	}
	/* userpart of request URI */
	if (parse_uri(msg->first_line.u.request.uri.s, 
				msg->first_line.u.request.uri.len, 
				&oparsed_uri)<0) {
		LM_WARN("orig URI not parsed\n");
	} else {
		if (!append_var(EV_OUSER, oparsed_uri.user.s, 
					oparsed_uri.user.len, list)) {
			LM_ERR("ppend_var OUSER failed\n");
			goto error;
		}
	}
	/* tid, transaction id == via/branch */
	if (!char_msg_val(msg, tid)) {
		LM_WARN("no tid can be determined\n");
		val=0; val_len=0;
	} else {
		val=tid;val_len=MD5_LEN;
	}
	if (!append_var(EV_TID, val,val_len, list)) {
		LM_ERR("append_var TID failed\n");
		goto error;
	}

	/* did, dialogue id == To-tag */
	if (!(msg->to && get_to(msg) ))  {
		LM_ERR("no to-tag\n");
		val=0; val_len=0;
	} else {
		val=get_to(msg)->tag_value.s;
		val_len=get_to(msg)->tag_value.len;
	}
	if (!append_var(EV_DID, val, val_len, list)) {
		LM_ERR("append_var DID failed\n");
		goto error;
	}
	return 1;
error:
	return 0;
}
Exemple #10
0
int build_publish_call_info_header(b2b_sca_record_t *rec, str *publish_hdr)
{
	unsigned int i;
	unsigned int size = sizeof(CALL_INFO_HDR);
	b2b_sca_call_t *call = NULL;
	char *p;

	rec->expires = 30;
	size += callinfo_default_uri.len +
		callinfo_appindex.len + callinfo_hdr_postfix.len;

	if (rec == NULL) {
		/* we need to build an idle Call-Info header */
		publish_hdr->s = publish_call_info_hdr_buf;
		p = &publish_call_info_hdr_buf[sizeof(CALL_INFO_HDR) - 1];
		goto default_hdr;
	}

	for (i=0; i<MAX_APPEARANCE_INDEX; i++) {
		if (rec->call[i]) {
			call = rec->call[i];
			if (call->call_state > ALERTING_STATE)
				rec->expires = 36000;
			size += call->call_info_uri.len +
				callinfo_appuri_prefix.len +
				call->call_info_apperance_uri.len +
				callinfo_appindex.len +
				call->appearance_index_str.len +
				callinfo_appstate.len +
				app_state[call->call_state].len + 2;
		}
	}

	if (size > PUBLISH_CALL_INFO_HDR_LEN) {
		LM_WARN("buffer overflow for PUBLISH Call-Info"
			" header: size [%d]\n", size);
		p = (char *)pkg_malloc(size);
		if (p == NULL) {
			LM_ERR("OOM\n");
			return -1;
		}
		publish_hdr->s = p;
		memcpy(p, publish_call_info_hdr_buf, sizeof(CALL_INFO_HDR) - 1);
		p += sizeof(CALL_INFO_HDR) - 1;
	} else {
		publish_hdr->s = publish_call_info_hdr_buf;
		p = &publish_call_info_hdr_buf[sizeof(CALL_INFO_HDR) - 1];
	}

	for (i=0; i<MAX_APPEARANCE_INDEX; i++) {
		if (rec->call[i]) {
			call = rec->call[i];

			memcpy(p, call->call_info_uri.s, call->call_info_uri.len);
			p += call->call_info_uri.len;

			memcpy(p, callinfo_appuri_prefix.s,
				callinfo_appuri_prefix.len);
			p += callinfo_appuri_prefix.len;

			memcpy(p, call->call_info_apperance_uri.s,
					call->call_info_apperance_uri.len);
			p += call->call_info_apperance_uri.len;
			*p = '\"'; p++;

			memcpy(p, callinfo_appindex.s, callinfo_appindex.len);
			p += callinfo_appindex.len;

			memcpy(p, call->appearance_index_str.s,
				call->appearance_index_str.len);
			p += call->appearance_index_str.len;

			memcpy(p, callinfo_appstate.s, callinfo_appstate.len);
			p += callinfo_appstate.len;

			memcpy(p, app_state[call->call_state].s, app_state[call->call_state].len);
			p += app_state[call->call_state].len;

			*p = ','; p++;
			*p = '<'; p++;
		}
	}

default_hdr:
	memcpy(p, callinfo_default_uri.s, callinfo_default_uri.len);
	p += callinfo_default_uri.len;

	memcpy(p, callinfo_appindex.s, callinfo_appindex.len);
	p += callinfo_appindex.len;

	memcpy(p, callinfo_hdr_postfix.s, callinfo_hdr_postfix.len);
	p += callinfo_hdr_postfix.len;

	publish_hdr->len = p - publish_hdr->s;

	LM_DBG("publish_hdr [%d:%d] [%.*s]\n", size, publish_hdr->len,
						publish_hdr->len, publish_hdr->s);
	return 0;
}
Exemple #11
0
void vqm_free(struct vqm_block* qm, void* p)
#endif
{
	struct vqm_frag *f, *next, *prev, *first_big;
	unsigned char b;

#ifdef DBG_QM_MALLOC
	LM_GEN1(memlog,"params (%p, %p), called from %s: %s(%d)\n", 
		qm, p, file, func, line);
	if (p>(void *)qm->core_end || p<(void*)qm->init_core){
		LM_CRIT("bad pointer %p (out of memory block!) - aborting\n", p);
		abort();
	}
#endif
	if (p==0) {
		LM_WARN("free(0) called\n");
		return;
	}
	f=(struct  vqm_frag*) ((char*)p-sizeof(struct vqm_frag));
	b=f->u.inuse.bucket;
#ifdef DBG_QM_MALLOC
	VQM_DEBUG_FRAG(qm, f);
	if ( ! FRAG_ISUSED(f) ) {
		LM_CRIT("freeing already freed pointer, first freed: %s: %s(%d) "
				"- aborting\n",	f->file, f->func, f->line);
		abort();
	}
	if ( b>MAX_BUCKET ) {
		LM_CRIT("fragment with too high bucket nr: "
				"%d, allocated: %s: %s(%d) - aborting\n",
				b, f->file, f->func, f->line); 
		abort();
	}
	LM_GEN1(memlog,"freeing %d bucket block alloc'ed from %s: %s(%d)\n", 
		f->u.inuse.bucket, f->file, f->func, f->line);
	f->file=file; f->func=func; f->line=line;
	qm->usage[ f->u.inuse.bucket ]--;
#endif
	if (IS_BIGBUCKET(qm,b)) {
		next=FRAG_NEXT(f);
		if  ((char *)next +sizeof( struct vqm_frag) < qm->core_end) {
			VQM_DEBUG_FRAG(qm, next);
			if (! FRAG_ISUSED(next)) { /* coalesce with next fragment */
				LM_DBG("coalesced with next\n");
				vqm_detach_free(qm, next);
				f->size+=next->size;
				FRAG_END(f)->size=f->size;
			}
		}
		first_big = qm->next_free[b];
		if (first_big &&  f>first_big) {
			prev=FRAG_PREV(f);
			VQM_DEBUG_FRAG(qm, prev);
			if (!FRAG_ISUSED(prev)) { /* coalesce with prev fragment */
				LM_DBG("coalesced with prev\n");
				vqm_detach_free(qm, prev );
				prev->size+=f->size;
				f=prev;
				FRAG_END(f)->size=f->size;
			}
		}
		if ((char *)f==qm->big_chunks) { /* release unused core */
			LM_DBG("big chunk released\n");
			qm->free_core+=f->size;
			qm->big_chunks+=f->size;
			return;
		}		
		first_big = qm->next_free[b];
		/* fix reverse link (used only for BIG_BUCKET */
		if (first_big) FRAG_END(first_big)->prv_free=f;
		FRAG_END(f)->prv_free=0;
	} else first_big = qm->next_free[b];
	f->u.nxt_free = first_big; /* also clobbers magic */
	qm->next_free[b] = f;
}
Exemple #12
0
void modem_process(struct modem *mdm)
{
	struct sms_msg    *sms_messg;
	struct incame_sms sms;
	struct network *net;
	int i,k,len;
	int counter;
	int dont_wait;
	int empty_pipe;
	int cpms_unsuported;
	int max_mem=0, used_mem=0;

	sms_messg = 0;
	cpms_unsuported = 0;

	/* let's open/init the modem */
	LM_DBG("opening modem\n");
	if (openmodem(mdm)==-1) {
		LM_ERR("failed to open modem %s! %s \n",
			mdm->name,strerror(errno));
		return;
	}

	setmodemparams(mdm);
	initmodem(mdm,check_cds_report);

	if ( (max_mem=check_memory(mdm,MAX_MEM))==-1 ) {
		LM_WARN("CPMS command unsuported! using default values (10,10)\n");
		used_mem = max_mem = 10;
		cpms_unsuported = 1;
	}
	LM_DBG("modem maximum memory is %d\n",max_mem);

	set_gettime_function();

	while(1)
	{
		/* update the local config */
		cfg_update();

		dont_wait = 0;
		for (i=0;i<nr_of_networks && mdm->net_list[i]!=-1;i++)
		{
			counter = 0;
			empty_pipe = 0;
			net = &(networks[mdm->net_list[i]]);
			/*getting msgs from pipe*/
			while( counter<net->max_sms_per_call && !empty_pipe )
			{
				/* let's read a sms from pipe */
				len = read(net->pipe_out, &sms_messg,
					sizeof(sms_messg));
				if (len!=sizeof(sms_messg)) {
					if (len>=0)
						LM_ERR("truncated message read from pipe!"
								" -> discarded\n");
					else if (errno==EAGAIN)
						empty_pipe = 1;
					else
						LM_ERR("pipe reading failed: %s\n",strerror(errno));
					sleep(1);
					counter++;
					continue;
				}
				(*queued_msgs)--;

				/* compute and send the sms */
				LM_DBG("%s processing sms for net %s:"
					" \n\tTo:[%.*s]\n\tBody=<%d>[%.*s]\n",
					mdm->device, net->name,
					sms_messg->to.len,sms_messg->to.s,
					sms_messg->text.len,sms_messg->text.len,sms_messg->text.s);
				send_as_sms( sms_messg , mdm);

				counter++;
				/* if I reached the limit -> set not to wait */
				if (counter==net->max_sms_per_call)
					dont_wait = 1;
			}/*while*/
		}/*for*/

		/* let's see if we have incoming sms */
		if ( !cpms_unsuported )
			if ((used_mem = check_memory(mdm,USED_MEM))==-1) {
				LM_ERR("CPMS command failed! cannot get used mem -> using 10\n");
				used_mem = 10;
			}

		/* if any, let's get them */
		if (used_mem)
			LM_DBG("%d new SMS on modem\n",used_mem);
			for(i=1,k=1;k<=used_mem && i<=max_mem;i++) {
				if (getsms(&sms,mdm,i)!=-1) {
					k++;
					LM_DBG("SMS Get from location %d\n",i);
					/*for test ;-) ->  to be remove*/
					LM_DBG("SMS RECEIVED:\n\rFrom: %s %s\n\r%.*s %.*s"
						"\n\r\"%.*s\"\n\r",sms.sender,sms.name,
						DATE_LEN,sms.date,TIME_LEN,sms.time,
						sms.userdatalength,sms.ascii);
					if (!sms.is_statusreport)
						_send_sms_as_sip(&sms, mdm);
					else 
						check_sms_report(&sms);
				}
			}

		/* if reports are used, checks for expired records in report queue */
		if (sms_report_type!=NO_REPORT)
			check_timeout_in_report_queue();

		/* sleep -> if it's needed */
		if (!dont_wait) {
				sleep(mdm->looping_interval);
		}
	}/*while*/
}
Exemple #13
0
int send_sms_as_sip( struct incame_sms *sms )
{
	str  sip_addr;
	str  sip_body;
	str  sip_from;
	int  is_pattern;
	int  k;
	char *p;

	/* first we have to parse the body to try to get out
	   the sip destination address;
	   The sms body can to be in the following two formats:
	   1. The entire or part of the sent header still exists - we will
	      pars it and consider the start of the sip message the first
	      character that doesn't match the header!
	   2. The sms body is totally different of the send sms -> search for a
	      sip address inside; everything before it is ignored, only the
	      part following the address being send as sip
	*/
	sip_addr.len = 0;
	sip_body.len = 0;
	p = sms->ascii;

	/* is our logo (or a part of it) still there? */
	if (*p==SMS_HDR_BF_ADDR[0]) {
		is_pattern = 1;
		/* try to match SMS_HDR_BF_ADDR */
		k=0;
		while( is_pattern && p<sms->ascii+sms->userdatalength
		&& k<SMS_HDR_BF_ADDR_LEN)
			if (*(p++)!=SMS_HDR_BF_ADDR[k++])
				is_pattern = 0;
		if (!is_pattern) {
			/* first header part is broken -> let's give it a chance
			   and parse for the first word delimiter */
			while(p<sms->ascii+sms->userdatalength && no_sip_addr_begin(*p))
				p++;
			p++;
			if (p+9>=sms->ascii+sms->userdatalength) {
				LM_ERR("unable to find sip_address start in sms body [%s]!\n",
						sms->ascii);
				goto error;
			}
			
		}
		/* lets get the address */
		if (p[0]!='s' || p[1]!='i' || p[2]!='p' || p[3]!=':') {
			LM_ERR("wrong sip address format in sms body [%s]!\n",sms->ascii);
			goto error;
		}
		sip_addr.s = p;
		/* goes to the end of the address */
		while(p<sms->ascii+sms->userdatalength && is_in_sip_addr(*p) )
			p++;
		if (p>=sms->ascii+sms->userdatalength) {
			LM_ERR("failed to find sip address end in sms body [%s]!\n",
					sms->ascii);
		}
		sip_addr.len = p-sip_addr.s;
		LM_DBG("sip address found [%.*s]\n",
			sip_addr.len,sip_addr.s);
		/* try to match SMS_HDR_AF_ADDR */
		k=0;
		while( is_pattern && p<sms->ascii+sms->userdatalength
		&& k<SMS_HDR_AF_ADDR_LEN)
			if (*(p++)!=SMS_HDR_AF_ADDR[k++])
				is_pattern = 0;
	} else {
		/* no trace of the pattern sent along with the orig sms*/
		do {
			if ((p[0]=='s'||p[0]=='S') && (p[1]=='i'||p[1]=='I')
			&& (p[2]=='p'||p[2]=='P') && p[3]==':') {
				/* we got the address beginning */
				sip_addr.s = p;
				/* goes to the end of the address */
				while(p<sms->ascii+sms->userdatalength && is_in_sip_addr(*p) )
					p++;
				if (p==sms->ascii+sms->userdatalength) {
					LM_ERR("failed to find sip address end in sms body [%s]!\n",
							sms->ascii);
					goto error;
				}
				sip_addr.len = p-sip_addr.s;
			} else {
				/* parse to the next word */
				/*LM_DBG("*** Skipping word len=%d\n",sms->userdatalength);*/
				while(p<sms->ascii+sms->userdatalength&&no_sip_addr_begin(*p)){
					p++;
				}
				p++;
				if (p+9>=sms->ascii+sms->userdatalength) {
				LM_ERR("unable to find sip address start in sms body [%s]!\n",
						sms->ascii);
					goto error;
				}
				/*LM_DBG("*** Done\n");*/
			}
		}while (!sip_addr.len);
	}

	/* the rest of the sms (if any ;-)) is the body! */
	sip_body.s = p;
	sip_body.len = sms->ascii + sms->userdatalength - p;
	/* let's trim out all \n an \r from beginning */
	while ( sip_body.len && sip_body.s
	&& (sip_body.s[0]=='\n' || sip_body.s[0]=='\r') ) {
		sip_body.s++;
		sip_body.len--;
	}
	if (sip_body.len==0) {
		LM_WARN("empty body for sms [%s]", sms->ascii);
		goto error;
	}
	LM_DBG("extracted body is: [%.*s]\n",sip_body.len, sip_body.s);

	/* finally, let's send it as sip message */
	sip_from.s = sms->sender;
	sip_from.len = strlen(sms->sender);
	/* patch the body with date and time */
	if (sms->userdatalength + CRLF_LEN + 1 /*'('*/ + DATE_LEN
	+ 1 /*','*/ + TIME_LEN + 1 /*')'*/< sizeof(sms->ascii)) {
		p = sip_body.s + sip_body.len;
		append_str( p, CRLF, CRLF_LEN);
		*(p++) = '(';
		append_str( p, sms->date, DATE_LEN);
		*(p++) = ',';
		append_str( p, sms->time, TIME_LEN);
		*(p++) = ')';
		sip_body.len += CRLF_LEN + DATE_LEN + TIME_LEN + 3;
	}
	return send_sip_msg_request(&sip_addr, &sip_from, &sip_body);

error:
	return -1;
}
Exemple #14
0
/*! \brief
 *  handle io routine, based on the fd_map type
 * (it will be called from reactor_main_loop )
 * params:  fm  - pointer to a fd hash entry
 *          idx - index in the fd_array (or -1 if not known)
 * return: -1 on error, or when we are not interested any more on reads
 *            from this fd (e.g.: we are closing it )
 *          0 on EAGAIN or when by some other way it is known that no more
 *            io events are queued on the fd (the receive buffer is empty).
 *            Usefull to detect when there are no more io events queued for
 *            sigio_rt, epoll_et, kqueue.
 *         >0 on successfull read from the fd (when there might be more io
 *            queued -- the receive buffer might still be non-empty)
 */
inline static int handle_io(struct fd_map* fm, int idx,int event_type)
{
	int ret=0;
	int n;
	struct tcp_connection* con;
	int s,rw;
	long resp;
	long response[2];

	switch(fm->type){
		case F_TIMER_JOB:
			handle_timer_job();
			break;
		case F_SCRIPT_ASYNC:
			async_resume_f( fm->fd, fm->data);
			return 0;
		case F_TCPMAIN:
again:
			ret=n=receive_fd(fm->fd, response, sizeof(response), &s, 0);
			if (n<0){
				if (errno == EWOULDBLOCK || errno == EAGAIN){
					ret=0;
					break;
				}else if (errno == EINTR) goto again;
				else{
					LM_CRIT("read_fd: %s \n", strerror(errno));
						abort(); /* big error*/
				}
			}
			if (n==0){
				LM_WARN("0 bytes read\n");
				break;
			}
			con = (struct tcp_connection *)response[0];
			rw = (int)response[1];

			if (con==0){
					LM_CRIT("null pointer\n");
					break;
			}
			if (s==-1) {
				LM_BUG("read_fd:no fd read\n");
				/* FIXME? */
				return -1;
			}
			if (con==tcp_conn_lst){
				LM_CRIT("duplicate"
							" connection received: %p, id %d, fd %d, refcnt %d"
							" state %d (n=%d)\n", con, con->id, con->fd,
							con->refcnt, con->state, n);
				tcpconn_release(con, CONN_ERROR,0);
				break; /* try to recover */
			}

			LM_DBG("We have received conn %p with rw %d on fd %d\n",con,rw,s);
			if (rw & IO_WATCH_READ) {
				/* 0 attempts so far for this SIP MSG */
				con->msg_attempts = 0;

				/* must be before reactor_add, as the add might catch some
				 * already existing events => might call handle_io and
				 * handle_io might decide to del. the new connection =>
				 * must be in the list */
				tcpconn_listadd(tcp_conn_lst, con, c_next, c_prev);
				con->timeout = con->lifetime;
				if (reactor_add_reader( s, F_TCPCONN, RCT_PRIO_NET, con )<0) {
					LM_CRIT("failed to add new socket to the fd list\n");
					tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev);
					goto con_error;
				}
	
				/* mark that the connection is currently in our process
				future writes to this con won't have to acquire FD */
				con->proc_id = process_no;
				/* save FD which is valid in context of this TCP worker */
				con->fd=s;
			} else if (rw & IO_WATCH_WRITE) {
				LM_DBG("Received con for async write %p ref = %d\n",con,con->refcnt);
				lock_get(&con->write_lock);
				resp = protos[con->type].net.write( (void*)con, s );
				lock_release(&con->write_lock);
				if (resp<0) {
					ret=-1; /* some error occured */
					con->state=S_CONN_BAD;
					tcpconn_release(con, CONN_ERROR,1);
					break;
				} else if (resp==1) {
					tcpconn_release(con, ASYNC_WRITE,1);
				} else {
					tcpconn_release(con, CONN_RELEASE,1);
				}
				ret = 0;
				/* we always close the socket received for writing */
				close(s);
			}
			break;
		case F_TCPCONN:
			if (event_type & IO_WATCH_READ) {
				con=(struct tcp_connection*)fm->data;
				resp = protos[con->type].net.read( (void*)con, &ret );
				if (resp<0) {
					ret=-1; /* some error occured */
					con->state=S_CONN_BAD;
					reactor_del_all( con->fd, idx, IO_FD_CLOSING );
					tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev);
					con->proc_id = -1;
					if (con->fd!=-1) { close(con->fd); con->fd = -1; }
					tcpconn_release(con, CONN_ERROR,0);
				} else if (con->state==S_CONN_EOF) {
					reactor_del_all( con->fd, idx, IO_FD_CLOSING );
					tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev);
					con->proc_id = -1;
					if (con->fd!=-1) { close(con->fd); con->fd = -1; }
					tcpconn_release(con, CONN_EOF,0);
				} else {
					//tcpconn_release(con, CONN_RELEASE);
					/* keep the connection for now */
					break;
				}
			}
			break;
		case F_NONE:
			LM_CRIT("empty fd map %p: "
						"{%d, %d, %p}\n", fm,
						fm->fd, fm->type, fm->data);
			goto error;
		default:
			LM_CRIT("uknown fd type %d\n", fm->type);
			goto error;
	}

	return ret;
con_error:
	con->state=S_CONN_BAD;
	tcpconn_release(con, CONN_ERROR,0);
	return ret;
error:
	return -1;
}
Exemple #15
0
/*
 * Called after val2str to realy binding
 */
int db_oracle_val2bind(bmap_t* _m, const db_val_t* _v, OCIDate* _o)
{
    if (VAL_NULL(_v)) {
        _m->addr = NULL;
        _m->size = 0;
        _m->type = SQLT_NON;
        return 0;
    }

    switch (VAL_TYPE(_v)) {
    case DB_INT:
        _m->addr = (int*)&VAL_INT(_v);
        _m->size = sizeof(VAL_INT(_v));
        _m->type = SQLT_INT;
        break;

    case DB_BIGINT:
        _m->addr = (int*)&VAL_BIGINT(_v);
        _m->size = sizeof(VAL_BIGINT(_v));
        _m->type = SQLT_NUM;
        break;

    case DB_BITMAP:
        _m->addr = (unsigned*)&VAL_BITMAP(_v);
        _m->size = sizeof(VAL_BITMAP(_v));
        _m->type = SQLT_UIN;
        break;

    case DB_DOUBLE:
        _m->addr = (double*)&VAL_DOUBLE(_v);
        _m->size = sizeof(VAL_DOUBLE(_v));
        _m->type = SQLT_FLT;
        break;

    case DB_STRING:
        _m->addr = (char*)VAL_STRING(_v);
        _m->size = strlen(VAL_STRING(_v))+1;
        _m->type = SQLT_STR;
        break;

    case DB_STR:
    {
        unsigned len = VAL_STR(_v).len;
        char *estr, *pstr = VAL_STR(_v).s;

        estr = (char*)memchr(pstr, 0, len);
        if (estr) {
            LM_WARN("truncate STR len from %u to: '%s'\n",
                    len, pstr);
            len = (unsigned)(estr - pstr) + 1;
        }
        _m->size = len;
        _m->addr = pstr;
        _m->type = SQLT_CHR;
    }
    break;

    case DB_DATETIME:
    {
        struct tm* tm = localtime(&VAL_TIME(_v));
        if (tm->tm_sec == 60)
            --tm->tm_sec;
        OCIDateSetDate(_o, (ub2)(tm->tm_year + 1900),
                       (ub1)(tm->tm_mon + 1), (ub1)tm->tm_mday);
        OCIDateSetTime(_o, (ub1)tm->tm_hour, (ub1)tm->tm_min,
                       (ub1)tm->tm_sec);
        _m->addr = _o;
        _m->size = sizeof(*_o);
        _m->type = SQLT_ODT;
    }
    break;

    case DB_BLOB:
        _m->addr = VAL_BLOB(_v).s;
        _m->size = VAL_BLOB(_v).len;
        _m->type = SQLT_CLOB;
        break;

    default:
        LM_ERR("unknown data type\n");
        return -1;
    }
    return 0;
}
Exemple #16
0
static int b2bl_add_tuple(b2bl_tuple_t* tuple, str* params[])
{
	b2bl_tuple_t* shm_tuple= NULL;
	unsigned int hash_index, local_index;
	str* b2bl_key;
	b2bl_entity_id_t* entity;
	int i;
	b2b_notify_t cback;
	str* client_id = NULL;
	unsigned int logic_restored = 0;

	LM_DBG("Add tuple key [%.*s]\n", tuple->key->len, tuple->key->s);
	if(b2bl_parse_key(tuple->key, &hash_index, &local_index)< 0)
	{
		LM_ERR("Wrong formatted b2b logic key\n");
		return -1;
	}
	shm_tuple = b2bl_insert_new(NULL, hash_index, tuple->scenario, params,
			(tuple->sdp.s?&tuple->sdp:NULL), NULL, local_index,
			&b2bl_key, UPDATEDB_FLAG);
	if(shm_tuple == NULL)
	{
		LM_ERR("Failed to insert new tuple\n");
		return -1;
	}
	shm_tuple->lifetime = tuple->lifetime;
	lock_release(&b2bl_htable[hash_index].lock);
	shm_tuple->scenario_state= tuple->scenario_state;
	shm_tuple->next_scenario_state= tuple->next_scenario_state;

	/* add entities */
	for(i=0; i< MAX_BRIDGE_ENT; i++)
	{
		if(!tuple->bridge_entities[i]->to_uri.len)
			continue;
		LM_DBG("Restore logic info for tuple:entity [%.*s][%d]\n",
				b2bl_key->len, b2bl_key->s, i);

		if(tuple->bridge_entities[i]->type == B2B_SERVER)
			cback = b2b_server_notify;
		else
			cback = b2b_client_notify;

		/* restore to the entities from b2b_entities module
		 * the parameter and callback function */
		if(b2b_api.restore_logic_info(tuple->bridge_entities[i]->type,
			&tuple->bridge_entities[i]->key, cback)< 0)
			LM_WARN("Failed to restore logic info for tuple:entity [%.*s][%d]\n",
				b2bl_key->len, b2bl_key->s, i);
		else
			logic_restored = 1;

		entity= b2bl_create_new_entity(tuple->bridge_entities[i]->type,
			&tuple->bridge_entities[i]->key,&tuple->bridge_entities[i]->to_uri,
			&tuple->bridge_entities[i]->from_uri, 0, &tuple->bridge_entities[i]->scenario_id, 0);
		if(client_id)
			pkg_free(client_id);
		if(entity == NULL)
		{
			LM_ERR("Failed to create entity %d\n", i);
			goto error;
		}
		shm_tuple->bridge_entities[i]= entity;
		/* put the pointer in clients or servers array */
		// FIXME: check if the restore logic is ok
		if(tuple->bridge_entities[i]->type == B2B_SERVER)
		{
			if (shm_tuple->servers[0])
				shm_tuple->servers[1] = entity;
			else
				shm_tuple->servers[0] = entity;
		}
		else
		{
			if (shm_tuple->clients[0])
				shm_tuple->clients[1] = entity;
			else
				shm_tuple->clients[0] = entity;
		}
	}
	if(shm_tuple->bridge_entities[1])
		shm_tuple->bridge_entities[1]->peer = shm_tuple->bridge_entities[0];
	if(shm_tuple->bridge_entities[0])
		shm_tuple->bridge_entities[0]->peer = shm_tuple->bridge_entities[1];

	/* Mark tuple without entities as expired */
	if(logic_restored==0)
		shm_tuple->lifetime = 1;

	return 0;
error:
	shm_free(shm_tuple);
	return -1;
}
Exemple #17
0
static int mod_init(void){
	str s;
	int n;

	LM_INFO("initializing TLS protocol\n");


	if (tls_db_enabled != 0 && tls_db_enabled != 1) {
		tls_db_enabled = 1;
	}

	if (tls_db_enabled) {

		/* create & init lock */
		if ((dom_lock = lock_init_rw()) == NULL) {
			LM_CRIT("failed to init lock\n");
			return -1;
		}

		init_db_url(tls_db_url, 0 /*cannot be null*/);

		tls_db_table.len = strlen(tls_db_table.s);

		if (tls_db_table.len == 0) {
			LM_ERR("db url not specified\n");
			return -1;
		}

		id_col.len = strlen(id_col.s);
		address_col.len = strlen(address_col.s);
		type_col.len = strlen(type_col.s);
		method_col.len = strlen(method_col.s);
		verify_cert_col.len = strlen(verify_cert_col.s);
		require_cert_col.len = strlen(require_cert_col.s);
		certificate_col.len = strlen(certificate_col.s);
		pk_col.len = strlen(pk_col.s);
		crl_check_col.len = strlen(crl_check_col.s);
		calist_col.len = strlen(calist_col.s);
		cadir_col.len = strlen(cadir_col.s);
		cplist_col.len = strlen(cplist_col.s);
		dhparams_col.len = strlen(dhparams_col.s);
		eccurve_col.len = strlen(eccurve_col.s);

		if (db_bind_mod(&tls_db_url, &dr_dbf)) {
			LM_CRIT("cannot bind to database module! "
				"Did you forget to load a database module ?\n");
			return -1;
		}
		/* init DB connection */
		if ((db_hdl = dr_dbf.init(&tls_db_url)) == 0) {
			LM_CRIT("cannot initialize database connection\n");
			return -1;
		}

		if (dr_dbf.use_table(db_hdl, &tls_db_table) < 0) {
			LM_ERR("cannot select table \"%.*s\"\n", tls_db_table.len, tls_db_table.s);
			return -1;
		}
	}

	if (tls_domain_avp) {
		s.s = tls_domain_avp;
		s.len = strlen(s.s);
		if (parse_avp_spec( &s, &tls_client_domain_avp)) {
			LM_ERR("cannot parse tls_client_avp");
			return -1;
		}
	}

	/*
	 * this has to be called before any function calling CRYPTO_malloc,
	 * CRYPTO_malloc will set allow_customize in openssl to 0
	 */
	if (!CRYPTO_set_mem_functions(os_malloc, os_realloc, os_free)) {
		LM_ERR("unable to set the memory allocation functions\n");
		LM_ERR("NOTE: check if you have openssl 1.0.1e-fips, as this "
			"version is know to be broken; if so, you need to upgrade or "
			"downgrade to a differen openssl version !!\n");
		return -1;
	}

#if !defined(OPENSSL_NO_COMP)
	STACK_OF(SSL_COMP)* comp_methods;
	/* disabling compression */
	LM_WARN("disabling compression due ZLIB problems\n");
	comp_methods = SSL_COMP_get_compression_methods();
	if (comp_methods==0) {
		LM_INFO("openssl compression already disabled\n");
	} else {
		sk_SSL_COMP_zero(comp_methods);
	}
#endif
	if (tls_init_multithread() < 0) {
		LM_ERR("failed to init multi-threading support\n");
		return -1;
	}

	SSL_library_init();
	SSL_load_error_strings();
	init_ssl_methods();

	n = check_for_krb();
	if (n==-1) {
		LM_ERR("kerberos check failed\n");
		return -1;
	}

	if ( ( n ^
#ifndef OPENSSL_NO_KRB5
			1
#else
			0
#endif
		 )!=0 ) {
		LM_ERR("compiled agaist an openssl with %s"
				"kerberos, but run with one with %skerberos\n",
				(n==1)?"":"no ",(n!=1)?"no ":"");
		return -1;
	}

	/*
	 * finish setting up the tls default domains
	 */
	tls_default_client_domain.type = TLS_DOMAIN_DEF|TLS_DOMAIN_CLI ;
	tls_default_client_domain.addr.af = AF_INET;

	tls_default_server_domain.type = TLS_DOMAIN_DEF|TLS_DOMAIN_SRV;
	tls_default_server_domain.addr.af = AF_INET;

	/*
	 * now initialize tls default domains
	 */
	if ( (n=init_tls_domains(&tls_default_server_domain)) ) {
		return n;
	}

	if ( (n=init_tls_domains(&tls_default_client_domain)) ) {
		return n;
	}
	/*
	 * now initialize tls virtual domains
	 */
	
	if (tls_db_enabled && load_info(&dr_dbf, db_hdl, &tls_db_table, &tls_server_domains,
			&tls_client_domains)){
		return -1;
	}

	if ( (n=init_tls_domains(tls_server_domains)) ) {
		return n;
	}

	if ( (n=init_tls_domains(tls_client_domains)) ) {
		return n;
	}
	/*
	 * we are all set
	 */
	return 0;

}
Exemple #18
0
int unregister(struct sip_msg* _m, udomain_t* _d, str* _uri, str *_ruid)
{
	str aor = {0, 0};
	sip_uri_t *u;
	urecord_t *r;
	ucontact_t *c;
	int res;

	if (_ruid == NULL) {
		/* No ruid provided - remove all contacts for aor */

		if (extract_aor(_uri, &aor, NULL) < 0) {
			LM_ERR("failed to extract Address Of Record\n");
			return -1;
		}

		u = parse_to_uri(_m);
		if(u==NULL) {
			LM_ERR("failed to extract Address Of Record\n");
			return -1;
		}

		if (star(_m, _d, &aor, &u->host) < 0)
		{
			LM_ERR("error unregistering user [%.*s]\n", aor.len, aor.s);
			return -2;
		}
	} else {
		/* ruid provided - remove a specific contact */

		if (_uri->len > 0) {

			if (extract_aor(_uri, &aor, NULL) < 0) {
				LM_ERR("failed to extract Address Of Record\n");
				return -1;
			}

			if (ul.get_urecord_by_ruid(_d, ul.get_aorhash(&aor),
						_ruid, &r, &c) != 0) {
				LM_WARN("AOR/Contact not found\n");
				return -3;
			}
			if (ul.delete_ucontact(r, c) != 0) {
				ul.unlock_udomain(_d, &aor);
				LM_WARN("could not delete contact\n");
				return -2;
			}
			ul.unlock_udomain(_d, &aor);

		} else {

			res = ul.delete_urecord_by_ruid(_d, _ruid);
			switch (res) {
				case -1:
					LM_ERR("could not delete contact\n");
					return -2;
				case -2:
					LM_WARN("contact not found\n");
					return -3;
				default:
					return 1;
			}

		}
	}

	return 1;
}
Exemple #19
0
/*
 * Setup default SSL_CTX (and SSL * ) behavior:
 *     verification, cipherlist, acceptable versions, ...
 */
static int init_ssl_ctx_behavior( struct tls_domain *d ) {
	int verify_mode;

#if (OPENSSL_VERSION_NUMBER > 0x10001000L)
	/*
	 * set dh params
	 */
	if (!d->tmp_dh_file) {
		LM_DBG("no DH params file for tls[%s:%d] defined, "
				"using default '%s'\n", ip_addr2a(&d->addr), d->port,
				tls_tmp_dh_file);
		d->tmp_dh_file = tls_tmp_dh_file;
	}
	if (d->tmp_dh_file && set_dh_params(d->ctx, d->tmp_dh_file) < 0)
		return -1;

	if (d->tls_ec_curve) {
		if (set_ec_params(d->ctx, d->tls_ec_curve) < 0) {
			return -1;
		}
	}
	else {
		LM_NOTICE("No EC curve defined\n");
	}
#else
	if (d->tmp_dh_file  || tls_tmp_dh_file)
		LM_WARN("DH params file discarded as not supported by your openSSL version\n");
	if (d->tls_ec_curve)
		LM_WARN("EC params file discarded as not supported by your openSSL version\n");
#endif

	if( d->ciphers_list != 0 ) {
		if( SSL_CTX_set_cipher_list(d->ctx, d->ciphers_list) == 0 ) {
			LM_ERR("failure to set SSL context "
					"cipher list '%s'\n", d->ciphers_list);
			return -1;
		} else {
			LM_NOTICE("cipher list set to %s\n", d->ciphers_list);
		}
	} else {
		LM_DBG( "cipher list null ... setting default\n");
	}

	/* Set a bunch of options:
	 *     do not accept SSLv2 / SSLv3
	 *     no session resumption
	 *     choose cipher according to server's preference's*/

	SSL_CTX_set_options(d->ctx,
			SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
			SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
			SSL_OP_CIPHER_SERVER_PREFERENCE);

	/* Set verification procedure
	 * The verification can be made null with SSL_VERIFY_NONE, or
	 * at least easier with SSL_VERIFY_CLIENT_ONCE instead of
	 * SSL_VERIFY_FAIL_IF_NO_PEER_CERT.
	 * For extra control, instead of 0, we can specify a callback function:
	 *           int (*verify_callback)(int, X509_STORE_CTX *)
	 * Also, depth 2 may be not enough in some scenarios ... though no need
	 * to increase it much further */

	if (d->type & TLS_DOMAIN_SRV) {
		/* Server mode:
		 * SSL_VERIFY_NONE
		 *   the server will not send a client certificate request to the
		 *   client, so the client  will not send a certificate.
		 * SSL_VERIFY_PEER
		 *   the server sends a client certificate request to the client.
		 *   The certificate returned (if any) is checked. If the verification
		 *   process fails, the TLS/SSL handshake is immediately terminated
		 *   with an alert message containing the reason for the verification
		 *   failure. The behaviour can be controlled by the additional
		 *   SSL_VERIFY_FAIL_IF_NO_PEER_CERT and SSL_VERIFY_CLIENT_ONCE flags.
		 * SSL_VERIFY_FAIL_IF_NO_PEER_CERT
		 *   if the client did not return a certificate, the TLS/SSL handshake
		 *   is immediately terminated with a ``handshake failure'' alert.
		 *   This flag must be used together with SSL_VERIFY_PEER.
		 * SSL_VERIFY_CLIENT_ONCE
		 *   only request a client certificate on the initial TLS/SSL
		 *   handshake. Do not ask for a client certificate again in case of
		 *   a renegotiation. This flag must be used together with
		 *   SSL_VERIFY_PEER.
		 */

		if( d->verify_cert ) {
			verify_mode = SSL_VERIFY_PEER;
			if( d->require_client_cert ) {
				LM_WARN("client verification activated. Client "
						"certificates are mandatory.\n");
				verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
			} else
				LM_WARN("client verification activated. Client "
						"certificates are NOT mandatory.\n");
		} else {
			verify_mode = SSL_VERIFY_NONE;
			LM_WARN("client verification NOT activated. Weaker security.\n");
		}
	} else {
		/* Client mode:
		 * SSL_VERIFY_NONE
		 *   if not using an anonymous cipher (by default disabled), the
		 *   server will send a certificate which will be checked. The result
		 *   of the certificate verification process can be checked after the
		 *   TLS/SSL handshake using the SSL_get_verify_result(3) function.
		 *   The handshake will be continued regardless of the verification
		 *   result.
		 * SSL_VERIFY_PEER
		 *   the server certificate is verified. If the verification process
		 *   fails, the TLS/SSL handshake is immediately terminated with an
		 *   alert message containing the reason for the verification failure.
		 *   If no server certificate is sent, because an anonymous cipher is
		 *   used, SSL_VERIFY_PEER is ignored.
		 * SSL_VERIFY_FAIL_IF_NO_PEER_CERT
		 *   ignored
		 * SSL_VERIFY_CLIENT_ONCE
		 *   ignored
		 */

		if( d->verify_cert ) {
			verify_mode = SSL_VERIFY_PEER;
			LM_WARN("server verification activated.\n");
		} else {
			verify_mode = SSL_VERIFY_NONE;
			LM_WARN("server verification NOT activated. Weaker security.\n");
		}
	}

	SSL_CTX_set_verify( d->ctx, verify_mode, verify_callback);
	SSL_CTX_set_verify_depth( d->ctx, VERIFY_DEPTH_S);

	SSL_CTX_set_session_cache_mode( d->ctx, SSL_SESS_CACHE_SERVER );
	SSL_CTX_set_session_id_context( d->ctx, OS_SSL_SESS_ID,
			OS_SSL_SESS_ID_LEN );

	return 0;
}
Exemple #20
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, udomain_t* _d, str* _a, int _use_regid, int novariation)
{
	ucontact_info_t* ci;
	urecord_t* r = NULL;
	ucontact_t* c;
	contact_t* _c;
	unsigned int flags;
	int num, expires;
	int maxc;
#ifdef USE_TCP
	int e_max, tcp_check;
	struct sip_uri uri;
#endif
	sip_uri_t *u;

	u = parse_to_uri(_m);
	if(u==NULL)
		goto error;

	flags = mem_only;
#ifdef USE_TCP
	if ( (_m->flags&tcp_persistent_flag)
			&& (_m->rcv.proto==PROTO_TCP||_m->rcv.proto==PROTO_TLS
				||_m->rcv.proto==PROTO_WS||_m->rcv.proto==PROTO_WSS)) {
		e_max = 0;
		tcp_check = 1;
	} else {
		e_max = tcp_check = 0;
	}
#endif
	_c = get_first_contact(_m);
	maxc = reg_get_crt_max_contacts();
	for( num=0,r=0,ci=0 ; _c ; _c = get_next_contact(_c) ) {
		/* calculate expires */
		calc_contact_expires(_m, _c->expires, &expires, novariation);
		/* Skip contacts with zero expires */
		if (expires == 0)
			continue;


		if (maxc > 0 && num >= maxc) {
			LM_INFO("too many contacts (%d) for AOR <%.*s>\n",
					num, _a->len, _a->s);
			rerrno = R_TOO_MANY;
			goto error;
		}
		num++;

		if (r==0) {
			if (ul.insert_urecord(_d, _a, &r) < 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, expires, flags, _use_regid))==0 ) {
			LM_ERR("failed to extract contact info\n");
			goto error;
		}

		/* hack to work with buggy clients having many contacts with same
		 * address in one REGISTER - increase CSeq to detect if there was
		 * one already added, then update */
		ci->cseq++;
		if ( r->contacts==0
				|| ul.get_ucontact_by_instance(r, &_c->uri, ci, &c) != 0) {
			ci->cseq--;
			if (ul.insert_ucontact( r, &_c->uri, ci, &c) < 0) {
				rerrno = R_UL_INS_C;
				LM_ERR("failed to insert contact\n");
				goto error;
			}
		} else {
			ci->cseq--;
			if (ul.update_ucontact( r, c, ci) < 0) {
				rerrno = R_UL_UPD_C;
				LM_ERR("failed to update contact\n");
				goto error;
			}
		}
#ifdef USE_TCP
		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 (uri.proto==PROTO_TCP || uri.proto==PROTO_TLS || uri.proto==PROTO_WS || uri.proto==PROTO_WSS) {
				if (e_max) {
					LM_WARN("multiple TCP contacts on single REGISTER\n");
					if (expires>e_max) e_max = expires;
				} else {
					e_max = expires;
				}
			}
		}
#endif
	}

	if (r) {
		if (r->contacts)
			build_contact(_m, r->contacts, &u->host);
		ul.release_urecord(r);
	} else { /* No contacts found */
		build_contact(_m, NULL, &u->host);
	}

#ifdef USE_TCP
	if ( tcp_check && e_max>0 ) {
		e_max -= act_time;
		/*FIXME: Do we want this in the sr core?*/
		/*force_tcp_conn_lifetime( &_m->rcv , e_max + 10 );*/
	}
#endif

	return 0;
error:
	if (r)
		ul.delete_urecord(_d, _a, r);
	return -1;
}
Exemple #21
0
/*!
 * \brief Function that is registered as RR callback for dialog tracking
 *
 * Function that is registered as RR callback for dialog tracking. It
 * sets the appropriate events after the SIP method and run the state
 * machine to update the dialog state. It updates then the saved
 * dialogs and also the statistics.
 * \param req SIP request
 * \param route_params record-route parameter
 * \param param unused
 */
void dlg_onroute(struct sip_msg* req, str *route_params, void *param) {
    struct dlg_cell *dlg;
    str val, callid, ftag, ttag;
    int h_entry, h_id, new_state, old_state, unref, event, timeout;
    unsigned int dir;
    int ret = 0;

    if (current_dlg_pointer != NULL)
        return;

    /* skip initial requests - they may end up here because of the
     * preloaded route */
    if ((!req->to && parse_headers(req, HDR_TO_F, 0) < 0) || !req->to) {
        LM_ERR("bad request or missing TO hdr :-/\n");
        return;
    }
    if (get_to(req)->tag_value.len == 0)
        return;

    dlg = 0;
    dir = DLG_DIR_NONE;

    if (seq_match_mode != SEQ_MATCH_NO_ID) {
        if (d_rrb.get_route_param(req, &rr_param, &val) != 0) {
            LM_DBG("Route param '%.*s' not found\n", rr_param.len, rr_param.s);
            if (seq_match_mode == SEQ_MATCH_STRICT_ID)
                return;
        } else {
            LM_DBG("route param is '%.*s' (len=%d)\n", val.len, val.s, val.len);

            if (parse_dlg_rr_param(val.s, val.s + val.len, &h_entry, &h_id) < 0)
                return;

            dlg = lookup_dlg(h_entry, h_id);
            if (dlg == 0) {
                LM_WARN("unable to find dialog for %.*s "
                        "with route param '%.*s' [%u:%u]\n",
                        req->first_line.u.request.method.len,
                        req->first_line.u.request.method.s,
                        val.len, val.s, h_entry, h_id);
                if (seq_match_mode == SEQ_MATCH_STRICT_ID)
                    return;
            } else {
                if (pre_match_parse(req, &callid, &ftag, &ttag, 1) < 0) {
                    // lookup_dlg has incremented the ref count by 1
                    unref_dlg(dlg, 1);
                    return;
                }
                if (match_dialog(dlg, &callid, &ftag, &ttag, &dir) == 0) {
                    LM_WARN("tight matching failed for %.*s with callid='%.*s'/%d, "
                            "ftag='%.*s'/%d, ttag='%.*s'/%d and direction=%d\n",
                            req->first_line.u.request.method.len,
                            req->first_line.u.request.method.s,
                            callid.len, callid.s, callid.len,
                            ftag.len, ftag.s, ftag.len,
                            ttag.len, ttag.s, ttag.len, dir);
                    LM_WARN("dialog identification elements are callid='%.*s'/%d, "
                            "caller tag='%.*s'/%d\n",
                            dlg->callid.len, dlg->callid.s, dlg->callid.len,
                            dlg->from_tag.len, dlg->from_tag.s,
                            dlg->from_tag.len);
                    // lookup_dlg has incremented the ref count by 1
                    unref_dlg(dlg, 1);

                    // Reset variables in order to do a lookup based on SIP-Elements.
                    dlg = 0;
                    dir = DLG_DIR_NONE;

                    if (seq_match_mode == SEQ_MATCH_STRICT_ID)
                        return;
                }
            }
        }
    }

    if (dlg == 0) {
        if (pre_match_parse(req, &callid, &ftag, &ttag, 1) < 0)
            return;
        /* TODO - try to use the RR dir detection to speed up here the
         * search -bogdan */
        dlg = get_dlg(&callid, &ftag, &ttag, &dir);
        if (!dlg) {
            LM_DBG("Callid '%.*s' not found\n",
                    req->callid->body.len, req->callid->body.s);
            return;
        }
    }

    /* set current dialog - re-use ref increment from dlg_get() above */
    set_current_dialog(req, dlg);
    _dlg_ctx.dlg = dlg;

    if (d_tmb.register_tmcb(req, NULL, TMCB_REQUEST_FWDED,
            store_dlg_in_tm_cb, (void*) dlg, NULL) < 0) {
        LM_ERR("failed to store dialog in transaction during dialog creation for later reference\n");
    }

    /* run state machine */
    switch (req->first_line.u.request.method_value) {
        case METHOD_PRACK:
            event = DLG_EVENT_REQPRACK;
            break;
        case METHOD_ACK:
            event = DLG_EVENT_REQACK;
            break;
        case METHOD_BYE:
            event = DLG_EVENT_REQBYE;
            break;
        default:
            event = DLG_EVENT_REQ;
    }

    next_state_dlg(dlg, event, &old_state, &new_state, &unref, 0);

    LM_DBG("unref after next state is %i\n", unref);
    CURR_DLG_ID = req->id;
    CURR_DLG_LIFETIME = (unsigned int) (time(0)) - dlg->start_ts;
    CURR_DLG_STATUS = new_state;

    /* run actions for the transition */
    if (event == DLG_EVENT_REQBYE && new_state == DLG_STATE_DELETED &&
            old_state != DLG_STATE_DELETED) {
        LM_DBG("BYE successfully processed\n");
        /* remove from timer */
        ret = remove_dialog_timer(&dlg->tl);
        if (ret < 0) {
            LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
                    "with clid '%.*s' and tags '%.*s'\n",
                    dlg, dlg->h_entry, dlg->h_id,
                    dlg->callid.len, dlg->callid.s,
                    dlg->from_tag.len, dlg->from_tag.s);

        } else if (ret > 0) {
            LM_WARN("inconsitent dlg timer data on dlg %p [%u:%u] "
                    "with clid '%.*s' and tags '%.*s' \n",
                    dlg, dlg->h_entry, dlg->h_id,
                    dlg->callid.len, dlg->callid.s,
                    dlg->from_tag.len, dlg->from_tag.s);

		} else {
			unref++;
		}
		/* dialog terminated (BYE) */
		dlg_terminated(req, dlg, dir);
		unref_dlg(dlg, unref);
		counter_add(dialog_ng_cnts_h.active, -1);
		counter_inc(dialog_ng_cnts_h.processed);
        return;
    }

    if ((event == DLG_EVENT_REQ || event == DLG_EVENT_REQACK)
            && (new_state == DLG_STATE_CONFIRMED || new_state==DLG_STATE_EARLY)) {

        timeout = get_dlg_timeout(req);
        if (timeout != default_timeout) {
            dlg->lifetime = timeout;
        }
        if (update_dlg_timer(&dlg->tl, dlg->lifetime) == -1) {
            LM_ERR("failed to update dialog lifetime\n");
        }
        if (update_cseqs(dlg, req, dir, &ttag) != 0) {
            LM_ERR("cseqs update failed\n");
        } else {
            dlg->dflags |= DLG_FLAG_CHANGED;
        }

		if(dlg_db_mode==DB_MODE_REALTIME && (dlg->dflags&DLG_FLAG_CHANGED)) {
			update_dialog_dbinfo(dlg);
		}

        if (old_state != DLG_STATE_CONFIRMED) {
            LM_DBG("confirming ACK successfully processed\n");

            /* confirming ACK request */
            run_dlg_callbacks(DLGCB_CONFIRMED, dlg, req, NULL, dir, 0);
        } else {
            LM_DBG("sequential request successfully processed\n");

            /* within dialog request */
            run_dlg_callbacks(DLGCB_REQ_WITHIN, dlg, req, NULL, dir, 0);

            if ((event != DLG_EVENT_REQACK) &&
                    (dlg->cbs.types) & DLGCB_RESPONSE_WITHIN) {
                /* ref the dialog as registered into the transaction callback.
                 * unref will be done when the callback will be destroyed */
                ref_dlg(dlg, 1);
                /* register callback for the replies of this request */
                if (d_tmb.register_tmcb(req, 0, TMCB_RESPONSE_FWDED,
                        (dir == DLG_DIR_UPSTREAM) ? dlg_seq_down_onreply : dlg_seq_up_onreply,
                        (void*) dlg, unreference_dialog) < 0) {
                    LM_ERR("failed to register TMCB (2)\n");
                    unref_dlg(dlg, 1);
                }
            }
        }
    }

    if (new_state == DLG_STATE_CONFIRMED && old_state != DLG_STATE_CONFIRMED) {
        dlg->dflags |= DLG_FLAG_CHANGED;

        if(dlg_db_mode == DB_MODE_REALTIME)
        	update_dialog_dbinfo(dlg);
    }

    return;
}
Exemple #22
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, int _mode, int _use_regid, int novariation)
{
	ucontact_info_t *ci;
	ucontact_t *c, *ptr, *ptr0;
	int expires, ret, updated;
	unsigned int flags;
#ifdef USE_TCP
	int e_max, tcp_check;
	struct sip_uri uri;
#endif
	int rc;
	contact_t* _c;
	int maxc;

	/* mem flag */
	flags = mem_only;

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

	if (!_mode) {
		maxc = reg_get_crt_max_contacts();
		if(maxc>0) {
			_c = get_first_contact(_m);
			if(test_max_contacts(_m, _r, _c, ci, maxc) != 0)
				goto error;
		}
	}

#ifdef USE_TCP
	if ( (_m->flags&tcp_persistent_flag) &&
			(_m->rcv.proto==PROTO_TCP||_m->rcv.proto==PROTO_TLS||_m->rcv.proto==PROTO_WS||_m->rcv.proto==PROTO_WSS)) {
		e_max = -1;
		tcp_check = 1;
	} else {
		e_max = tcp_check = 0;
	}
#endif

	_c = get_first_contact(_m);
	updated=0;
	for( ; _c ; _c = get_next_contact(_c) ) {
		/* calculate expires */
		calc_contact_expires(_m, _c->expires, &expires, novariation);

		/* pack the contact info */
		if ( (ci=pack_ci( 0, _c, expires, 0, _use_regid))==0 ) {
			LM_ERR("failed to pack contact specific info\n");
			goto error;
		}

		/* search for the contact*/
		ret = ul.get_ucontact_by_instance( _r, &_c->uri, ci, &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) {
			if(expires!=0 && _mode)
				break;
			continue;
		}

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

			if (ul.insert_ucontact( _r, &_c->uri, ci, &c) < 0) {
				rerrno = R_UL_INS_C;
				LM_ERR("failed to insert contact\n");
				goto error;
			}
			rc = 1;
			if(_mode)
			{
				ptr=_r->contacts;
				while(ptr)
				{
					ptr0 = ptr->next;
					if(ptr!=c)
						ul.delete_ucontact(_r, ptr);
					ptr=ptr0;
				}
				updated=1;
			}
		} else {
			/* Contact found */
			if (expires == 0) {
				/* it's expired */
				if (mem_only) {
					c->flags |= FL_MEM;
				} else {
					c->flags &= ~FL_MEM;
				}

				if (ul.delete_ucontact(_r, c) < 0) {
					rerrno = R_UL_DEL_C;
					LM_ERR("failed to delete contact\n");
					goto error;
				}
				rc = 3;
			} else {
				/* do update */
				if(_mode)
				{
					ptr=_r->contacts;
					while(ptr)
					{
						ptr0 = ptr->next;
						if(ptr!=c)
							ul.delete_ucontact(_r, ptr);
						ptr=ptr0;
					}
					updated=1;
				}
				/* If call-id has changed then delete all records with this sip.instance
				 * then insert new record */
				if (ci->instance.s != NULL &&
						(ci->callid->len != c->callid.len ||
						strncmp(ci->callid->s, c->callid.s, ci->callid->len) != 0))
				{
					ptr = _r->contacts;
					while (ptr)
					{
						ptr0 = ptr->next;
						if ((ptr != c) && ptr->instance.len == c->instance.len &&
								strncmp(ptr->instance.s, c->instance.s, ptr->instance.len) == 0)
						{
							ul.delete_ucontact(_r, ptr);
						}
						ptr = ptr0;
					}
					updated = 1;
				}
				if (ul.update_ucontact(_r, c, ci) < 0) {
					rerrno = R_UL_UPD_C;
					LM_ERR("failed to update contact\n");
					goto error;
				}
				rc = 2;
			}
		}
#ifdef USE_TCP
		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 (uri.proto==PROTO_TCP || uri.proto==PROTO_TLS || uri.proto==PROTO_WS || uri.proto==PROTO_WSS) {
				if (e_max>0) {
					LM_WARN("multiple TCP contacts on single REGISTER\n");
				}
				if (expires>e_max) e_max = expires;
			}
		}
#endif
		/* have one contact only -- break */
		if(updated)
			break;
	}

#ifdef USE_TCP
	if ( tcp_check && e_max>-1 ) {
		if (e_max) e_max -= act_time;
		/*FIXME: Do we want this in the sr core? */
		/*force_tcp_conn_lifetime( &_m->rcv , e_max + 10 );*/
	}
#endif

	return rc;
error:
	return -1;
}
Exemple #23
0
int dbg_dump_json(struct sip_msg* msg, unsigned int mask, int level)
{
	int i;
	pv_value_t value;
	pv_cache_t **_pv_cache = pv_cache_get_table();
	pv_cache_t *el = NULL;
	srjson_doc_t jdoc;
	srjson_t *jobj = NULL;
	char *output = NULL;
	str item_name = STR_NULL;
	static char iname[128];
	int result = -1;

	if(_pv_cache==NULL)
	{
		LM_ERR("cannot access pv_cache\n");
		return -1;
	}

	memset(_dbg_xavp_dump, 0, sizeof(str*)*DBG_XAVP_DUMP_SIZE);
	srjson_InitDoc(&jdoc, NULL);
	if(jdoc.root==NULL)
	{
		jdoc.root = srjson_CreateObject(&jdoc);
		if(jdoc.root==NULL)
		{
			LM_ERR("cannot create json root\n");
			goto error;
		}
	}
	for(i=0;i<PV_CACHE_SIZE;i++)
	{
		el = _pv_cache[i];
		while(el)
		{
			if(!(el->spec.type==PVT_AVP||
				el->spec.type==PVT_SCRIPTVAR||
				el->spec.type==PVT_XAVP||
				el->spec.type==PVT_OTHER)||
				!((el->spec.type==PVT_AVP&&mask&DBG_DP_AVP)||
				(el->spec.type==PVT_XAVP&&mask&DBG_DP_XAVP)||
				(el->spec.type==PVT_SCRIPTVAR&&mask&DBG_DP_SCRIPTVAR)||
				(el->spec.type==PVT_OTHER&&mask&DBG_DP_OTHER))||
				(el->spec.trans!=NULL))
			{
				el = el->next;
				continue;
			}
			jobj = NULL;
			item_name.len = 0;
			item_name.s = 0;
			iname[0] = '\0';
			if(el->spec.type==PVT_AVP)
			{
				if(el->spec.pvp.pvi.type==PV_IDX_ALL||
					(el->spec.pvp.pvi.type==PV_IDX_INT&&el->spec.pvp.pvi.u.ival!=0))
				{
					el = el->next;
					continue;
				}
				else
				{
					if(_dbg_get_array_avp_vals(msg, &el->spec.pvp, &jdoc, &jobj, &item_name)!=0)
					{
						LM_WARN("can't get value[%.*s]\n", el->pvname.len, el->pvname.s);
						el = el->next;
						continue;
					}
					if(srjson_GetArraySize(&jdoc, jobj)==0 && !(mask&DBG_DP_NULL))
					{
						el = el->next;
						continue;
					}
					snprintf(iname, 128, "$avp(%.*s)", item_name.len, item_name.s);
				}
			}
			else if(el->spec.type==PVT_XAVP)
			{
				if(_dbg_xavp_dump_lookup(&el->spec.pvp)!=0)
				{
					el = el->next;
					continue;
				}
				if(_dbg_get_obj_xavp_vals(msg, &el->spec.pvp, &jdoc, &jobj, &item_name)!=0)
				{
					LM_WARN("can't get value[%.*s]\n", el->pvname.len, el->pvname.s);
					el = el->next;
					continue;
				}
				if(srjson_GetArraySize(&jdoc, jobj)==0 && !(mask&DBG_DP_NULL))
				{
					el = el->next;
					continue;
				}
				snprintf(iname, 128, "$xavp(%.*s)", item_name.len, item_name.s);
			}
			else
			{
				if(pv_get_spec_value(msg, &el->spec, &value)!=0)
				{
					LM_WARN("can't get value[%.*s]\n", el->pvname.len, el->pvname.s);
					el = el->next;
					continue;
				}
				if(value.flags&(PV_VAL_NULL|PV_VAL_EMPTY|PV_VAL_NONE))
				{
					if(mask&DBG_DP_NULL)
					{
						jobj = srjson_CreateNull(&jdoc);
					}
					else
					{
						el = el->next;
						continue;
					}
				}else if(value.flags&(PV_VAL_INT)){
					jobj = srjson_CreateNumber(&jdoc, value.ri);
				}else if(value.flags&(PV_VAL_STR)){
					jobj = srjson_CreateStr(&jdoc, value.rs.s, value.rs.len);
				}else {
					LM_WARN("el->pvname[%.*s] value[%d] unhandled\n", el->pvname.len, el->pvname.s,
						value.flags);
					el = el->next;
					continue;
				}
				if(jobj==NULL)
				{
					LM_ERR("el->pvname[%.*s] empty json object\n", el->pvname.len,
						el->pvname.s);
					goto error;
				}
				snprintf(iname, 128, "%.*s", el->pvname.len, el->pvname.s);
			}
			if(jobj!=NULL)
			{
				srjson_AddItemToObject(&jdoc, jdoc.root, iname, jobj);
			}
			el = el->next;
		}
	}
	output = srjson_PrintUnformatted(&jdoc, jdoc.root);
	if(output==NULL)
	{
		LM_ERR("cannot print json doc\n");
		goto error;
	}
	LOG(level, "%s\n", output);
	result = 0;

error:
	if(output!=NULL) jdoc.free_fn(output);
	srjson_DestroyDoc(&jdoc);

	return result;
}
Exemple #24
0
int save(struct sip_msg* _m, udomain_t* _d, int _cflags, str *_uri)
{
	contact_t* c;
	int st, mode;
	str aor;
	int ret;
	sip_uri_t *u;
	rr_t *route;
	struct sip_uri puri;
	param_hooks_t hooks;
	param_t *params;
	contact_t *contact;
	int use_ob = 1, use_regid = 1;
	int novariation = 0;


	u = parse_to_uri(_m);
	if(u==NULL)
		goto error;

	rerrno = R_FINE;
	ret = 1;

	if (parse_message(_m) < 0) {
		goto error;
	}

	if (check_contacts(_m, &st) > 0) {
		goto error;
	}

	if (parse_supported(_m) == 0) {
		if (!(get_supported(_m)	& F_OPTION_TAG_OUTBOUND)
				&& reg_outbound_mode == REG_OUTBOUND_REQUIRE) {
			LM_WARN("Outbound required by server and not supported by UAC\n");
			rerrno = R_OB_UNSUP;
			goto error;
		}
	}

	if (parse_require(_m) == 0) {
		if ((get_require(_m) & F_OPTION_TAG_OUTBOUND)
				&& reg_outbound_mode == REG_OUTBOUND_NONE) {
			LM_WARN("Outbound required by UAC and not supported by server\n");
			rerrno = R_OB_REQD;
			goto error;
		}
	}

	if (reg_outbound_mode != REG_OUTBOUND_NONE
			&& _m->contact && _m->contact->parsed
			&& !(parse_headers(_m, HDR_VIA2_F, 0) == -1 || _m->via2 == 0
				|| _m->via2->error != PARSE_OK)) {
		/* Outbound supported on server, and more than one Via: - not the first hop */

		if (!(parse_headers(_m, HDR_PATH_F, 0) == -1 || _m->path == 0)) {
			route = (rr_t *)0;
			if (parse_rr_body(_m->path->body.s, _m->path->body.len, &route) < 0) {
				LM_ERR("Failed to parse Path: header body\n");
				goto error;
			}
			if (parse_uri(route->nameaddr.uri.s, route->nameaddr.uri.len, &puri) < 0) {
				LM_ERR("Failed to parse Path: URI\n");
				free_rr(&route);
				goto error;
			}
			if (parse_params(&puri.params, CLASS_URI, &hooks, &params) != 0) {
				LM_ERR("Failed to parse Path: URI parameters\n");
				free_rr(&route);
				goto error;
			}
			/* Not interested in param body - just the hooks */
			free_params(params);
			if (!hooks.uri.ob) {
				/* No ;ob parameter to top Path: URI - no outbound */
				use_ob = 0;
			}
			free_rr(&route);
		} else {
			/* No Path: header - no outbound */
			use_ob = 0;

		}

		contact = ((contact_body_t *) _m->contact->parsed)->contacts;
		if (!contact) {
			LM_ERR("empty Contact:\n");
			goto error;
		}

		if ((use_ob == 0) && (reg_regid_mode == REG_REGID_OUTBOUND)) {
			if ((get_supported(_m) & F_OPTION_TAG_OUTBOUND)
					&& contact->reg_id) {
				LM_WARN("Outbound used by UAC but not supported by edge proxy\n");
				rerrno = R_OB_UNSUP_EDGE;
				goto error;
			} else {
				/* ignore ;reg-id parameter */
				use_regid = 0;
			}
		}
	}

	get_act_time();
	c = get_first_contact(_m);

	if (extract_aor((_uri)?_uri:&get_to(_m)->uri, &aor, NULL) < 0) {
		LM_ERR("failed to extract Address Of Record\n");
		goto error;
	}

	mem_only = is_cflag_set(REG_SAVE_MEM_FL)?FL_MEM:FL_NONE;
	novariation = is_cflag_set(REG_SAVE_NOVARIATION_FL)? 1:0;

	if (c == 0) {
		if (st) {
			if (star(_m, (udomain_t*)_d, &aor, &u->host) < 0) goto error;
			else ret=3;
		} else {
			if (no_contacts(_m, (udomain_t*)_d, &aor, &u->host) < 0) goto error;
			else ret=4;
		}
	} else {
		mode = is_cflag_set(REG_SAVE_REPL_FL)?1:0;
		if ((ret=add_contacts(_m, (udomain_t*)_d, &aor, mode, use_regid, novariation)) < 0)
			goto error;
		ret = (ret==0)?1:ret;
	}

	update_stat(accepted_registrations, 1);

	/* Only send reply upon request, not upon reply */
	if ((is_route_type(REQUEST_ROUTE) || is_route_type(FAILURE_ROUTE))
			&& !is_cflag_set(REG_SAVE_NORPL_FL) && (reg_send_reply(_m) < 0))
		return -1;

	if (path_enabled && path_mode != PATH_MODE_OFF) {
		reset_path_vector(_m);
	}
	return ret;
error:
	update_stat(rejected_registrations, 1);
	if (is_route_type(REQUEST_ROUTE) && !is_cflag_set(REG_SAVE_NORPL_FL) )
		reg_send_reply(_m);
    if (R_TOO_MANY == rerrno)
	    return -2; 
	/* for all other */
	return 0;
}
Exemple #25
0
/**
 * Check, if a user-agent follows the indicated service-routes
 */
int check_service_routes(struct sip_msg* _m, udomain_t* _d) {
	struct sip_uri uri;
	int i;
	struct hdr_field *hdr;
	rr_t *r;
//	char srcip[20];
//	str received_host;
	
        struct via_body * vb;
        unsigned short port;
        unsigned short proto;
	/* Contact not found => not following service-routes */
	if (c == NULL) return -1;

	/* Search for the first Route-Header: */
	if (find_first_route(_m) < 0) return -1;

	LM_DBG("Got %i Route-Headers.\n", c->num_service_routes);

//	received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip));
//	received_host.s = srcip;
        vb = cscf_get_ue_via(_m);
        port = vb->port?vb->port:5060;
        proto = vb->proto;
	
	/* Lock this record while working with the data: */
	ul.lock_udomain(_d, &vb->host, port, proto);
        
	pcontact_t * c = getContactP(_m, _d, PCONTACT_REGISTERED);
	if (!c) {
		LM_DBG("no contact found in usrloc when checking for service route\n");
		goto error;
	}

	/* Check the route-set: */
	if (_m->route) {
		hdr = _m->route;
		LM_DBG("hdr is %p\n", hdr);
		/* Check, if the first host is ourself: */
		r = (rr_t*)hdr->parsed;
		if (r) {
			LM_DBG("Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
			/* Skip first headers containing myself: */
			while (r && (parse_uri(r->nameaddr.uri.s, r->nameaddr.uri.len, &uri) == 0)
			  && check_self(&uri.host,uri.port_no?uri.port_no:SIP_PORT,0)) {
				LM_DBG("Self\n");
				/* Check for more headers and fail, if it was the last one
				   Check, if service-routes are indicated.
				   If yes, request is not following service-routes */
				if (find_next_route(_m, &hdr) != 0) r = NULL;
				else r = (rr_t*)hdr->parsed;

				if (!r && (c->num_service_routes > 0)) {
					LM_DBG("Not enough route-headers in Message\n");
					goto error;
				}
				LM_DBG("hdr is %p\n", hdr);
				LM_DBG("r is %p\n", r);
				if (r)
					LM_DBG("Next Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
			}
			LM_DBG("We have %d service-routes\n", c->num_service_routes);
			/* Then check the following headers: */
			for (i=0; i< c->num_service_routes; i++) {
				LM_DBG("Route must be: %.*s\n", c->service_routes[i].len, c->service_routes[i].s);

				/* No more Route-Headers? Not following service-routes */
				if (!r) {
					LM_DBG("No more route headers in message.\n");
					 goto error;
				}
				
				LM_DBG("Route is: %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
 				
				/* Check length: */
				if (r->nameaddr.uri.len != c->service_routes[i].len) {
					LM_DBG("Length does not match.\n");
					 goto error;
				}
				/* Check contents: */
				if (strncasecmp(r->nameaddr.uri.s, c->service_routes[i].s, c->service_routes[i].len) != 0) {
					LM_DBG("String comparison failed.\n");
					 goto error;
				}
				if (find_next_route(_m, &hdr) != 0) r = NULL;
				else r = (rr_t*)hdr->parsed;
			}

			/* Check, if it was the last route-header in the message: */
			if (r) {
				LM_DBG("Too many route headers in message.\n");
				 goto error;
			}
		} else {
			LM_WARN("Strange: Route-Header is present, but not parsed?!?");
			if (c->num_service_routes > 0) goto error;
		}
	} else {
		LM_DBG("No route header in Message.\n");
		/* No route-header? Check, if service-routes are indicated.
		   If yes, request is not following service-routes */
		if (c->num_service_routes > 0) goto error;
	}
	/* Unlock domain */
	ul.unlock_udomain(_d, &vb->host, port, proto);
	return 1;
error:
	/* Unlock domain */
	ul.unlock_udomain(_d, &vb->host, port, proto);
	return -1;
}
Exemple #26
0
static int mod_init(void) {
	int n;
	load_dlg_f load_dlg;
	load_tm_f load_tm;
	bind_usrloc_t bind_usrloc;

	if (!fix_parameters()) {
		LM_ERR("unable to set Ro configuration parameters correctly\n");
		goto error;
	}

	/* bind to the tm module */
	if (!(load_tm = (load_tm_f) find_export("load_tm", NO_SCRIPT, 0))) {
		LM_ERR("Can not import load_tm. This module requires tm module\n");
		goto error;
	}
	if (load_tm(&tmb) == -1)
		goto error;

	if (!(load_dlg = (load_dlg_f) find_export("load_dlg", 0, 0))) { /* bind to dialog module */
		LM_ERR("can not import load_dlg. This module requires Kamailio dialog module.\n");
	}
	if (load_dlg(&dlgb) == -1) {
		goto error;
	}

	if (load_cdp_api(&cdpb) != 0) { /* load the CDP API */
		LM_ERR("can't load CDP API\n");
		goto error;
	}

	if (load_dlg_api(&dlgb) != 0) { /* load the dialog API */
		LM_ERR("can't load Dialog API\n");
		goto error;
	}

	cdp_avp = load_cdp_avp(); /* load CDP_AVP API */
	if (!cdp_avp) {
		LM_ERR("can't load CDP_AVP API\n");
		goto error;
	}

	/* init timer lists*/
	if (init_ro_timer(ro_session_ontimeout) != 0) {
		LM_ERR("cannot init timer list\n");
		return -1;
	}

	/* initialized the hash table */
	for (n = 0; n < (8 * sizeof(n)); n++) {
		if (ro_session_hash_size == (1 << n))
			break;
		if (ro_session_hash_size < (1 << n)) {
			LM_WARN("hash_size is not a power of 2 as it should be -> rounding from %d to %d\n", ro_session_hash_size, 1 << (n - 1));
			ro_session_hash_size = 1 << (n - 1);
		}
	}

	if (init_ro_session_table(ro_session_hash_size) < 0) {
		LM_ERR("failed to create ro session hash table\n");
		return -1;
	}

	/* register global timer */
	if (register_timer(ro_timer_routine, 0/*(void*)ro_session_list*/, 1) < 0) {
		LM_ERR("failed to register timer \n");
		return -1;
	}

	bind_usrloc = (bind_usrloc_t) find_export("ul_bind_usrloc", 1, 0);
	if (!bind_usrloc) {
	    LM_ERR("can't bind usrloc\n");
	    return -1;
	}
	
	if (bind_usrloc(&ul) < 0) {
	    return -1;
	}

	/*Register for callback of URECORD being deleted - so we can send a SAR*/

	if (ul.register_ulcb == NULL) {
	    LM_ERR("Could not import ul_register_ulcb\n");
	    return -1;
	}
	
	 /* register statistics */
	if (register_module_stats(exports.name, charging_stats) != 0) {
		LM_ERR("failed to register core statistics\n");
		return -1;
	}

	/*if (register_stat(MOD_NAME, "ccr_responses_time", &ccr_responses_time, 0)) {
		LM_ERR("failed to register core statistics\n");
		return -1;
	}*/

	return 0;

error:
	LM_ERR("Failed to initialise ims_qos module\n");
	return RO_RETURN_FALSE;

}
Exemple #27
0
int send_subscribe(subs_info_t* subs)
{
	ua_pres_t* presentity= NULL;
	str met= {"SUBSCRIBE", 9};
	str* str_hdr= NULL;
	int ret= -1;
	unsigned int hash_code=0;
	ua_pres_t* hentity= NULL;
	int expires;
	int flag;
	int result;
	uac_req_t uac_r;
	db1_res_t *res=NULL;
	ua_pres_t dbpres;
	str pres_uri={0,0}, watcher_uri={0,0}, extra_headers={0,0};
	dlg_t* td= NULL;


	memset(&dbpres, 0, sizeof(dbpres));
	dbpres.pres_uri = &pres_uri;
	dbpres.watcher_uri = &watcher_uri;
	dbpres.extra_headers = &extra_headers; 

	print_subs(subs);

	flag= subs->source_flag;
	if(subs->source_flag & XMPP_INITIAL_SUBS)
		subs->source_flag= XMPP_SUBSCRIBE;

	if(subs->expires< 0)
		expires= 3600;
	else
		expires= subs->expires;

	str_hdr= subs_build_hdr(subs->contact, expires, subs->event, 
			subs->extra_headers);
	if(str_hdr== NULL || str_hdr->s== NULL)
	{
		LM_ERR("while building extra headers\n");
		return -1;
	}

	if (dbmode == PUA_DB_ONLY && pua_dbf.start_transaction)
	{
		if (pua_dbf.start_transaction(pua_db, DB_LOCKING_WRITE) < 0)
		{
			LM_ERR("in start_transaction\n");
			goto error;
		}
	}

	/* generation of hash and getting lock moved from here to further down */

	if (dbmode==PUA_DB_ONLY)
	{
		presentity = get_dialog_puadb(subs->id, subs->pres_uri, &dbpres, &res);
	}
	else
	{
		ua_pres_t pres;

		memset(&pres, 0, sizeof(ua_pres_t));
		pres.pres_uri = subs->pres_uri;
		pres.watcher_uri = subs->watcher_uri;
		pres.flag = subs->source_flag;
		pres.id = subs->id;
		pres.event = subs->event;
		if (subs->remote_target)
			pres.remote_contact = *subs->remote_target;

		hash_code=core_hash(subs->pres_uri, subs->watcher_uri, HASH_SIZE);
		lock_get(&HashT->p_records[hash_code].lock);
		presentity= search_htable(&pres, hash_code);
	}

	/* if flag == INSERT_TYPE insert no matter what the search result is */
	if(subs->flag & INSERT_TYPE)
	{
		LM_DBG("A subscription request with insert type\n");
		goto insert;
	}
	
	if(presentity== NULL )
	{
		int size;
insert:
	
		if (subs->expires == 0)
		{
			/* Don't create a new dialog when expires == 0 */
       			if (dbmode != PUA_DB_ONLY)
				lock_release(&HashT->p_records[hash_code].lock);
			goto done;
		}

		if(subs->flag & UPDATE_TYPE)
		{
			LM_DBG("request for a subscription with update type"
					" and no record found\n");
			subs->flag= INSERT_TYPE;
		}	
		hentity= subscribe_cbparam(subs, REQ_OTHER);
		if(hentity== NULL)
		{
			LM_ERR("while building callback"
					" param\n");
       			if (dbmode != PUA_DB_ONLY)
				lock_release(&HashT->p_records[hash_code].lock);
			goto error;
		}
		hentity->flag= flag;

		set_uac_req(&uac_r, &met, str_hdr, 0, 0, TMCB_LOCAL_COMPLETED,
				subs_cback_func, (void*)hentity);
		result= tmb.t_request_outside
			(&uac_r,						  /* Type of the message */
		subs->remote_target?subs->remote_target:subs->pres_uri,/* Request-URI*/
			subs->pres_uri,				  /* To */
			subs->watcher_uri,			  /* From */
			subs->outbound_proxy		  /* Outbound_proxy */	
			);
		if(result< 0)
		{
			LM_ERR("while sending request with t_request\n");
			if (uac_r.dialog != NULL)
			{
				uac_r.dialog->rem_target.s = 0;
				uac_r.dialog->dst_uri.s = 0;
				tmb.free_dlg(uac_r.dialog);
				uac_r.dialog = 0;
			}
			shm_free(hentity);
       			if (dbmode != PUA_DB_ONLY)
				lock_release(&HashT->p_records[hash_code].lock);

			/* Although this is an error must not return -1 as the
			   calling function must continue processing. */
			ret = 0;
			goto error;
		}

		/* Now create a temporary hash table entry.
		   This is needed to deal with the race-hazard when NOTIFYs
		   arrive before the 2xx response to the SUBSCRIBE. */
		size = sizeof(ua_pres_t)+ 2 * sizeof(str) + (
			subs->pres_uri->len +
			subs->watcher_uri->len +
			uac_r.dialog->id.loc_tag.len +
			uac_r.dialog->id.call_id.len +
			subs->id.len) * sizeof(char);

		presentity= (ua_pres_t*)shm_malloc(size);
		if(presentity== NULL)
		{
			LM_ERR("no more share memory\n");
       			if (dbmode != PUA_DB_ONLY)
				lock_release(&HashT->p_records[hash_code].lock);
			goto error;
		}
		memset(presentity, 0, size);
		size= sizeof(ua_pres_t);

		presentity->pres_uri = (str *) ((char *) presentity + size);
		size += sizeof(str);
		presentity->pres_uri->s= (char *) presentity + size;
		memcpy(presentity->pres_uri->s, subs->pres_uri->s, subs->pres_uri->len);
		presentity->pres_uri->len= subs->pres_uri->len;
		size+= subs->pres_uri->len;

		presentity->watcher_uri= (str *) ((char *) presentity + size);
		size += sizeof(str);
		presentity->watcher_uri->s= (char *) presentity + size;
		memcpy(presentity->watcher_uri->s, subs->watcher_uri->s, subs->watcher_uri->len);
		presentity->watcher_uri->len = subs->watcher_uri->len;
		size += subs->watcher_uri->len;

		presentity->call_id.s = (char *) presentity + size;
		memcpy(presentity->call_id.s, uac_r.dialog->id.call_id.s, uac_r.dialog->id.call_id.len);
		presentity->call_id.len = uac_r.dialog->id.call_id.len;
		size += uac_r.dialog->id.call_id.len;

		presentity->from_tag.s = (char *) presentity + size;
		memcpy(presentity->from_tag.s, uac_r.dialog->id.loc_tag.s, uac_r.dialog->id.loc_tag.len);
		presentity->from_tag.len= uac_r.dialog->id.loc_tag.len;
		size += uac_r.dialog->id.loc_tag.len;

		presentity->id.s = (char *) presentity+ size;
		memcpy(presentity->id.s, subs->id.s, subs->id.len);
		presentity->id.len = subs->id.len;
		size += subs->id.len;

		presentity->event = subs->event;
		presentity->flag = subs->source_flag;
		presentity->cseq = uac_r.dialog->loc_seq.value;

		/* Set the temporary record expiry for 2 * 64T1 seconds from now */
		presentity->expires= (int)time(NULL) + 64;
		presentity->desired_expires= presentity->expires;

		if (dbmode==PUA_DB_ONLY)
		{
			insert_dialog_puadb(presentity);
			shm_free(presentity);
		}
		else
		{
			insert_htable(presentity, hash_code);
			lock_release(&HashT->p_records[hash_code].lock);
		}

		uac_r.dialog->rem_target.s = 0;
		uac_r.dialog->dst_uri.s = 0;
		tmb.free_dlg(uac_r.dialog);
		uac_r.dialog = 0;
	}
	else
	{
		if (subs->internal_update_flag == INTERNAL_UPDATE_TRUE)
		{
			LM_INFO("attempting to re-SUBSCRIBE on internal (rls_update_subs()) update - skipping\n");
			if (dbmode != PUA_DB_ONLY)
				lock_release(&HashT->p_records[hash_code].lock);
			goto done;
		}

		if (presentity->to_tag.len == 0)
		{
			if (subs->expires > 0)
				LM_WARN("attempting to re-SUBSCRIBE to a temporary (non-established) dialog - skipping\n");
			else
			{
				LM_WARN("attempting to un-SUBSCRIBE from a temporary (non-established) dialog - skipping and deleting dialog\n");
				if (dbmode==PUA_DB_ONLY)
					delete_dialog_puadb(presentity);
				else
					delete_htable(presentity, hash_code);
			}

			if (dbmode != PUA_DB_ONLY)
				lock_release(&HashT->p_records[hash_code].lock);
			goto done;
		}

		td= pua_build_dlg_t(presentity);
		if(td== NULL)
		{
			LM_ERR("while building tm dlg_t structure");
			if (dbmode!=PUA_DB_ONLY)
				lock_release(&HashT->p_records[hash_code].lock);
			goto error;
		}
				
		hentity= subs_cbparam_indlg(presentity, expires, REQ_OTHER);
		if(hentity== NULL)
		{
			LM_ERR("while building callback param\n");
			if (dbmode!=PUA_DB_ONLY)
				lock_release(&HashT->p_records[hash_code].lock);
			goto error;
		}
		if (dbmode!=PUA_DB_ONLY)
			lock_release(&HashT->p_records[hash_code].lock);

		LM_DBG("event parameter: %d\n", hentity->event);	

		set_uac_req(&uac_r, &met, str_hdr, 0, td, TMCB_LOCAL_COMPLETED,
				subs_cback_func, (void*)hentity);
		result= tmb.t_request_within(&uac_r);
		if(result< 0)
		{
			shm_free(hentity);
			hentity= NULL;
			LM_ERR("while sending request with t_request\n");
			goto error;
		}
	}


done:
	if (dbmode == PUA_DB_ONLY && pua_dbf.end_transaction)
	{
		if (pua_dbf.end_transaction(pua_db) < 0)
		{
			LM_ERR("in end_transaction\n");
			goto error;
		}
	}

	ret = 0;

error:
	pua_free_tm_dlg(td);
	pkg_free(str_hdr);
	free_results_puadb(res);

	if (dbmode == PUA_DB_ONLY && pua_dbf.abort_transaction)
	{
		if (pua_dbf.abort_transaction(pua_db) < 0)
			LM_ERR("in abort_transaction\n");
	}

	return ret;
}
Exemple #28
0
static int w_ro_ccr(struct sip_msg *msg, str* route_name, str* direction, str* charge_type, str* unit_type, int reservation_units, char* _d) {
	/* PSEUDOCODE/NOTES
	 * 1. What mode are we in - terminating or originating
	 * 2. check request type - 	IEC - Immediate Event Charging
	 * 							ECUR - Event Charging with Unit Reservation
	 * 							SCUR - Session Charging with Unit Reservation
	 * 3. probably only do SCUR in this module for now - can see event based charging in another component instead (AS for SMS for example, etc)
	 * 4. Check a dialog exists for call, if not we fail
	 * 5. make sure we dont already have an Ro Session for this dialog
	 * 6. create new Ro Session
	 * 7. register for DLG callback passing new Ro session as parameter - (if dlg torn down we know which Ro session it is associated with)
	 *
	 *
	 */
	int ret = RO_RETURN_TRUE;
	int dir = 0;
	str identity = {0, 0},
		contact = {0, 0};
	struct hdr_field *h=0;
	
	cfg_action_t* cfg_action;
	tm_cell_t *t;
	unsigned int tindex = 0,
				 tlabel = 0;
	struct impu_data *impu_data;
	udomain_t* domain_t = (udomain_t*) _d;
	char *p;
	struct dlg_cell* dlg;
	unsigned int len;
	struct ro_session *ro_session = 0;
	int free_contact = 0;
	
	LM_DBG("Ro CCR initiated: direction:%.*s, charge_type:%.*s, unit_type:%.*s, reservation_units:%i, route_name:%.*s",
			direction->len, direction->s,
			charge_type->len, charge_type->s,
			unit_type->len, unit_type->s,
			reservation_units,
			route_name->len, route_name->s);

	if (msg->first_line.type != SIP_REQUEST) {
	    LM_ERR("Ro_CCR() called from SIP reply.");
	    return RO_RETURN_ERROR;;
	}
	
	//make sure we can get the dialog! if not, we can't continue
	
	dlg = dlgb.get_dlg(msg);
	if (!dlg) {
		LM_ERR("Unable to find dialog and cannot do Ro charging without it\n");
		return RO_RETURN_ERROR;
	}
	
	dir = get_direction_as_int(direction);
	
	if (dir == RO_ORIG_DIRECTION) {
		//get caller IMPU from asserted identity
		if ((identity = cscf_get_asserted_identity(msg, 0)).len == 0) {
			LM_DBG("No P-Asserted-Identity hdr found. Using From hdr for asserted_identity");
			identity = dlg->from_uri;
		}
		//get caller contact from contact header - if not present then skip this
		if ((contact = cscf_get_contact(msg)).len == 0) {
		    LM_WARN("Can not get contact from message - will not get callbacks if this IMPU is removed to terminate call");
			goto send_ccr;
		}
		
	} else if (dir == RO_TERM_DIRECTION){
		//get callee IMPU from called part id - if not present then skip this
		if ((identity = cscf_get_public_identity_from_called_party_id(msg, &h)).len == 0) {
			LM_WARN("No P-Called-Identity hdr found - will not get callbacks if this IMPU is removed to terminate call");
			goto send_ccr;
		}
		//get callee contact from request URI
		contact = cscf_get_contact_from_requri(msg);
		free_contact = 1;
	    
	} else {
	    LM_CRIT("don't know what to do in unknown mode - should we even get here\n");
	    ret = RO_RETURN_ERROR;
	    goto done;
	}
	
	LM_DBG("IMPU data to pass to usrloc:  contact <%.*s> identity <%.*s>\n", contact.len, contact.s, identity.len, identity.s);
	
	//create impu_data_parcel
	len = identity.len + contact.len +  sizeof (struct impu_data);
	impu_data = (struct impu_data*) shm_malloc(len);
	if (!impu_data) {
	    LM_ERR("Unable to allocate memory for impu_data, trying to send CCR\n");
	    ret = RO_RETURN_ERROR;
	    goto done;
	}
	memset(impu_data, 0, len);
	
	p = (char*) (impu_data + 1);
	impu_data->identity.s = p;
	impu_data->identity.len = identity.len;
	memcpy(p, identity.s, identity.len);
	p += identity.len;

	impu_data->contact.s = p;
	impu_data->contact.len = contact.len;
	memcpy(p, contact.s, contact.len);
	p += contact.len;
	
	impu_data->d = domain_t;

	if (p != (((char*) impu_data) + len)) {
	    LM_ERR("buffer overflow creating impu data, trying to send CCR\n");
	    shm_free(impu_data);
	    ret = RO_RETURN_ERROR;
	    goto done;
	}
	
	
	//reg for callbacks on confirmed and terminated
	if (dlgb.register_dlgcb(dlg, /* DLGCB_RESPONSE_FWDED */ DLGCB_CONFIRMED, add_dlg_data_to_contact, (void*)impu_data ,NULL ) != 0) {
	    LM_CRIT("cannot register callback for dialog confirmation\n");
	    ret = RO_RETURN_ERROR;
	    goto done;
	}

	if (dlgb.register_dlgcb(dlg, DLGCB_TERMINATED | DLGCB_FAILED | DLGCB_EXPIRED /*| DLGCB_DESTROY */, remove_dlg_data_from_contact, (void*)impu_data, NULL ) != 0) {
	    LM_CRIT("cannot register callback for dialog termination\n");
	    ret = RO_RETURN_ERROR;
	    goto done;
	}
	
send_ccr:

	//check if we need to send_ccr - 
	//we get the ro_session based on dlg->h_id and dlg->h_entry and direction 0 (so get any ro_session)
	//if it already exists then we go to done
	if (single_ro_session_per_dialog && (ro_session = lookup_ro_session(dlg->h_entry, &dlg->callid, 0, 0))) {
	    LM_DBG("single_ro_session_per_dialog = 1 and ro_session already exists for this dialog -so we don't need to send another one\n");
	    unref_ro_session(ro_session,1);//for the lookup ro session ref
	    goto done;
	}
	
	LM_DBG("Looking for route block [%.*s]\n", route_name->len, route_name->s);

	int ri = route_get(&main_rt, route_name->s);
	if (ri < 0) {
		LM_ERR("unable to find route block [%.*s]\n", route_name->len, route_name->s);
		ret = RO_RETURN_ERROR;
		goto done;
	}
	
	cfg_action = main_rt.rlist[ri];
	if (!cfg_action) {
		LM_ERR("empty action lists in route block [%.*s]\n", route_name->len, route_name->s);
		ret = RO_RETURN_ERROR;
		goto done;
	}

	//before we send lets suspend the transaction
	t = tmb.t_gett();
	if (t == NULL || t == T_UNDEFINED) {
		if (tmb.t_newtran(msg) < 0) {
			LM_ERR("cannot create the transaction for CCR async\n");
			ret = RO_RETURN_ERROR;
			goto done;
		}
		t = tmb.t_gett();
		if (t == NULL || t == T_UNDEFINED) {
			LM_ERR("cannot lookup the transaction\n");
			ret = RO_RETURN_ERROR;
			goto done;
		}
	}

	LM_DBG("Suspending SIP TM transaction\n");
	if (tmb.t_suspend(msg, &tindex, &tlabel) < 0) {
		LM_ERR("failed to suspend the TM processing\n");
		ret =  RO_RETURN_ERROR;
		goto done;
	}
	
	ret = Ro_Send_CCR(msg, dlg, dir, charge_type, unit_type, reservation_units, cfg_action, tindex, tlabel);
	
	if(ret < 0){
	    LM_ERR("Failed to send CCR\n");
		tmb.t_cancel_suspend(tindex, tlabel);
	}
    
done:
	if(free_contact)  shm_free(contact.s);// shm_malloc in cscf_get_public_identity_from_requri	
	return ret;
}
/**
 * init module function
 */
static int mod_init(void)
{
	unsigned int n;
	LM_INFO("Initializing Http Async module\n");

#ifdef STATISTICS
	/* register statistics */
	if (register_module_stats( exports.name, mod_stats)!=0 ) {
		LM_ERR("failed to register core statistics\n");
		return -1;
	}
#endif
	/* sanitize hash_size */
	if (hash_size < 1){
		LM_WARN("hash_size is smaller "
				"than 1  -> rounding from %d to 1\n",
				hash_size);
				hash_size = 1;
	}
	/* check that the hash table size is a power of 2 */
	for( n=0 ; n<(8*sizeof(n)) ; n++) {
		if (hash_size==(1<<n))
			break;
		if (n && hash_size<(1<<n)) {
			LM_WARN("hash_size is not a power "
				"of 2 as it should be -> rounding from %d to %d (n=%d)\n",
				hash_size, 1<<(n-1), n);
			hash_size = 1<<(n-1);
			break;
		}
	}
	/* check 'workers' param */
	if (num_workers < 1) {
		LM_ERR("the 'workers' parameter must be >= 1\n");
		return -1;
	}

	tls_verify_host = tls_verify_host?1:0;
	tls_verify_peer = tls_verify_peer?1:0;

	/* init http parameters list */
	init_query_params(&ah_params);

	if (strncmp("shm", memory_manager, 3) == 0) {
		curl_memory_manager = 0;
	} else if (strncmp("sys", memory_manager, 3) == 0) {
		curl_memory_manager = 1;
	} else {
		LM_ERR("invalid memory_manager parameter: '%s'\n", memory_manager);
		return -1;
	}

	/* init faked sip msg */
	if(faked_msg_init()<0) {
		LM_ERR("failed to init faked sip msg\n");
		return -1;
	}

	if(load_tm_api( &tmb ) < 0) {
		LM_INFO("cannot load the TM-functions - async relay disabled\n");
		memset(&tmb, 0, sizeof(tm_api_t));
	}

	/* allocate workers array */
	workers = shm_malloc(num_workers * sizeof(*workers));
	if(workers == NULL) {
		LM_ERR("error in shm_malloc\n");
		return -1;
	}
	memset(workers, 0, num_workers * sizeof(*workers));

	register_procs(num_workers);

	/* add child to update local config framework structures */
	cfg_register_child(num_workers);

	return 0;
}
Exemple #30
0
int set_modem_arg(struct modem *mdm, char *arg, char *arg_end)
{
	int err, foo;

	if (*(arg+1)!='=') {
		LM_ERR("invalid parameter syntax near [=]\n");
		goto error;
	}
	switch (*arg)
	{
		case 'd':  /* device */
			memcpy(mdm->device,arg+2,arg_end-arg-2);
			mdm->device[arg_end-arg-2] = 0;
			break;
		case 'p':  /* pin */
			memcpy(mdm->pin,arg+2,arg_end-arg-2);
			mdm->pin[arg_end-arg-2] = 0;
			break;
		case 'm':  /* mode */
			if (!strncasecmp(arg+2,"OLD",3)
			&& arg_end-arg-2==3) {
				mdm->mode = MODE_OLD;
			} else if (!strncasecmp(arg+2,"DIGICOM",7)
			&& arg_end-arg-2==7) {
				mdm->mode = MODE_DIGICOM;
			} else if (!strncasecmp(arg+2,"ASCII",5)
			&& arg_end-arg-2==5) {
				mdm->mode = MODE_ASCII;
			} else if (!strncasecmp(arg+2,"NEW",3)
			&& arg_end-arg-2==3) {
				mdm->mode = MODE_NEW;
			} else {
				LM_ERR("invalid value \"%.*s\" for param [m]\n",
					(int)(arg_end-arg-2),arg+2);
				goto error;
			}
			break;
		case 'c':  /* sms center number */
			memcpy(mdm->smsc,arg+2,arg_end-arg-2);
			mdm->smsc[arg_end-arg-2] = 0;
			break;
		case 'r':  /* retry time */
			foo=str2s(arg+2,arg_end-arg-2,&err);
			if (err) {
				LM_ERR("failed to convert [r] arg to integer!\n");
				goto error;
			}
			mdm->retry = foo;
			break;
		case 'l':  /* looping interval */
			foo=str2s(arg+2,arg_end-arg-2,&err);
			if (err) {
				LM_ERR("failed to convert [l] arg to integer!\n");
				goto error;
			}
			mdm->looping_interval = foo;
			break;
		case 'b':  /* baudrate */
			foo=str2s(arg+2,arg_end-arg-2,&err);
			if (err) {
				LM_ERR("failed to convert [b] arg to integer!\n");
				goto error;
			}
			switch (foo) {
				case   300: foo=B300; break;
				case  1200: foo=B1200; break;
				case  2400: foo=B2400; break;
				case  9600: foo=B9600; break;
				case 19200: foo=B19200; break;
				case 38400: foo=B38400; break;
				case 57600: foo=B57600; break;
				default:
					LM_ERR("unsupported value %d for [b] arg!\n",foo);
					goto error;
			}
			mdm->baudrate = foo;
			break;
		case 's':  /* scan */
			foo=str2s(arg+2,arg_end-arg-2,&err);
			if (err) {
				LM_WARN("cannot convert [s] arg to integer!, assume default mode s=%d (SCAN)\n", 
					SMS_BODY_SCAN);
				foo = SMS_BODY_SCAN;
			}
			switch (foo) {
				case   SMS_BODY_SCAN: 
				case   SMS_BODY_SCAN_NO: 
				case   SMS_BODY_SCAN_MIX: 
					break;
				default:
					LM_WARN("unsupported value s=%d for [s] arg!, assume default mode s=%d (SCAN)\n",
						  foo,SMS_BODY_SCAN);
					foo = SMS_BODY_SCAN;
			}
			mdm->scan = foo;
			break;
		case 't':  /* to */
			memcpy(mdm->to,arg+2,arg_end-arg-2);
			mdm->to[arg_end-arg-2] = 0;
			break;
		default:
			LM_ERR("unknown param name [%c]\n",*arg);
			goto error;
	}

	return 1;
error:
	return -1;
}