Esempio n. 1
0
int add_credential( unsigned int type, void *val)
{
	struct uac_credential *crd;
	char *p;
	str foo;

	p = (char*)val;
	crd = 0;

	if (p==0 || *p==0)
		goto error;

	crd = (struct uac_credential*)pkg_malloc(sizeof(struct uac_credential));
	if (crd==0)
	{
		LM_ERR("no more pkg mem\n");
		goto error;
	}
	memset( crd, 0, sizeof(struct uac_credential));

	/*parse the user */
	while (*p && isspace((int)*p)) p++;
	foo.s = p;
	while (*p && *p!=':' && !isspace((int)*p)) p++;
	if (foo.s==p || *p==0)
		/* missing or empty user */
		goto parse_error;
	foo.len = p - foo.s;
	/* dulicate it */
	duplicate_str( crd->user, foo, error);

	/* parse the ':' separator */
	while (*p && isspace((int)*p)) p++;
	if (*p!=':')
		goto parse_error;
	p++;
	while (*p && isspace((int)*p)) p++;
	if (*p==0)
		goto parse_error;

	/*parse the realm */
	while (*p && isspace((int)*p)) p++;
	foo.s = p;
	while (*p && *p!=':' && !isspace((int)*p)) p++;
	if (foo.s==p || *p==0)
		/* missing or empty realm */
		goto parse_error;
	foo.len = p - foo.s;
	/* dulicate it */
	duplicate_str( crd->realm, foo, error);

	/* parse the ':' separator */
	while (*p && isspace((int)*p)) p++;
	if (*p!=':')
		goto parse_error;
	p++;
	while (*p && isspace((int)*p)) p++;
	if (*p==0)
		goto parse_error;

	/*parse the passwd */
	while (*p && isspace((int)*p)) p++;
	foo.s = p;
	while (*p && !isspace((int)*p)) p++;
	if (foo.s==p)
		/* missing or empty passwd */
		goto parse_error;
	foo.len = p - foo.s;
	/* dulicate it */
	duplicate_str( crd->passwd, foo, error);

	/* end of string */
	while (*p && isspace((int)*p)) p++;
	if (*p!=0)
		goto parse_error;

	/* link the new cred struct */
	crd->next = crd_list;
	crd_list = crd;

	pkg_free(val);
	return 0;
parse_error:
		LM_ERR("parse error in <%s> "
		"around %ld\n", (char*)val, (long)(p-(char*)val));
error:
	if (crd)
		free_credential(crd);
	return -1;
}
Esempio n. 2
0
int dlg_replace_contact(struct sip_msg* msg, struct dlg_cell* dlg)
{
//	str local_contact;
	struct lump* lump, *crt, *prev_crt =0, *a, *foo;
	int offset;
	int len,n;
	char *prefix=NULL,*suffix=NULL,*p,*p_init;
	int prefix_len,suffix_len;

	if(!msg->contact)
	{
		if(parse_headers(msg, HDR_CONTACT_F, 0)< 0)
		{
			LM_ERR("Failed to parse headers\n");
			return -1;
		}
		if(!msg->contact)
			return 0;
	}

	prefix_len = 5; /* <sip: */
	prefix = pkg_malloc(prefix_len);
	if (!prefix) {
		LM_ERR("no more pkg\n");
		goto error;
	}

	suffix_len = RR_DLG_PARAM_SIZE+1; /* > */
	suffix = pkg_malloc(suffix_len);
	if (!suffix) {
		LM_ERR("no more pkg\n");
		goto error;
	}

	memcpy(prefix,"<sip:",prefix_len);
	
	p_init = p = suffix;
	*p++ = ';';
	memcpy(p,"did",3);
	p+=3;
	*p++ = '=';

	n = RR_DLG_PARAM_SIZE - (p-p_init);
	if (int2reverse_hex( &p, &n, dlg->h_entry)==-1)
		return -1;

	*(p++) = DLG_SEPARATOR;

	n = RR_DLG_PARAM_SIZE - (p-p_init);
	if (int2reverse_hex( &p, &n, dlg->h_id)==-1)
		return -1;

	*p++ = '>';
	suffix_len = p - p_init;

	offset = msg->contact->body.s - msg->buf;
	len = msg->contact->body.len;

	for (crt = msg->add_rm;crt;) {
		if (crt->type == HDR_CONTACT_T && crt->op == LUMP_DEL &&
				crt->u.offset >= offset && crt->u.offset <= offset + len) {
			lump = crt;
			crt = crt->next;
			a=lump->before;
			while(a) {
				LM_DBG("before [%p], op=%d\n", a, a->op);
				if(a->op == LUMP_ADD)
					LM_DBG("value= %.*s\n", a->len, a->u.value);
				foo=a; a=a->before;
				if (!(foo->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM)))
					free_lump(foo);
				if (!(foo->flags&LUMPFLAG_SHMEM))
					pkg_free(foo);
			}

			a=lump->after;
			while(a) {
				LM_DBG("after [%p], op=%d\n", a, a->op);
				if(a->op == LUMP_ADD)
					LM_DBG("value= %.*s\n", a->len, a->u.value);
				foo=a; a=a->after;
				if (!(foo->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM)))
					free_lump(foo);
				if (!(foo->flags&LUMPFLAG_SHMEM))
					pkg_free(foo);
			}
			if(lump == msg->add_rm)
				msg->add_rm = lump->next;
			else
				prev_crt->next = lump->next;
			if (!(lump->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM)))
				free_lump(lump);
			if (!(lump->flags&LUMPFLAG_SHMEM))
				pkg_free(lump);
			continue;
		}
		prev_crt = crt;
		crt= crt->next;
	}

	if ((lump = del_lump(msg, msg->contact->body.s - msg->buf, msg->contact->body.len,HDR_CONTACT_T)) == 0) {
		LM_ERR("del_lump failed \n");
		goto error;
	}

	if ((lump = insert_new_lump_after(lump,prefix,prefix_len,HDR_CONTACT_T)) == 0) {
		LM_ERR("failed inserting '<sip:'\n");
		goto error;
	}

	if ((lump = insert_subst_lump_after(lump, SUBST_SND_ALL, HDR_CONTACT_T)) == 0) {
		LM_ERR("failed inserting SUBST_SND buf\n");
		goto error;
	}

	if ((lump = insert_new_lump_after(lump,suffix,suffix_len,HDR_CONTACT_T)) == 0) {
		LM_ERR("failed inserting '<sip:'\n");
		goto error;
	}
	
//	LM_DBG("Replaced contact with [%.*s]\n", local_contact.len, local_contact.s);

	return 0;
error:
	if (prefix) pkg_free(prefix);
	if (suffix) pkg_free(suffix);
	return -1;
}
Esempio n. 3
0
static int l_siplua_moduleFunc(lua_State *L)
{
  struct sipapi_object *o;
  const char *func;
  int n, nargs;
  cmd_export_t *exp_func_struct;
  action_elem_t elems[MAX_ACTION_ELEMS];
  const char *s, *msg;
  char *str;
  int i;
  struct action *act;
  int retval;

  o = luaL_checkudata(L, 1, "siplua.api");
  func = luaL_checkstring(L, 2);
  n = lua_gettop(L);
  nargs = n - 2;
  if (n - 1 > MAX_ACTION_ELEMS)
    return luaL_error(L, "function '%s' called with too many arguments [%d > %d]",
	       func, nargs, MAX_ACTION_ELEMS - 1);
  exp_func_struct = find_cmd_export_t((char *)func, nargs, 0);
  if (!exp_func_struct)
    {
      return luaL_error(L, "function '%s' called, but not available.");
    }
  elems[0].type = CMD_ST;
  elems[0].u.data = exp_func_struct;
  memset(&elems[1], '\0', nargs * sizeof(action_elem_t));
  for (i = 0; i < nargs; ++i)
    {
      s = lua_tostring(L, 3 + i);
      if (!s)
	{
	  siplua_moduleFunc_free(func, exp_func_struct, elems, nargs);
	  msg = lua_pushfstring(L, "%s expected, got %s",
				lua_typename(L, LUA_TSTRING), luaL_typename(L, 3 + i));
	  return luaL_argerror(L, 3 + i, msg);
	}
      str = pkg_malloc(strlen(s) + 1);
      if (!str)
	{
	  siplua_moduleFunc_free(func, exp_func_struct, elems, nargs);
	  return luaL_error(L, "Not enough memory");
	}
      strcpy(str, s);
      /* We should maybe try STR_ST and elems[].u.str.{s,len} */
      elems[i + 1].type = STRING_ST;
      elems[i + 1].u.data = str; /* elems[].u.string */
    }
  act = mk_action(MODULE_T, n - 2 + 1, elems, 0);
  if (!act)
    {
      siplua_moduleFunc_free(func, exp_func_struct, elems, nargs);
      return luaL_error(L, "action structure could not be created. Error.");
    }
/*   siplua_log(L_DBG, "fixup/%p free_fixup/%p", */
/* 	     exp_func_struct->fixup, */
/* 	     exp_func_struct->free_fixup); */
  if (exp_func_struct->fixup)
    {
      if (!siplua_unsafemodfnc && !exp_func_struct->free_fixup)
	{
	  siplua_moduleFunc_free(func, exp_func_struct, act->elem, nargs);
	  return luaL_error(L, "Module function '%s' is unsafe. Call is refused.\n", func);
	}
      if (nargs == 0)
	{
	  retval = exp_func_struct->fixup(0, 0);
	  if (retval < 0)
	    {
	      siplua_moduleFunc_free(func, exp_func_struct, act->elem, nargs);
	      return luaL_error(L, "Error in fixup (0)\n");
	    }
	}
      for (i = 0; i < nargs; ++i)
	{
	  retval = exp_func_struct->fixup(&act->elem[i + 1].u.data, i + 1);
	  if (retval < 0)
	    {
	      siplua_moduleFunc_free(func, exp_func_struct, act->elem, nargs);
	      return luaL_error(L, "Error in fixup (%d)\n", i + 1);
	    }
	  act->elem[i + 1].type = MODFIXUP_ST;
	}
    }
  retval = do_action(act, o->msg);
  siplua_moduleFunc_free(func, exp_func_struct, act->elem, nargs);
  pkg_free(act);
  lua_pushinteger(L, retval);
  return 1;
}
Esempio n. 4
0
/*
 * Convert a row from result into db API representation
 */
int convert_row(db_con_t* _h, db_res_t* _res, db_row_t* _r)
{
	int i;
	if ((!_h) || (!_r) || (!_res)) 
	{
#ifdef DBT_EXTRA_DEBUG
		LOG(L_ERR, "DBT:convert_row: Invalid parameter value\n");
#endif
		return -1;
	}

	ROW_VALUES(_r) = (db_val_t*)pkg_malloc(sizeof(db_val_t) * RES_COL_N(_res));
	ROW_N(_r) = RES_COL_N(_res);
	if (!ROW_VALUES(_r)) 
	{
		LOG(L_ERR, "DBT:convert_row: No memory left\n");
		return -1;
	}

	for(i = 0; i < RES_COL_N(_res); i++) 
	{
		(ROW_VALUES(_r)[i]).nul = DBT_CON_ROW(_h)->fields[i].nul;
		switch(RES_TYPES(_res)[i])
		{
			case DB_INT:
				VAL_INT(&(ROW_VALUES(_r)[i])) = 
						DBT_CON_ROW(_h)->fields[i].val.int_val;
				VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_INT;
			break;

			case DB_DOUBLE:
				VAL_DOUBLE(&(ROW_VALUES(_r)[i])) = 
						DBT_CON_ROW(_h)->fields[i].val.double_val;
				VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_DOUBLE;
			break;

			case DB_STRING:
				VAL_STR(&(ROW_VALUES(_r)[i])).s = 
						DBT_CON_ROW(_h)->fields[i].val.str_val.s;
				VAL_STR(&(ROW_VALUES(_r)[i])).len =
						DBT_CON_ROW(_h)->fields[i].val.str_val.len;
				VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_STR;
			break;

			case DB_STR:
				VAL_STR(&(ROW_VALUES(_r)[i])).s = 
						DBT_CON_ROW(_h)->fields[i].val.str_val.s;
				VAL_STR(&(ROW_VALUES(_r)[i])).len =
						DBT_CON_ROW(_h)->fields[i].val.str_val.len;
				VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_STR;
			break;

			case DB_DATETIME:
				VAL_INT(&(ROW_VALUES(_r)[i])) = 
						DBT_CON_ROW(_h)->fields[i].val.int_val;
				VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_INT;
			break;

			case DB_BLOB:
				VAL_STR(&(ROW_VALUES(_r)[i])).s =
						DBT_CON_ROW(_h)->fields[i].val.str_val.s;
				VAL_STR(&(ROW_VALUES(_r)[i])).len =
						DBT_CON_ROW(_h)->fields[i].val.str_val.len;
				VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_STR;
			break;

			case DB_BITMAP:
				VAL_INT(&(ROW_VALUES(_r)[i])) =
					DBT_CON_ROW(_h)->fields[i].val.bitmap_val;
				VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_INT;
			break;
		}
	}
	return 0;
}
Esempio n. 5
0
/*! \brief Convert the file content into regular expresions and store them in pcres */
static int load_pcres(int action)
{
	int i, j;
	FILE *f;
	char line[FILE_MAX_LINE];
	char **patterns = NULL;
	pcre *pcre_tmp = NULL;
	size_t pcre_size;
	int pcre_rc;
	const char *pcre_error;
	int pcre_erroffset;
	int num_pcres_tmp = 0;
	pcre **pcres_tmp = NULL;

	/* Get the lock */
	lock_get(reload_lock);

	if (!(f = fopen(file, "r"))) {
		LM_ERR("could not open file '%s'\n", file);
		goto err;
	}

	/* Array containing each pattern in the file */
	if ((patterns = pkg_malloc(sizeof(char*) * max_groups)) == 0) {
		LM_ERR("no more memory for patterns\n");
		fclose(f);
		goto err;
	}
	memset(patterns, 0, sizeof(char*) * max_groups);

	for (i=0; i<max_groups; i++) {
		if ((patterns[i] = pkg_malloc(sizeof(char) * group_max_size)) == 0) {
			LM_ERR("no more memory for patterns[%d]\n", i);
			fclose(f);
			goto err;
		}
		memset(patterns[i], '\0', group_max_size);
	}

	/* Read the file and extract the patterns */
	memset(line, '\0', FILE_MAX_LINE);
	i = -1;
	while (fgets(line, FILE_MAX_LINE, f) != NULL) {

		/* Ignore comments and lines starting by space, tab, CR, LF */
		if(isspace(line[0]) || line[0]=='#') {
			memset(line, '\0', FILE_MAX_LINE);
			continue;
		}

		/* First group */
		if (i == -1 && line[0] != '[') {
			LM_ERR("first group must be initialized with [0] before any regular expression\n");
			fclose(f);
			goto err;
		}

		/* New group */
		if (line[0] == '[') {
			i++;
			/* Check if there are more patterns than the max value */
			if (i >= max_groups) {
				LM_ERR("max patterns exceeded\n");
				fclose(f);
				goto err;
			}
			/* Start the regular expression with '(' */
			patterns[i][0] = '(';
			memset(line, '\0', FILE_MAX_LINE);
			continue;
		}

		/* Check if the patter size is too big (aprox) */
		if (strlen(patterns[i]) + strlen(line) >= group_max_size - 2) {
			LM_ERR("pattern max file exceeded\n");
			fclose(f);
			goto err;
		}

		/* Append ')' at the end of the line */
		if (line[strlen(line) - 1] == '\n') {
			line[strlen(line)] = line[strlen(line) - 1];
			line[strlen(line) - 2] = ')';
		} else {
			/* This is the last char in the file and it's not \n */
			line[strlen(line)] = ')';
		}

		/* Append '(' at the beginning of the line */
		memcpy(patterns[i]+strlen(patterns[i]), "(", 1);

		/* Append the line to the current pattern */
		memcpy(patterns[i]+strlen(patterns[i]), line, strlen(line));

		memset(line, '\0', FILE_MAX_LINE);
	}
	num_pcres_tmp = i + 1;

	fclose(f);

	if(num_pcres_tmp==0) {
		LM_ERR("no expressions in the file\n");
		goto err;
	}

	/* Fix the patterns */
	for (i=0; i < num_pcres_tmp; i++) {

		/* Convert empty groups in unmatcheable regular expression ^$ */
		if (strlen(patterns[i]) == 1) {
			patterns[i][0] = '^';
			patterns[i][1] = '$';
			patterns[i][2] = '\0';
			continue;
		}

		/* Delete possible '\n' at the end of the pattern */
		if (patterns[i][strlen(patterns[i])-1] == '\n') {
			patterns[i][strlen(patterns[i])-1] = '\0';
		}

		/* Replace '\n' with '|' (except at the end of the pattern) */
		for (j=0; j < strlen(patterns[i]); j++) {
			if (patterns[i][j] == '\n' && j != strlen(patterns[i])-1) {
				patterns[i][j] = '|';
			}
		}

		/* Add ')' at the end of the pattern */
		patterns[i][strlen(patterns[i])] = ')';
	}

	/* Log the group patterns */
	LM_INFO("num groups = %d\n", num_pcres_tmp);
	for (i=0; i < num_pcres_tmp; i++) {
		LM_INFO("<group[%d]>%s</group[%d]> (size = %i)\n", i, patterns[i], i, (int)strlen(patterns[i]));
	}

	/* Temporal pointer of pcres */
	if ((pcres_tmp = pkg_malloc(sizeof(pcre *) * num_pcres_tmp)) == 0) {
		LM_ERR("no more memory for pcres_tmp\n");
		goto err;
	}
	for (i=0; i<num_pcres_tmp; i++) {
		pcres_tmp[i] = NULL;
	}

	/* Compile the patters */
	for (i=0; i<num_pcres_tmp; i++) {

		pcre_tmp = pcre_compile(patterns[i], pcre_options, &pcre_error, &pcre_erroffset, NULL);
		if (pcre_tmp == NULL) {
			LM_ERR("pcre_tmp compilation of '%s' failed at offset %d: %s\n", patterns[i], pcre_erroffset, pcre_error);
			goto err;
		}
		pcre_rc = pcre_fullinfo(pcre_tmp, NULL, PCRE_INFO_SIZE, &pcre_size);
		if (pcre_rc) {
			printf("pcre_fullinfo on compiled pattern[%i] yielded error: %d\n", i, pcre_rc);
			goto err;
		}

		if ((pcres_tmp[i] = pkg_malloc(pcre_size)) == 0) {
			LM_ERR("no more memory for pcres_tmp[%i]\n", i);
			goto err;
		}

		memcpy(pcres_tmp[i], pcre_tmp, pcre_size);
		pcre_free(pcre_tmp);
		pkg_free(patterns[i]);
		patterns[i] = NULL;
	}

	/* Copy to shared memory */
	if (action == RELOAD) {
		for(i=0; i<*num_pcres; i++) {  /* Use the previous num_pcres value */
			if (pcres[i]) {
				shm_free(pcres[i]);
			}
		}
		shm_free(pcres);
	}
	if ((pcres = shm_malloc(sizeof(pcre *) * num_pcres_tmp)) == 0) {
		LM_ERR("no more memory for pcres\n");
		goto err;
	}
	for (i=0; i<num_pcres_tmp; i++) {
		pcres[i] = NULL;
	}
	for (i=0; i<num_pcres_tmp; i++) {
		pcre_rc = pcre_fullinfo(pcres_tmp[i], NULL, PCRE_INFO_SIZE, &pcre_size);
		if ((pcres[i] = shm_malloc(pcre_size)) == 0) {
			LM_ERR("no more memory for pcres[%i]\n", i);
			goto err;
		}
		memcpy(pcres[i], pcres_tmp[i], pcre_size);
	}
	*num_pcres = num_pcres_tmp;
	*pcres_addr = pcres;

	/* Free used memory */
	for (i=0; i<num_pcres_tmp; i++) {
		pkg_free(pcres_tmp[i]);
	}
	pkg_free(pcres_tmp);
	pkg_free(patterns);
	lock_release(reload_lock);

	return 0;

err:
	if (patterns) {
		for(i=0; i<max_groups; i++) {
			if (patterns[i]) {
				pkg_free(patterns[i]);
			}
		}
		pkg_free(patterns);
	}
	if (pcres_tmp) {
		for (i=0; i<num_pcres_tmp; i++) {
			if (pcres_tmp[i]) {
				pkg_free(pcres_tmp[i]);
			}
		}
		pkg_free(pcres_tmp);
	}
	if (reload_lock) {
		lock_release(reload_lock);
	}
	if (action == START) {
		free_shared_memory();
	}
	return -1;
}
Esempio n. 6
0
int dbt_result_extract_fields(dbt_table_p _dtp, dbt_row_p _drp,
				int* _lres, dbt_result_p _dres)
{
	dbt_row_p _rp=NULL;
	int i, n;
	
	if(!_dtp || !_drp || !_dres || _dres->nrcols<=0)	
		return -1;
	
	_rp = dbt_result_new_row(_dres);
	if(!_rp)
		return -1;

	for(i=0; i<_dres->nrcols; i++)
	{
		n = (_lres)?_lres[i]:i;
		if(dbt_is_neq_type(_dres->colv[i].type, _dtp->colv[n]->type))
		{
			LM_DBG("wrong types!\n");
			goto clean;
		}
		_rp->fields[i].nul = _drp->fields[n].nul;
		if(_rp->fields[i].nul)
		{
			memset(&(_rp->fields[i].val), 0, sizeof(_rp->fields[i].val));
			continue;
		}
		
		switch(_dres->colv[i].type)
		{
			case DB1_INT:
			case DB1_DATETIME:
			case DB1_BITMAP:
				_rp->fields[i].type = _dres->colv[i].type;
				_rp->fields[i].val.int_val = _drp->fields[n].val.int_val;
			break;
			case DB1_DOUBLE:
				_rp->fields[i].type = DB1_DOUBLE;
				_rp->fields[i].val.double_val=_drp->fields[n].val.double_val;
			break;
			case DB1_STRING:
			case DB1_STR:
			case DB1_BLOB:
				_rp->fields[i].type = _dres->colv[i].type;
				_rp->fields[i].val.str_val.len =
						_drp->fields[n].val.str_val.len;
				_rp->fields[i].val.str_val.s =(char*)pkg_malloc(sizeof(char)*
						(_drp->fields[n].val.str_val.len+1));
				if(!_rp->fields[i].val.str_val.s)
					goto clean;
				memcpy(_rp->fields[i].val.str_val.s,
						_drp->fields[n].val.str_val.s,
						_rp->fields[i].val.str_val.len);
				_rp->fields[i].val.str_val.s[_rp->fields[i].val.str_val.len]=0;
			break;
			default:
				goto clean;
		}
	}

	if(_dres->rows)
		(_dres->rows)->prev = _rp;
	_rp->next = _dres->rows;
	_dres->rows = _rp;
	_dres->nrrows++;

	return 0;

clean:
	LM_DBG("make clean!\n");
	while(i>=0)
	{
		if((_rp->fields[i].type == DB1_STRING
					|| _rp->fields[i].type == DB1_STR
					|| _rp->fields[i].type == DB1_BLOB)
				&& !_rp->fields[i].nul
				&& _rp->fields[i].val.str_val.s)
			pkg_free(_rp->fields[i].val.str_val.s);
				
		i--;
	}
	pkg_free(_rp->fields);
	pkg_free(_rp);

	return -1;
}
Esempio n. 7
0
int send_sip_msg_request(str *to, str *from_user, str *body)
{
	str msg_type = STR_STATIC_INIT("MESSAGE");
	str from;
	str hdrs;
	int foo;
	char *p;
	uac_req_t uac_r;

	from.s = hdrs.s = 0;
	from.len = hdrs.len = 0;

	/* From header */
	from.len = 6 /*"<sip:+"*/ +  from_user->len/*user*/ + 1/*"@"*/
		+ domain.len /*host*/ + 1 /*">"*/ ;
	from.s = (char*)pkg_malloc(from.len);
	if (!from.s)
		goto error;
	p=from.s;
	append_str(p,"<sip:+",6);
	append_str(p,from_user->s,from_user->len);
	*(p++)='@';
	append_str(p,domain.s,domain.len);
	*(p++)='>';

	/* hdrs = Contact header + Content-type */
	/* length */
	hdrs.len = CONTENT_TYPE_HDR_LEN + CRLF_LEN;
	if (use_contact)
		hdrs.len += 15 /*"Contact: <sip:+"*/ + from_user->len/*user*/ +
			1/*"@"*/ + domain.len/*host*/ + 1 /*">"*/ + CRLF_LEN;
	hdrs.s = (char*)pkg_malloc(hdrs.len);
	if (!hdrs.s)
		goto error;
	p=hdrs.s;
	append_str(p,CONTENT_TYPE_HDR,CONTENT_TYPE_HDR_LEN);
	append_str(p,CRLF,CRLF_LEN);
	if (use_contact) {
		append_str(p,"Contact: <sip:+",15);
		append_str(p,from_user->s,from_user->len);
		*(p++)='@';
		append_str(p,domain.s,domain.len);
		append_str(p,">"CRLF,1+CRLF_LEN);
	}

	/* sending the request */
	set_uac_req(&uac_r,
			&msg_type,	/* request type */
			&hdrs,		/* Additional headers including CRLF */
			body,		/* Message body */
			0,		/* dialog structure */
			0,		/* callback flags */
			0,		/* Callback function */
			0		/* Callback parameter */
		);
	
	foo = tmb.t_request(&uac_r,
			0,	/* Request-URI */
			to,	/* To */
			&from,	/* From */
			0	/* next hop */
		);

	if (from.s) pkg_free(from.s);
	if (hdrs.s) pkg_free(hdrs.s);
	return foo;
error:
	LM_ERR("no free pkg memory!\n");
	if (from.s) pkg_free(from.s);
	if (hdrs.s) pkg_free(hdrs.s);
	return -1;
}
Esempio n. 8
0
static int alter_mediaip(struct sip_msg *msg, str *body, str *oldip, int oldpf,
  			str *newip, int newpf, int preserve)
{
	char *buf;
	int offset;
	struct lump* anchor;
	str omip, nip, oip;

	/* check that updating mediaip is really necessary */
	if (oldpf == newpf && isnulladdr(oldip, oldpf))
		return 0;
	if (newip->len == oldip->len && memcmp(newip->s, oldip->s, newip->len) == 0)
		return 0;

	/*
	 * Since rewriting the same info twice will mess SDP up,
	 * apply simple anti foot shooting measure - put flag on
	 * messages that have been altered and check it when
	 * another request comes.
	 */
#if 0
	/* disabled:
	 *  - alter_mediaip is called twice if 2 c= lines are present
	 *    in the sdp (and we want to allow it)
	 *  - the message flags are propagated in the on_reply_route
	 *  => if we set the flags for the request they will be seen for the
	 *    reply too, but we don't want that
	 *  --andrei
	 */
	if (msg->msg_flags & FL_SDP_IP_AFS) {
		LOG(L_ERR, "ERROR: alter_mediaip: you can't rewrite the same "
		  "SDP twice, check your config!\n");
		return -1;
	}
#endif

	if (preserve != 0) {
		anchor = anchor_lump(msg, body->s + body->len - msg->buf  , 0, 0);
		if (anchor == NULL) 
		{
			LOG(L_ERR, "ERROR: alter_mediaip: anchor_lump failed\n");
			return -1;
		}
		if (oldpf == AF_INET6) 
		{
			omip.s = AOLDMEDIP6 ;
			omip.len = AOLDMEDIP6_LEN;
		} else {
			omip.s = AOLDMEDIP;
			omip.len = AOLDMEDIP_LEN;
		}
		buf = pkg_malloc(omip.len + oldip->len + CRLF_LEN);
		if (buf == NULL) 
		{
			LOG(L_ERR, "ERROR: alter_mediaip: out of memory\n");
			return -1;
		}
		memcpy(buf, omip.s, omip.len);
		memcpy(buf + omip.len, oldip->s, oldip->len);
		memcpy(buf + omip.len + oldip->len, CRLF, CRLF_LEN);
		if (insert_new_lump_after(anchor, buf,
		    omip.len + oldip->len + CRLF_LEN, 0) == NULL) {
			LOG(L_ERR, "ERROR: alter_mediaip: insert_new_lump_after failed\n");
			pkg_free(buf);
			return -1;
		}
	}

	if (oldpf == newpf) {
		nip.len = newip->len;
		nip.s = pkg_malloc(nip.len);
		if (nip.s == NULL) {
			LOG(L_ERR, "ERROR: alter_mediaip: out of memory\n");
			return -1;
		}
		memcpy(nip.s, newip->s, newip->len);
	} else {
		nip.len = newip->len + 2;
		nip.s = pkg_malloc(nip.len);
		if (nip.s == NULL) {
			LOG(L_ERR, "ERROR: alter_mediaip: out of memory\n");
			return -1;
		}
		memcpy(nip.s + 2, newip->s, newip->len);
		nip.s[0] = (newpf == AF_INET6) ? '6' : '4';
		nip.s[1] = ' ';
	}

	oip = *oldip;
	if (oldpf != newpf) {
		do {
			oip.s--;
			oip.len++;
		} while (*oip.s != '6' && *oip.s != '4');
	}
	offset = oip.s - msg->buf;
	anchor = del_lump(msg, offset, oip.len, 0);
	if (anchor == NULL) {
		LOG(L_ERR, "ERROR: alter_mediaip: del_lump failed\n");
		pkg_free(nip.s);
		return -1;
	}

#if 0
	msg->msg_flags |= FL_SDP_IP_AFS;
#endif

	if (insert_new_lump_after(anchor, nip.s, nip.len, 0) == 0) {
		LOG(L_ERR, "ERROR: alter_mediaip: insert_new_lump_after failed\n");
		pkg_free(nip.s);
		return -1;
	}
	return 0;
}
Esempio n. 9
0
static int alter_mediaport(struct sip_msg *msg, str *body, str *oldport, str *newport,
  int preserve)
{
	char *buf;
	int offset;
	struct lump* anchor;

	/* check that updating mediaport is really necessary */
	if (newport->len == oldport->len &&
	    memcmp(newport->s, oldport->s, newport->len) == 0)
		return 0;

	/*
	 * Since rewriting the same info twice will mess SDP up,
	 * apply simple anti foot shooting measure - put flag on
	 * messages that have been altered and check it when
	 * another request comes.
	 */
#if 0
	/* disabled: - it propagates to the reply and we don't want this
	 *  -- andrei */
	if (msg->msg_flags & FL_SDP_PORT_AFS) {
		LOG(L_ERR, "ERROR: alter_mediaip: you can't rewrite the same "
		  "SDP twice, check your config!\n");
		return -1;
	}
#endif

	if (preserve != 0) {
		anchor = anchor_lump(msg, body->s + body->len - msg->buf, 0, 0);
		if (anchor == NULL) {
			LOG(L_ERR, "ERROR: alter_mediaport: anchor_lump failed\n");
			return -1;
		}
		buf = pkg_malloc(AOLDMEDPRT_LEN + oldport->len + CRLF_LEN);
		if (buf == NULL) {
			LOG(L_ERR, "ERROR: alter_mediaport: out of memory\n");
			return -1;
		}
		memcpy(buf, AOLDMEDPRT, AOLDMEDPRT_LEN);
		memcpy(buf + AOLDMEDPRT_LEN, oldport->s, oldport->len);
		memcpy(buf + AOLDMEDPRT_LEN + oldport->len, CRLF, CRLF_LEN);
		if (insert_new_lump_after(anchor, buf,
		    AOLDMEDPRT_LEN + oldport->len + CRLF_LEN, 0) == NULL) {
			LOG(L_ERR, "ERROR: alter_mediaport: insert_new_lump_after failed\n");
			pkg_free(buf);
			return -1;
		}
	}

	buf = pkg_malloc(newport->len);
	if (buf == NULL) {
		LOG(L_ERR, "ERROR: alter_mediaport: out of memory\n");
		return -1;
	}
	offset = oldport->s - msg->buf;
	anchor = del_lump(msg, offset, oldport->len, 0);
	if (anchor == NULL) {
		LOG(L_ERR, "ERROR: alter_mediaport: del_lump failed\n");
		pkg_free(buf);
		return -1;
	}
	memcpy(buf, newport->s, newport->len);
	if (insert_new_lump_after(anchor, buf, newport->len, 0) == 0) {
		LOG(L_ERR, "ERROR: alter_mediaport: insert_new_lump_after failed\n");
		pkg_free(buf);
		return -1;
	}

#if 0
	msg->msg_flags |= FL_SDP_PORT_AFS;
#endif
	return 0;
}
static int
UseMediaProxy(struct sip_msg* msg, char* str1, char* str2)
{
    str sdp, sessionIP, callId, fromDomain, toDomain, userAgent, tokens[64];
    str fromAddr, toAddr, fromTag, toTag;
    char *clientIP, *ptr, *command, *result, *agent, *fromType, *toType, *info;
    int streamCount, i, port, count, portCount, cmdlen, infolen, success, type;
    StreamInfo streams[64], stream;
    Bool request;

    if (msg->first_line.type == SIP_REQUEST) {
        if (msg->first_line.u.request.method_value == METHOD_INVITE)
            type = MSG_INVITE;
        else if (msg->first_line.u.request.method_value == METHOD_ACK)
            type = MSG_ACK;
        else
            type = MSG_UNKNOWN;
    } else if (msg->first_line.type == SIP_REPLY) {
        type = MSG_REPLY;
    } else {
        type = MSG_UNKNOWN;
    }

    if (type==MSG_INVITE || type==MSG_ACK) {
        request = True;
    } else if (type==MSG_REPLY) {
        request = False;
    } else {
        return -1;
    }

    if (!getCallId(msg, &callId)) {
        LOG(L_ERR, "error: use_media_proxy(): can't get Call-Id\n");
        return -1;
    }

    success = getSDPMessage(msg, &sdp);
    if (success==0 && type==MSG_ACK) {
        return 1; // nothing to do. it's ok for ACK to not have a SDP body
    } else if (success <= 0) {
        LOG(L_ERR, "error: use_media_proxy(): failed to get the SDP message\n");
        return -1;
    }

    if (!getSessionLevelMediaIP(&sdp, &sessionIP)) {
        LOG(L_ERR, "error: use_media_proxy(): error parsing the SDP message\n");
        return -1;
    }

    streamCount = getMediaStreams(&sdp, &sessionIP, streams, 64);
    if (streamCount == -1) {
        LOG(L_ERR, "error: use_media_proxy(): can't extract media streams "
            "from the SDP message\n");
        return -1;
    }

    if (streamCount == 0) {
        // there are no media streams. we have nothing to do.
        return 1;
    }

    fromDomain = getFromDomain(&fromType, msg);
    fromAddr   = getFromAddress(msg);
    toAddr     = getToAddress(msg);
    fromTag    = getFromTag(msg);
    toTag      = getToTag(msg);
    userAgent  = getUserAgent(msg);
    if (request) {
        toDomain = getDestinationDomain(&toType, msg); // call only for requests
    } else {
        toDomain = getToDomain(&toType, msg);
    }

    clientIP = ip_addr2a(&msg->rcv.src_ip);

    infolen = fromAddr.len + toAddr.len + fromTag.len + toTag.len + 64;

    cmdlen = callId.len + strlen(clientIP) + fromDomain.len + toDomain.len +
        userAgent.len*3 + infolen + 128;

    for (i=0; i<streamCount; i++) {
        stream = streams[i];
        cmdlen += stream.ip.len + stream.port.len + stream.type.len + 4;
    }

    command = pkg_malloc(cmdlen);
    if (!command) {
        LOG(L_ERR, "error: use_media_proxy(): out of memory\n");
        return -1;
    }

    if (request)
        count = sprintf(command, "request %.*s", callId.len, callId.s);
    else
        count = sprintf(command, "lookup %.*s", callId.len, callId.s);

    for (i=0, ptr=command+count; i<streamCount; i++) {
        char c = (i==0 ? ' ' : ',');
        count = sprintf(ptr, "%c%.*s:%.*s:%.*s", c,
                        streams[i].ip.len, streams[i].ip.s,
                        streams[i].port.len, streams[i].port.s,
                        streams[i].type.len, streams[i].type.s);
        ptr += count;
    }

    agent = encodeQuopri(userAgent);
    if (!agent) {
        LOG(L_ERR, "error: use_media_proxy(): out of memory\n");
        pkg_free(command);
        return -1;
    }

    info = pkg_malloc(infolen);
    if (!info) {
        LOG(L_ERR, "error: use_media_proxy(): out of memory\n");
        pkg_free(command);
        pkg_free(agent);
        return -1;
    }

    sprintf(info, "from:%.*s,to:%.*s,fromtag:%.*s,totag:%.*s",
            fromAddr.len, fromAddr.s, toAddr.len, toAddr.s,
            fromTag.len, fromTag.s, toTag.len, toTag.s);
    if (isRTPAsymmetric(userAgent)) {
        strcat(info, ",asymmetric");
    }

    snprintf(ptr, command + cmdlen - ptr, " %s %.*s %s %.*s %s %s info=%s\n",
             clientIP, fromDomain.len, fromDomain.s, fromType,
             toDomain.len, toDomain.s, toType, agent, info);

    pkg_free(info);
    pkg_free(agent);

    result = sendMediaproxyCommand(command);

    pkg_free(command);

    if (result == NULL)
        return -1;

    count = getTokens(result, tokens, sizeof(tokens)/sizeof(str));

    if (count == 0) {
        LOG(L_ERR, "error: use_media_proxy(): empty response from mediaproxy\n");
        return -1;
    } else if (count<streamCount+1) {
        if (request) {
            LOG(L_ERR, "error: use_media_proxy(): insufficient ports returned "
                "from mediaproxy: got %d, expected %d\n", count-1, streamCount);
            return -1;
        } else {
            LOG(L_WARN, "warning: use_media_proxy(): broken client. Called UA "
                "added extra media stream(s) in the OK reply\n");
        }
    }

    if (sessionIP.s && !isAnyAddress(sessionIP)) {
        success = replaceElement(msg, &sessionIP, &tokens[0]);
        if (!success) {
            LOG(L_ERR, "error: use_media_proxy(): failed to replace "
                "session-level media IP in SDP body\n");
            return -1;
        }
    }

    portCount = min(count-1, streamCount);

    for (i=0; i<portCount; i++) {
        // check. is this really necessary?
        port = strtoint(&tokens[i+1]);
        if (port <= 0 || port > 65535) {
            LOG(L_ERR, "error: use_media_proxy(): invalid port returned "
                "by mediaproxy: %.*s\n", tokens[i+1].len, tokens[i+1].s);
            //return -1;
            continue;
        }

        if (streams[i].port.len!=1 || streams[i].port.s[0]!='0') {
            success = replaceElement(msg, &(streams[i].port), &tokens[i+1]);
            if (!success) {
                LOG(L_ERR, "error: use_media_proxy(): failed to replace "
                    "port in media stream nr. %d\n", i+1);
                return -1;
            }
        }

        if (streams[i].localIP && !isAnyAddress(streams[i].ip)) {
            success = replaceElement(msg, &(streams[i].ip), &tokens[0]);
            if (!success) {
                LOG(L_ERR, "error: use_media_proxy(): failed to replace "
                    "IP address in media stream nr. %d\n", i+1);
                return -1;
            }
        }
    }

    return 1;
}
Esempio n. 11
0
/* initialization of rtp_proxy module */
int rtpproxy_init()
{

	memset(&rtpp_list, 0, sizeof(rtpp_list));
	rtpp_node_count = 0;
	if (rtpproxy_enable) {
		/* Make rtp proxies list. */
		char *p, *p1, *p2, *plim;

		p = rtpproxy_sock;
		plim = p + strlen(p);
		for(;;) {
			struct rtpp_node *pnode;
			int weight;

			weight = 1;
			while (*p && isspace(*p))
				++p;
			if (p >= plim)
				break;
			p1 = p;
			while (*p && !isspace(*p))
				++p;
			if (p <= p1)
				break; /* may happen??? */
			/* Have weight specified? If yes, scan it */
			p2 = memchr(p1, '=', p - p1);
	

			if (p2 != NULL) {
				weight = strtoul(p2 + 1, NULL, 10);
			} else {
				p2 = p;
			}
			pnode = pkg_malloc(sizeof(struct rtpp_node));
			if (pnode == NULL) {
				LOG(L_ERR, "nathelper: Can't allocate memory\n");
				return -1;
			}
			memset(pnode, 0, sizeof(*pnode));
			pnode->rn_recheck_ticks = 0;
			pnode->rn_weight = weight;
			pnode->rn_umode = 0;
			pnode->rn_fd = -1;
			pnode->rn_disabled = 0;
			pnode->rn_url = pkg_malloc(p2 - p1 + 1);
	
			LOG(L_INFO,"INFO:"M_NAME"node is created\n") ;

		

			if (pnode->rn_url == NULL) {
				LOG(L_ERR, "nathelper: Can't allocate memory\n");
				return -1;
			}
	
			/*LOG(L_CRIT,"started to add the pnode to rtpp list\n") ; */

			/* adding proxy nodes to the list */
			memmove(pnode->rn_url, p1, p2 - p1);
			pnode->rn_url[p2 - p1] = 0;
			if (rtpp_list.rn_first == NULL) {
				rtpp_list.rn_first = pnode;
			} else {
				rtpp_list.rn_last->rn_next = pnode;
			}
			rtpp_list.rn_last = pnode;
			++rtpp_node_count;
			
			/* Leave only address in rn_address */
			pnode->rn_address = pnode->rn_url;
	

			if (strncmp(pnode->rn_address, "udp:", 4) == 0) {
				pnode->rn_umode = 1;
				pnode->rn_address += 4;
			} else if (strncmp(pnode->rn_address, "udp6:", 5) == 0) {
				pnode->rn_umode = 6;
				pnode->rn_address += 5;
			} else if (strncmp(pnode->rn_address, "unix:", 5) == 0) {
				pnode->rn_umode = 0;
				pnode->rn_address += 5;
			}	
		 /* 	LOG(L_CRIT,"is getting out of the rtp block\n") ;*/
		}
	}
	return 1;
}
// Check if the requested asymmetrics file has changed and reload it if needed
static void
checkAsymmetricFile(AsymmetricClients *aptr)
{
    char buf[512], errbuf[256], *which;
    regex_t *re, **regs;
    int i, size, code;
    Bool firstTime = False;
    struct stat statbuf;
    FILE *file;
    str line;

    if (stat(aptr->file, &statbuf) < 0)
        return; // ignore missing file

    if (statbuf.st_mtime <= aptr->timestamp)
        return; // not changed

    // now we have work to do

    which = (aptr == &sipAsymmetrics ? "SIP" : "RTP");

    if (!aptr->clients) {
        // if we are here the first time allocate memory to hold the regexps

        // initial size of array
        // (hopefully not reached so we won't need to realloc)
        size = 32;
        aptr->clients = (regex_t**)pkg_malloc(size*sizeof(regex_t**));
        if (!aptr->clients) {
            LOG(L_WARN, "warning: mediaproxy/checkAsymmetricFile() cannot "
                "allocate memory for the %s asymmetric client list. "
                "%s asymmetric clients will not be handled properly.\n",
                which, which);
            return; // ignore as it is not fatal
        }
        aptr->size  = size;
        aptr->count = 0;
        firstTime = True;
    } else {
        // else clean old stuff
        for (i=0; i<aptr->count; i++) {
            regfree(aptr->clients[i]);
            pkg_free(aptr->clients[i]);
            aptr->clients[i] = NULL;
        }
        aptr->count = 0;
    }

    // read new
    file = fopen(aptr->file, "r");
    i = 0; // this will count on which line are we in the file
    while (!feof(file)) {
        if (!fgets(buf, 512, file))
            break;
        i++;

        line.s = buf;
        line.len = strlen(buf);
        trim(&line);
        if (line.len == 0 || line.s[0] == '#')
            continue; // comment or empty line. ignore
        line.s[line.len] = 0;

        re = (regex_t*)pkg_malloc(sizeof(regex_t));
        if (!re) {
            LOG(L_WARN, "warning: mediaproxy/checkAsymmetricFile(): "
                "cannot allocate memory for all the %s asymmetric "
                "clients listed in file. Some of them will not be "
                "handled properly.\n", which);
            break;
        }
        code = regcomp(re, line.s, REG_EXTENDED|REG_ICASE|REG_NOSUB);
        if (code == 0) {
            if (aptr->count+1 > aptr->size) {
                size = aptr->size * 2;
                regs = aptr->clients;
                regs = (regex_t**)pkg_realloc(regs, size*sizeof(regex_t**));
                if (!regs) {
                    LOG(L_WARN, "warning: mediaproxy/checkAsymmetricFile(): "
                        "cannot allocate memory for all the %s asymmetric "
                        "clients listed in file. Some of them will not be "
                        "handled properly.\n", which);
                    break;
                }
                aptr->clients = regs;
                aptr->size = size;
            }
            aptr->clients[aptr->count] = re;
            aptr->count++;
        } else {
            regerror(code, re, errbuf, 256);
            LOG(L_WARN, "warning: mediaproxy/checkAsymmetricFile(): cannot "
                "compile line %d of the %s asymmetric clients file into a "
                "regular expression (will be ignored): %s", i, which, errbuf);
            pkg_free(re);
        }
    }

    aptr->timestamp = statbuf.st_mtime;

    LOG(L_INFO, "info: mediaproxy: %sloaded %s asymmetric clients file "
        "containing %d entr%s.\n", firstTime ? "" : "re",
        which, aptr->count, aptr->count==1 ? "y" : "ies");

}
Esempio n. 13
0
ht_cell_t* ht_cell_value_add(ht_t *ht, str *name, int val, ht_cell_t *old)
{
	unsigned int idx;
	unsigned int hid;
	ht_cell_t *it, *prev, *cell;
	time_t now;
	int_str isval;

	if(ht==NULL || ht->entries==NULL)
		return NULL;

	hid = ht_compute_hash(name);

	idx = ht_get_entry(hid, ht->htsize);

	now = 0;
	if(ht->htexpire>0)
		now = time(NULL);
	prev = NULL;
	ht_slot_lock(ht, idx);
	it = ht->entries[idx].first;
	while(it!=NULL && it->cellid < hid)
	{
		prev = it;
		it = it->next;
	}
	while(it!=NULL && it->cellid == hid)
	{
		if(name->len==it->name.len
				&& strncmp(name->s, it->name.s, name->len)==0)
		{
			/* found */
			if(now>0 && it->expire!=0 && it->expire<now) {
				/* entry has expired */

				if(ht->flags==PV_VAL_INT) {
					/* initval is integer, use it to create a fresh entry */
					it->flags &= ~AVP_VAL_STR;
					it->value.n = ht->initval.n;
					/* increment will be done below */
				} else {
					ht_slot_unlock(ht, idx);
					return NULL;
				}
			}
			/* update value */
			if(it->flags&AVP_VAL_STR)
			{
				/* string value cannot be incremented */
				ht_slot_unlock(ht, idx);
				return NULL;
			} else {
				it->value.n += val;
				if(ht->updateexpire)
					it->expire = now + ht->htexpire;
				if(old!=NULL)
				{
					if(old->msize>=it->msize)
					{
						memcpy(old, it, it->msize);
						ht_slot_unlock(ht, idx);
						return old;
					}
				}
				cell = (ht_cell_t*)pkg_malloc(it->msize);
				if(cell!=NULL)
					memcpy(cell, it, it->msize);

				ht_slot_unlock(ht, idx);
				return cell;
			}
		}
		prev = it;
		it = it->next;
	}
	/* add val if htable has an integer init value */
	if(ht->flags!=PV_VAL_INT)
	{
		ht_slot_unlock(ht, idx);
		return NULL;
	}
	isval.n = ht->initval.n + val;
	it = ht_cell_new(name, 0, &isval, hid);
	if(it == NULL)
	{
		LM_ERR("cannot create new cell.\n");
		ht_slot_unlock(ht, idx);
		return NULL;
	}
	it->expire = now + ht->htexpire;
	if(prev==NULL)
	{
		if(ht->entries[idx].first!=NULL)
		{
			it->next = ht->entries[idx].first;
			ht->entries[idx].first->prev = it;
		}
		ht->entries[idx].first = it;
	} else {
		it->next = prev->next;
		it->prev = prev;
		if(prev->next)
			prev->next->prev = it;
		prev->next = it;
	}
	ht->entries[idx].esize++;
	if(old!=NULL)
	{
		if(old->msize>=it->msize)
		{
			memcpy(old, it, it->msize);
			ht_slot_unlock(ht, idx);
			return old;
		}
	}
	cell = (ht_cell_t*)pkg_malloc(it->msize);
	if(cell!=NULL)
		memcpy(cell, it, it->msize);

	ht_slot_unlock(ht, idx);
	return cell;
}
Esempio n. 14
0
void* my_pkg_malloc(size_t size){
	
	return pkg_malloc(size);
}
Esempio n. 15
0
/* parses the first line, returns pointer to  next line  & fills fl;
   also  modifies buffer (to avoid extra copy ops) */
char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl)
{
	
	char *tmp;
	char* second;
	char* third;
	char* nl;
	int offset;
	/* int l; */
	char* end;
	char s1,s2,s3;
	char *prn;
	unsigned int t;

	/* grammar:
		request  =  method SP uri SP version CRLF
		response =  version SP status  SP reason  CRLF
		(version = "SIP/2.0")
	*/
	

	offset = 0;
	end=buffer+len;
	/* see if it's a reply (status) */

	/* jku  -- parse well-known methods */

	/* drop messages which are so short they are for sure useless;
           utilize knowledge of minimum size in parsing the first
	   token 
        */
	if (len <=16 ) {
		LOG(L_INFO, "ERROR: parse_first_line: message too short: %d\n", len);
		goto error1;
	}
	tmp=buffer;
  	/* is it perhaps a reply, ie does it start with "SIP...." ? */
	if ( 	(*tmp=='S' || *tmp=='s') && 
		strncasecmp( tmp+1, SIP_VERSION+1, SIP_VERSION_LEN-1)==0 &&
		(*(tmp+SIP_VERSION_LEN)==' ')) {
			fl->type=SIP_REPLY;
			fl->u.reply.version.len=SIP_VERSION_LEN;
			tmp=buffer+SIP_VERSION_LEN;
	} else if (http_reply_parse != 0 &&
		 	(*tmp=='H' || *tmp=='h') &&
			/* 'HTTP/1.' */
			strncasecmp( tmp+1, HTTP_VERSION+1, HTTP_VERSION_LEN-1)==0 &&
			/* [0|1] */
			((*(tmp+HTTP_VERSION_LEN)=='0') || (*(tmp+HTTP_VERSION_LEN)=='1')) &&
			(*(tmp+HTTP_VERSION_LEN+1)==' ')  ){ 
			/* ugly hack to be able to route http replies
			 * Note: - the http reply must have a via
			 *       - the message is marked as SIP_REPLY (ugly)
			 */
				fl->type=SIP_REPLY;
				fl->u.reply.version.len=HTTP_VERSION_LEN+1 /*include last digit*/;
				tmp=buffer+HTTP_VERSION_LEN+1 /* last digit */;
	} else IFISMETHOD( INVITE, 'I' )
	else IFISMETHOD( CANCEL, 'C')
	else IFISMETHOD( ACK, 'A' )
	else IFISMETHOD( BYE, 'B' ) 
	else IFISMETHOD( INFO, 'I' )
	else IFISMETHOD( REGISTER, 'R')
	else IFISMETHOD( SUBSCRIBE, 'S')
	else IFISMETHOD( NOTIFY, 'N')
	else IFISMETHOD( MESSAGE, 'M')
	else IFISMETHOD( OPTIONS, 'O')
	else IFISMETHOD( PRACK, 'P')
	else IFISMETHOD( UPDATE, 'U')
	else IFISMETHOD( REFER, 'R')
	else IFISMETHOD( PUBLISH, 'P')
	/* if you want to add another method XXX, include METHOD_XXX in
           H-file (this is the value which you will take later in
           processing and define XXX_LEN as length of method name;
	   then just call IFISMETHOD( XXX, 'X' ) ... 'X' is the first
	   latter; everything must be capitals
	*/
	else {
		/* neither reply, nor any of known method requests, 
		   let's believe it is an unknown method request
        	*/
		tmp=eat_token_end(buffer,buffer+len);
		if ((tmp==buffer)||(tmp>=end)){
			LOG(L_INFO, "ERROR:parse_first_line: empty  or bad first line\n");
			goto error1;
		}
		if (*tmp!=' ') {
			LOG(L_INFO, "ERROR:parse_first_line: method not followed by SP\n");
			goto error1;
		}
		fl->type=SIP_REQUEST;
		fl->u.request.method_value=METHOD_OTHER;
		fl->u.request.method.len=tmp-buffer;
	}


	/* identifying type of message over now; 
	   tmp points at space after; go ahead */

	fl->u.request.method.s=buffer;  /* store ptr to first token */
	second=tmp+1;			/* jump to second token */
	offset=second-buffer;

/* EoJku */
	
	/* next element */
	tmp=eat_token_end(second, second+len-offset);
	if (tmp>=end){
		goto error;
	}
	offset+=tmp-second;
	third=eat_space_end(tmp, tmp+len-offset);
	offset+=third-tmp;
	if ((third==tmp)||(tmp>=end)){
		goto error;
	}
	fl->u.request.uri.s=second;
	fl->u.request.uri.len=tmp-second;

	/* jku: parse status code */
	if (fl->type==SIP_REPLY) {
		if (fl->u.request.uri.len!=3) {
			LOG(L_INFO, "ERROR:parse_first_line: len(status code)!=3: %.*s\n",
				fl->u.request.uri.len, ZSW(second) );
			goto error;
		}
		s1=*second; s2=*(second+1);s3=*(second+2);
		if (s1>='0' && s1<='9' && 
		    s2>='0' && s2<='9' &&
		    s3>='0' && s3<='9' ) {
			fl->u.reply.statuscode=(s1-'0')*100+10*(s2-'0')+(s3-'0');
		} else {
			LOG(L_INFO, "ERROR:parse_first_line: status_code non-numerical: %.*s\n",
				fl->u.request.uri.len, ZSW(second) );
			goto error;
		}
	}
	/* EoJku */

	/*  last part: for a request it must be the version, for a reply
	 *  it can contain almost anything, including spaces, so we don't care
	 *  about it*/
	if (fl->type==SIP_REQUEST){
		tmp=eat_token_end(third,third+len-offset);
		offset+=tmp-third;
		if ((tmp==third)||(tmp>=end)){
			goto error;
		}
		if (! is_empty_end(tmp, tmp+len-offset)){
			goto error;
		}
	}else{
		tmp=eat_token2_end(third,third+len-offset,'\r'); /* find end of line 
												  ('\n' or '\r') */
		if (tmp>=end){ /* no crlf in packet => invalid */
			goto error;
		}
		offset+=tmp-third;
	}
	nl=eat_line(tmp,len-offset);
	if (nl>=end){ /* no crlf in packet or only 1 line > invalid */
		goto error;
	}
	fl->u.request.version.s=third;
	fl->u.request.version.len=tmp-third;
	fl->len=nl-buffer;

	return nl;

error:
	LOG(L_DBG, "parse_first_line: bad %s first line\n",
		(fl->type==SIP_REPLY)?"reply(status)":"request");

	LOG(L_DBG, "at line 0 char %d: \n", offset );
	prn=pkg_malloc( offset );
	if (prn) {
		for (t=0; t<offset; t++)
			if (*(buffer+t)) *(prn+t)=*(buffer+t);
			else *(prn+t)=176; /* '°' */
		LOG(L_DBG, "parsed so far: %.*s\n", offset, ZSW(prn) );
		pkg_free( prn );
	};
error1:
	fl->type=SIP_INVALID;
	LOG(L_ERR, "parse_first_line: bad message (offset: %d)\n", offset);
	/* skip  line */
	nl=eat_line(buffer,len);
	return nl;
}
Esempio n. 16
0
static int
force_rtp_proxy2_f(struct sip_msg* msg, char* str1, char* str2)
{
	str body, body1, oldport, oldip, newport, newip;
	str callid, from_tag, to_tag, tmp;
	int create, port, len, asymmetric, flookup, argc, proxied, real;
	int oidx, pf=0, pf1, force, node_idx;
	char opts[16];
	char *cp, *cp1;
	char  *cpend, *next;
	char **ap, *argv[10];
	struct lump* anchor;
	struct rtpp_node *node;
	struct iovec v[14] = {
		{NULL, 0},	/* command */
		{NULL, 0},	/* options */
		{" ", 1},	/* separator */
		{NULL, 0},	/* callid */
		{" ", 1},	/* separator */
		{NULL, 7},	/* newip */
		{" ", 1},	/* separator */
		{NULL, 1},	/* oldport */
		{" ", 1},	/* separator */
		{NULL, 0},	/* from_tag */
		{";", 1},	/* separator */
		{NULL, 0},	/* medianum */
		{" ", 1},	/* separator */
		{NULL, 0}	/* to_tag */
	};
	char *v1p, *v2p, *c1p, *c2p, *m1p, *m2p, *bodylimit;
	char medianum_buf[20];
	int medianum, media_multi;
	str medianum_str, tmpstr1;
	int c1p_altered;

	v[1].iov_base=opts;
	asymmetric = flookup = force = real = 0;
	oidx = 1;
	node_idx = -1;
	for (cp = str1; *cp != '\0'; cp++) {
		switch (*cp) {
		case ' ':
		case '\t':
			break;

		case 'a':
		case 'A':
			opts[oidx++] = 'A';
			asymmetric = 1;
			real = 1;
			break;

		case 'i':
		case 'I':
			opts[oidx++] = 'I';
			break;

		case 'e':
		case 'E':
			opts[oidx++] = 'E';
			break;

		case 'l':
		case 'L':
			flookup = 1;
			break;

		case 'f':
		case 'F':
			force = 1;
			break;

		case 'r':
		case 'R':
			real = 1;
			break;

		case 'n':
		case 'N':
			cp++;
			for (len = 0; isdigit(cp[len]); len++)
				continue;
			if (len == 0) {
				LOG(L_ERR, "ERROR: force_rtp_proxy2: non-negative integer"
				    "should follow N option\n");
				return -1;
			}
			node_idx = strtoul(cp, NULL, 10);
			cp += len - 1;
			break;

		default:
			LOG(L_ERR, "ERROR: force_rtp_proxy2: unknown option `%c'\n", *cp);
			return -1;
		}
	}

	if (msg->first_line.type == SIP_REQUEST &&
	    msg->first_line.u.request.method_value == METHOD_INVITE) {
		create = 1;
	} else if (msg->first_line.type == SIP_REPLY) {
		create = 0;
	} else {
		return -1;
	}
	/* extract_body will also parse all the headers in the message as
	 * a side effect => don't move get_callid/get_to_tag in front of it
	 * -- andrei */
	if (extract_body(msg, &body) == -1) {
		LOG(L_ERR, "ERROR: force_rtp_proxy2: can't extract body "
		    "from the message\n");
		return -1;
	}
	if (get_callid(msg, &callid) == -1 || callid.len == 0) {
		LOG(L_ERR, "ERROR: force_rtp_proxy2: can't get Call-Id field\n");
		return -1;
	}
	if (get_to_tag(msg, &to_tag) == -1) {
		LOG(L_ERR, "ERROR: force_rtp_proxy2: can't get To tag\n");
		return -1;
	}
	if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {
		LOG(L_ERR, "ERROR: force_rtp_proxy2: can't get From tag\n");
		return -1;
	}
	if (flookup != 0) {
		if (create == 0 || to_tag.len == 0)
			return -1;
		create = 0;
		tmp = from_tag;
		from_tag = to_tag;
		to_tag = tmp;
	}
	proxied = 0;
	for (cp = body.s; (len = body.s + body.len - cp) >= ANORTPPROXY_LEN;) {
		cp1 = ser_memmem(cp, ANORTPPROXY, len, ANORTPPROXY_LEN);
		if (cp1 == NULL)
			break;
		if (cp1[-1] == '\n' || cp1[-1] == '\r') {
			proxied = 1;
			break;
		}
		cp = cp1 + ANORTPPROXY_LEN;
	}
	if (proxied != 0 && force == 0)
		return -1;
	/*
	 * Parsing of SDP body.
	 * It can contain a few session descriptions (each starts with
	 * v-line), and each session may contain a few media descriptions
	 * (each starts with m-line).
	 * We have to change ports in m-lines, and also change IP addresses in
	 * c-lines which can be placed either in session header (fallback for
	 * all medias) or media description.
	 * Ports should be allocated for any media. IPs all should be changed
	 * to the same value (RTP proxy IP), so we can change all c-lines
	 * unconditionally.
	 */
	bodylimit = body.s + body.len;
	v1p = find_sdp_line(body.s, bodylimit, 'v');
	if (v1p == NULL) {
		LOG(L_ERR, "ERROR: force_rtp_proxy2: no sessions in SDP\n");
		return -1;
	}
	v2p = find_next_sdp_line(v1p, bodylimit, 'v', bodylimit);
	media_multi = (v2p != bodylimit);
	v2p = v1p;
	medianum = 0;
	for(;;) {
		/* Per-session iteration. */
		v1p = v2p;
		if (v1p == NULL || v1p >= bodylimit)
			break; /* No sessions left */
		v2p = find_next_sdp_line(v1p, bodylimit, 'v', bodylimit);
		/* v2p is text limit for session parsing. */
		m1p = find_sdp_line(v1p, v2p, 'm');
		/* Have this session media description? */
		if (m1p == NULL) {
			LOG(L_ERR, "ERROR: force_rtp_proxy2: no m= in session\n");
			return -1;
		}
		/*
		 * Find c1p only between session begin and first media.
		 * c1p will give common c= for all medias.
		 */
		c1p = find_sdp_line(v1p, m1p, 'c');
		c1p_altered = 0;
		/* Have session. Iterate media descriptions in session */
		m2p = m1p;
		for (;;) {
			m1p = m2p;
			if (m1p == NULL || m1p >= v2p)
				break;
			m2p = find_next_sdp_line(m1p, v2p, 'm', v2p);
			/* c2p will point to per-media "c=" */
			c2p = find_sdp_line(m1p, m2p, 'c');
			/* Extract address and port */
			tmpstr1.s = c2p ? c2p : c1p;
			if (tmpstr1.s == NULL) {
				/* No "c=" */
				LOG(L_ERR, "ERROR: force_rtp_proxy2: can't"
				    " find media IP in the message\n");
				return -1;
			}
			tmpstr1.len = v2p - tmpstr1.s; /* limit is session limit text */
			if (extract_mediaip(&tmpstr1, &oldip, &pf) == -1) {
				LOG(L_ERR, "ERROR: force_rtp_proxy2: can't"
				    " extract media IP from the message\n");
				return -1;
			}
			tmpstr1.s = m1p;
			tmpstr1.len = m2p - m1p;
			if (extract_mediaport(&tmpstr1, &oldport) == -1) {
				LOG(L_ERR, "ERROR: force_rtp_proxy2: can't"
				    " extract media port from the message\n");
				return -1;
			}
			++medianum;
			if (asymmetric != 0 || real != 0) {
				newip = oldip;
			} else {
				newip.s = ip_addr2a(&msg->rcv.src_ip);
				newip.len = strlen(newip.s);
			}
			/* XXX must compare address families in all addresses */
			if (pf == AF_INET6) {
				opts[oidx] = '6';
				oidx++;
			}
			snprintf(medianum_buf, sizeof medianum_buf, "%d", medianum);
			medianum_str.s = medianum_buf;
			medianum_str.len = strlen(medianum_buf);
			opts[0] = (create == 0) ? 'L' : 'U';
			v[1].iov_len = oidx;
			STR2IOVEC(callid, v[3]);
			STR2IOVEC(newip, v[5]);
			STR2IOVEC(oldport, v[7]);
			STR2IOVEC(from_tag, v[9]);
			if (1 || media_multi) /* XXX netch: can't choose now*/
			{
				STR2IOVEC(medianum_str, v[11]);
			} else {
				v[10].iov_len = v[11].iov_len = 0;
			}
			STR2IOVEC(to_tag, v[13]);
			do {
				node = select_rtpp_node(callid, 1, node_idx);
				if (!node) {
					LOG(L_ERR, "ERROR: force_rtp_proxy2: no available proxies\n");
					return -1;
				}
				cp = send_rtpp_command(node, v, (to_tag.len > 0) ? 14 : 12);
			} while (cp == NULL);
			/* Parse proxy reply to <argc,argv> */
			argc = 0;
			memset(argv, 0, sizeof(argv));
			cpend=cp+strlen(cp);
			next=eat_token_end(cp, cpend);
			for (ap = argv; cp<cpend; cp=next+1, next=eat_token_end(cp, cpend)){
				*next=0;
				if (*cp != '\0') {
					*ap=cp;
					argc++;
					if ((char*)++ap >= ((char*)argv+sizeof(argv)))
						break;
				}
			}
			if (argc < 1) {
				LOG(L_ERR, "force_rtp_proxy2: no reply from rtp proxy\n");
				return -1;
			}
			port = atoi(argv[0]);
			if (port <= 0 || port > 65535) {
				LOG(L_ERR, "force_rtp_proxy2: incorrect port in reply from rtp proxy\n");
				return -1;
			}

			pf1 = (argc >= 3 && argv[2][0] == '6') ? AF_INET6 : AF_INET;

			if (isnulladdr(&oldip, pf)) {
				if (pf1 == AF_INET6) {
					newip.s = "::";
					newip.len = 2;
				} else {
					newip.s = "0.0.0.0";
					newip.len = 7;
				}
			} else {
				newip.s = (argc < 2) ? str2 : argv[1];
				newip.len = strlen(newip.s);
			}
			newport.s = int2str(port, &newport.len); /* beware static buffer */
			/* Alter port. */
			body1.s = m1p;
			body1.len = bodylimit - body1.s;
			if (alter_mediaport(msg, &body1, &oldport, &newport, 0) == -1)
				return -1;
			/*
			 * Alter IP. Don't alter IP common for the session
			 * more than once.
			 */
			if (c2p != NULL || !c1p_altered) {
				body1.s = c2p ? c2p : c1p;
				body1.len = bodylimit - body1.s;
				if (alter_mediaip(msg, &body1, &oldip, pf, &newip, pf1, 0) == -1)
					return -1;
				if (!c2p)
					c1p_altered = 1;
			}
		} /* Iterate medias in session */
	} /* Iterate sessions */

	if (proxied == 0) {
		cp = pkg_malloc(ANORTPPROXY_LEN * sizeof(char));
		if (cp == NULL) {
			LOG(L_ERR, "ERROR: force_rtp_proxy2: out of memory\n");
			return -1;
		}
		anchor = anchor_lump(msg, body.s + body.len - msg->buf, 0, 0);
		if (anchor == NULL) {
			LOG(L_ERR, "ERROR: force_rtp_proxy2: anchor_lump failed\n");
			pkg_free(cp);
			return -1;
		}
		memcpy(cp, ANORTPPROXY, ANORTPPROXY_LEN);
		if (insert_new_lump_after(anchor, cp, ANORTPPROXY_LEN, 0) == NULL) {
			LOG(L_ERR, "ERROR: force_rtp_proxy2: insert_new_lump_after failed\n");
			pkg_free(cp);
			return -1;
		}
	}

	return 1;
}
Esempio n. 17
0
int sctp_server_rcv_loop()
{
	int len;
#ifdef DYN_BUF
	char* buf;
#else
	static char buf [BUF_SIZE+1];
#endif
	char *tmp;
	union sockaddr_union* from;
	unsigned int fromlen;
	struct receive_info ri;
	struct sctp_sndrcvinfo sinfo;


	from=(union sockaddr_union*) pkg_malloc(sizeof(union sockaddr_union));
	if (from==0){
		LM_ERR("out of pkg memory\n");
		goto error;
	}
	memset(&sinfo, 0 , sizeof(sinfo));
	ri.bind_address=bind_address; /* this will not change, we do it only once*/
	ri.dst_port=bind_address->port_no;
	ri.dst_ip=bind_address->address;
	ri.proto=PROTO_SCTP;
	ri.proto_reserved1=ri.proto_reserved2=0;
	for(;;){
#ifdef DYN_BUF
		buf=pkg_malloc(BUF_SIZE+1);
		if (buf==0){
			LM_ERR(" could not allocate receive buffer in pkg memory\n");
			goto error;
		}
#endif
		fromlen=sockaddru_len(bind_address->su);
		len = sctp_recvmsg(bind_address->socket, buf, BUF_SIZE, &from->s, &fromlen, &sinfo, 0);
		
		if (len==-1){
			if (errno==EAGAIN){
				LM_DBG("packet with bad checksum received\n");
				continue;
			}
			LM_ERR("sctp_recvmsg:[%d] %s\n", errno, strerror(errno));
			if ((errno==EINTR)||(errno==EWOULDBLOCK)|| (errno==ECONNREFUSED))
				continue; /* goto skip;*/
			else goto error;
		}
		/* we must 0-term the messages, receive_msg expects it */
		buf[len]=0; /* no need to save the previous char */

		ri.src_su=*from;
		su2ip_addr(&ri.src_ip, from);
		ri.src_port=su_getport(from);

#ifndef NO_ZERO_CHECKS
		if (buf[len-1]==0) {
			tmp=ip_addr2a(&ri.src_ip);
			LM_WARN("upstream bug - 0-terminated packet from %s %d\n",
					tmp, htons(ri.src_port));
			len--;
		}
#endif
		if (ri.src_port==0){
			tmp=ip_addr2a(&ri.src_ip);
			LM_INFO("dropping 0 port packet from %s\n", tmp);
			continue;
		}
		
		
		/* receive_msg must free buf too!*/
		receive_msg(buf, len, &ri);
		
	/* skip: do other stuff */
		
	}
	/*
	if (from) pkg_free(from);
	return 0;
	*/
	
error:
	if (from) pkg_free(from);
	return -1;
}
Esempio n. 18
0
File: tm.c Progetto: Danfx/opensips
inline static int w_t_new_request(struct sip_msg* msg, char *p_method,
			char *p_ruri, char *p_from, char *p_to, char *p_body, char *p_ctx)
{
#define CONTENT_TYPE_HDR      "Content-Type: "
#define CONTENT_TYPE_HDR_LEN  (sizeof(CONTENT_TYPE_HDR)-1)
	static dlg_t dlg;
	struct usr_avp **avp_list;
	str ruri;
	str method;
	str body;
	str headers;
	str s;
	int_str ctx;
	char *p;

	memset( &dlg, 0, sizeof(dlg_t));

	/* evaluate the parameters */

	/* method */
	if ( fixup_get_svalue(msg, (gparam_p)p_method, &method)<0 ) {
		LM_ERR("failed to extract METHOD param\n");
		return -1;
	}
	LM_DBG("setting METHOD to <%.*s>\n", method.len, method.s);

	/* ruri - next hop is the same as RURI */
	dlg.hooks.next_hop = dlg.hooks.request_uri = &ruri;
	if ( fixup_get_svalue(msg, (gparam_p)p_ruri, &ruri)<0 ) {
		LM_ERR("failed to extract RURI param\n");
		return -1;
	}
	LM_DBG("setting RURI to <%.*s>\n",
		dlg.hooks.next_hop->len, dlg.hooks.next_hop->s);

	/* FROM URI + display */
	if ( fixup_get_svalue(msg, (gparam_p)p_from, &s)<0 ) {
		LM_ERR("failed to extract FROM param\n");
		return -1;
	}
	if ( (p=q_memrchr(s.s, ' ', s.len))==NULL ) {
		/* no display, only FROM URI */
		dlg.loc_uri = s;
		dlg.loc_dname.s = NULL;
		dlg.loc_dname.len = 0;
	} else {
		/* display + URI */
		dlg.loc_uri.s = p+1;
		dlg.loc_uri.len = s.s+s.len - dlg.loc_uri.s;
		dlg.loc_dname.s = s.s;
		dlg.loc_dname.len = p - s.s;
	}
	LM_DBG("setting FROM to <%.*s> + <%.*s>\n",
		dlg.loc_dname.len, dlg.loc_dname.s,
		dlg.loc_uri.len, dlg.loc_uri.s);

	/* TO URI + display */
	if ( fixup_get_svalue(msg, (gparam_p)p_to, &s)<0 ) {
		LM_ERR("failed to extract TO param\n");
		return -1;
	}
	if ( (p=q_memrchr(s.s, ' ', s.len))==NULL ) {
		/* no display, only TO URI */
		dlg.rem_uri = s;
		dlg.rem_dname.s = NULL;
		dlg.rem_dname.len = 0;
	} else {
		/* display + URI */
		dlg.rem_uri.s = p+1;
		dlg.rem_uri.len = s.s+s.len - dlg.rem_uri.s;
		dlg.rem_dname.s = s.s;
		dlg.rem_dname.len = p - s.s;
	}
	LM_DBG("setting TO to <%.*s> + <%.*s>\n",
		dlg.rem_dname.len, dlg.rem_dname.s,
		dlg.rem_uri.len, dlg.rem_uri.s);

	/* BODY and Content-Type */
	if (p_body!=NULL) {
		if ( fixup_get_svalue(msg, (gparam_p)p_body, &body)<0 ) {
			LM_ERR("failed to extract BODY param\n");
			return -1;
		}
		if ( (p=q_memchr(body.s, ' ', body.len))==NULL ) {
			LM_ERR("Content Type not found in the beginning of body <%.*s>\n",
				body.len, body.s);
			return -1;
		}
		/* build the Content-type header */
		headers.len = CONTENT_TYPE_HDR_LEN + (p-body.s) + CRLF_LEN;
		if ( (headers.s=(char*)pkg_malloc(headers.len))==NULL ) {
			LM_ERR("failed to get pkg mem (needed %d)\n",headers.len);
			return -1;
		}
		memcpy( headers.s, CONTENT_TYPE_HDR, CONTENT_TYPE_HDR_LEN);
		memcpy( headers.s+CONTENT_TYPE_HDR_LEN, body.s, p-body.s);
		memcpy( headers.s+CONTENT_TYPE_HDR_LEN+(p-body.s), CRLF, CRLF_LEN);
		/* set the body */
		body.len = body.s + body.len - (p+1);
		body.s = p + 1;
		LM_DBG("setting BODY to <%.*s> <%.*s>\n",
			headers.len, headers.s,
			body.len, body.s );
	} else {
		body.s = NULL;
		body.len = 0;
		headers.s = NULL;
		headers.len = 0;
	}

	/* context value */
	if (p_ctx!=NULL) {
		if ( fixup_get_svalue(msg, (gparam_p)p_ctx, &ctx.s)<0 ) {
			LM_ERR("failed to extract BODY param\n");
			if (p_body) pkg_free(headers.s);
			return -1;
		}
		LM_DBG("setting CTX AVP to <%.*s>\n", ctx.s.len, ctx.s.s);
		avp_list = set_avp_list( &dlg.avps );
		if (!add_avp( AVP_VAL_STR, uac_ctx_avp_id, ctx))
			LM_ERR("failed to add ctx AVP, ignorring...\n");
		set_avp_list( avp_list );
	}

	/* add cseq */
	dlg.loc_seq.value = DEFAULT_CSEQ;
	dlg.loc_seq.is_set = 1;

	/* add callid */
	generate_callid(&dlg.id.call_id);

	/* add FROM tag */
	generate_fromtag(&dlg.id.loc_tag, &dlg.id.call_id);
	/* TO tag is empty as this is a initial request */
	dlg.id.rem_tag.s = NULL;
	dlg.id.rem_tag.len = 0;

	/* do the actual sending now */
	if ( t_uac( &method, headers.s?&headers:NULL, body.s?&body:NULL,
	&dlg, 0, 0, 0) <= 0 ) {
		LM_ERR("failed to send the request out\n");
		if (headers.s) pkg_free(headers.s);
		if (dlg.avps) destroy_avp_list(&dlg.avps);
		return -1;
	}

	/* success -> do cleanup */
	if (headers.s) pkg_free(headers.s);
	return 1;
}
Esempio n. 19
0
/* Format of _o:  column1 [ASC|DESC], column2 [ASC|DESC], ... */
int dbt_parse_orderbyclause(db_key_t **_o_k, char **_o_op, int *_o_n, db_key_t _o)
{
	char *_po, *_ps, *_pe;
	char _c = '\0';
	char _d[8];
	int _n;
	int _i;
	str *_s;

	/* scan _o, count ',' -> upper bound for no of columns */
	_n = 1;
	for (_i=0; _i < _o->len; _i++)
		if (_o->s[_i] == ',')
			_n++;

    /* *_o_k will include the db_key_ts, the strs, a copy of _o and \0 */
	*_o_k = pkg_malloc((sizeof(db_key_t)+sizeof(str)) * _n + _o->len + 1);
	if (!*_o_k)
		return -1;
	_s = (str *)((char *)(*_o_k) + sizeof(db_key_t) * _n);
	for (_i=0; _i < _n; _i++)
	    (*_o_k)[_i] = &_s[_i];
	_po = (char *)(*_o_k) + (sizeof(db_key_t) + sizeof(str)) * _n;
	memcpy(_po, _o->s, _o->len);
	*(_po+_o->len) = '\0';

	*_o_op = pkg_malloc(sizeof(char) * _n);
	if (!*_o_op)
	{
		pkg_free(*_o_k);
		return -1;
	}

	*_o_n = 0;
	_ps = _po;
	while (*_o_n < _n)
	{
		while (*_ps == ' ') _ps++;
		if (*_ps == '\0')
			break;
		strcpy(_d, " \f\n\r\t\v,"); /* isspace() and comma */
		if (*_ps == '"' || *_ps == '\'') /* detect quote */
		{
			_d[0] = *_ps;
			_d[1] = '\0';
			_ps++;
		}
		_pe = strpbrk(_ps, _d); /* search quote, space, comma or eos */
		if (!_pe && _d[0] == ' ') /* if token is last token in string */
			_pe = _po + _o->len; /* point to end of string */
		if (! _pe) /* we were looking for quote but found none */
			goto parse_error;

		/* _ps points to start of column-name,
		 * _pe points after the column-name, on quote, space, comma, or '\0' */
		_c = *_pe;
		*_pe = '\0';
		(*_o_k)[*_o_n]->s = _ps;
		(*_o_k)[*_o_n]->len = _pe - _ps;
		(*_o_op)[*_o_n] = '<'; /* default */
		(*_o_n)++;

		if (_c == '\0')
			break;

		/* go beyond current token */
		_ps = _pe + 1;
		if (_c == ',')
			continue;
		while (*_ps == ' ') _ps++;
		if (*_ps == ',')
		{
			_ps++;
			continue;
		}
		if (*_ps == '\0')
			break;

		/* there is ASC OR DESC qualifier */
		if (strncasecmp(_ps, "DESC", 4) == 0)
		{
			(*_o_op)[*_o_n-1] = '>';
			_ps += 4;
		} else if (strncasecmp(_ps, "ASC", 3) == 0)
		{
			_ps += 3;
		} else goto parse_error;

		/* point behind qualifier */
		while (*_ps == ' ') _ps++;
		if (*_ps == ',')
		{
			_ps++;
			continue;
		}
		if (*_ps == '\0')
			break;
		goto parse_error;
	}

	if (*_ps != '\0' && _c != '\0')   /* that means more elements than _tbc->nrcols */
		goto parse_error;

	if (*_o_n == 0) /* there weren't actually any columns */
	{
		pkg_free(*_o_k);
		pkg_free(*_o_op);
		*_o_op = NULL;
		*_o_k = NULL;
		return 0; /* return success anyway */
	}

	return 0;

parse_error:
	pkg_free(*_o_k);
	pkg_free(*_o_op);
	*_o_op = NULL;
	*_o_k = NULL;
	*_o_n = 0;
	return -1;
}
Esempio n. 20
0
int _bm_register_timer(char *tname, int mode, unsigned int *id)
{
    benchmark_timer_t *bmt = 0;
    benchmark_timer_t **tidx = 0;

    if(tname==NULL || id==NULL || bm_mycfg==NULL || strlen(tname)==0
            || strlen(tname)>BM_NAME_LEN-1)
        return -1;

    bmt = bm_mycfg->timers;
    while(bmt)
    {
        if(strcmp(bmt->name, tname)==0)
        {
            *id = bmt->id;
            return 0;
        }
        bmt = bmt->next;
    }
    if(mode==0)
        return -1;

    bmt = (benchmark_timer_t*)shm_malloc(sizeof(benchmark_timer_t));

    if(bmt==0)
    {
        LM_ERR("no more shm\n");
        return -1;
    }
    memset(bmt, 0, sizeof(benchmark_timer_t));

    /* private memory, otherwise we have races */
    bmt->start = (bm_timeval_t*)pkg_malloc(sizeof(bm_timeval_t));
    if(bmt->start == NULL)
    {
        shm_free(bmt);
        LM_ERR("no more pkg\n");
        return -1;
    }
    memset(bmt->start, 0, sizeof(bm_timeval_t));

    strcpy(bmt->name, tname);
    if(bm_mycfg->timers==0)
    {
        bmt->id = 0;
        bm_mycfg->timers = bmt;
    } else {
        bmt->id = bm_mycfg->timers->id+1;
        bmt->next = bm_mycfg->timers;
        bm_mycfg->timers = bmt;
    }

    /* do the indexing */
    if(bmt->id%10==0)
    {
        if(bm_mycfg->tindex!=NULL)
            tidx = bm_mycfg->tindex;
        bm_mycfg->tindex = (benchmark_timer_t**)shm_malloc((10+bmt->id)*
                           sizeof(benchmark_timer_t*));
        if(bm_mycfg->tindex==0)
        {
            LM_ERR("no more share memory\n");
            if(tidx!=0)
                shm_free(tidx);
            return -1;
        }
        memset(bm_mycfg->tindex, 0, (10+bmt->id)*sizeof(benchmark_timer_t*));
        if(tidx!=0)
        {
            memcpy(bm_mycfg->tindex, tidx, bmt->id*sizeof(benchmark_timer_t*));
            shm_free(tidx);
        }
    }
    bm_mycfg->tindex[bmt->id] = bmt;
    bm_mycfg->nrtimers = bmt->id + 1;
    bm_reset_timer(bmt->id);
    *id = bmt->id;
    LM_DBG("timer [%s] added with index <%u>\n", bmt->name, bmt->id);

    return 0;
}
Esempio n. 21
0
/**
 * @brief send a dmq message
 *
 * peer - the peer structure on behalf of which we are sending
 * body - the body of the message
 * node - we send the message to this node
 * resp_cback - a response callback that gets called when the transaction is complete
 */
int dmq_send_message(dmq_peer_t* peer, str* body, dmq_node_t* node,
		dmq_resp_cback_t* resp_cback, int max_forwards, str* content_type)
{
	uac_req_t uac_r;
	str str_hdr = {0, 0};
	str from = {0, 0}, to = {0, 0};
	dmq_cback_param_t* cb_param = NULL;
	int result = 0;
	int len = 0;
	
	if (!content_type) {
		LM_ERR("content-type is null\n");
		return -1;
	}
	/* add Max-Forwards and Content-Type headers */
	str_hdr.len = 34 + content_type->len + (CRLF_LEN*2);
	str_hdr.s = pkg_malloc(str_hdr.len);
	if(str_hdr.s==NULL) {
		LM_ERR("no more pkg\n");
		return -1;
	}
	len += sprintf(str_hdr.s, "Max-Forwards: %d" CRLF "Content-Type: %.*s" CRLF, max_forwards, content_type->len, content_type->s);
	str_hdr.len = len;
	
	cb_param = shm_malloc(sizeof(*cb_param));
	if (cb_param == NULL) {
		LM_ERR("no more shm for building callback parameter\n");
		goto error;
	}
	memset(cb_param, 0, sizeof(*cb_param));
	cb_param->resp_cback = *resp_cback;
	cb_param->node = shm_dup_node(node);
	if (cb_param->node == NULL) {
		LM_ERR("error building callback parameter\n");
		goto error;
	}
	
	if(build_uri_str(&peer->peer_id, &dmq_server_uri, &from) < 0) {
		LM_ERR("error building from string [username %.*s]\n",
				STR_FMT(&peer->peer_id));
		goto error;
	}
	if(build_uri_str(&peer->peer_id, &node->uri, &to) < 0) {
		LM_ERR("error building to string\n");
		goto error;
	}
	
	set_uac_req(&uac_r, &dmq_request_method, &str_hdr, body, NULL,
			TMCB_LOCAL_COMPLETED, dmq_tm_callback, (void*)cb_param);
	uac_r.ssock = &dmq_server_socket;

	result = tmb.t_request(&uac_r, &to,
			       &to, &from,
			       NULL);
	if(result < 0) {
		LM_ERR("error in tmb.t_request_within\n");
		goto error;
	}
	pkg_free(str_hdr.s);
	pkg_free(from.s);
	pkg_free(to.s);
	return 0;
error:
	pkg_free(str_hdr.s);
	if (from.s!=NULL) 
		pkg_free(from.s);
	if (to.s!=NULL) 
		pkg_free(to.s);
	if (cb_param) {
		if (cb_param->node)
			destroy_dmq_node(cb_param->node, 1);
		shm_free(cb_param);
	}
	return -1;
}
Esempio n. 22
0
/*! \note WARNING: buf must be 0 terminated (buf[len]=0) or some things might
 * break (e.g.: modules/textops)
 */
int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
{
	static context_p ctx = NULL;
	struct sip_msg* msg;
	struct timeval start;
	int rc;
	char *tmp;
	str in_buff;

	in_buff.len = len;
	in_buff.s = buf;

	/* the raw processing callbacks can change the buffer,
	further use in_buff.s and at the end try to free in_buff.s
	if changed by callbacks */
	run_pre_raw_processing_cb(PRE_RAW_PROCESSING,&in_buff,NULL);
	/* update the length for further processing */
	len = in_buff.len;

	msg=pkg_malloc(sizeof(struct sip_msg));
	if (msg==0) {
		LM_ERR("no pkg mem left for sip_msg\n");
		goto error;
	}
	msg_no++;
	/* number of vias parsed -- good for diagnostic info in replies */
	via_cnt=0;

	memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
	/* fill in msg */
	msg->buf=in_buff.s;
	msg->len=len;
	msg->rcv=*rcv_info;
	msg->id=msg_no;
	msg->ruri_q = Q_UNSPECIFIED;

	if (parse_msg(in_buff.s,len, msg)!=0){
		tmp=ip_addr2a(&(rcv_info->src_ip));
		LM_ERR("Unable to parse msg received from [%s:%d]\n", tmp, rcv_info->src_port);
		/* if a REQUEST msg was detected (first line was successfully parsed) we
		   should trigger the error route */
		if ( msg->first_line.type==SIP_REQUEST && error_rlist.a!=NULL )
			run_error_route(msg, 1);
		goto parse_error;
	}
	LM_DBG("After parse_msg...\n");

	start_expire_timer(start,execmsgthreshold);

	/* ... clear branches from previous message */
	clear_branches();

	if (msg->first_line.type==SIP_REQUEST) {
		update_stat( rcv_reqs, 1);
		/* sanity checks */
		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
			/* no via, send back error ? */
			LM_ERR("no via found in request\n");
			update_stat( err_reqs, 1);
			goto parse_error;
		}
		/* check if necessary to add receive?->moved to forward_req */
		/* check for the alias stuff */
		if (msg->via1->alias && tcp_accept_aliases &&
		is_tcp_based_proto(rcv_info->proto) ) {
			if (tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port,
									rcv_info->proto)!=0){
				LM_WARN("tcp alias failed\n");
				/* continue */
			}
		}

		LM_DBG("preparing to run routing scripts...\n");
		/* set request route type --bogdan*/
		set_route_type( REQUEST_ROUTE );

		/* prepare and set a new processing context for this request */
		prepare_context( ctx, parse_error );
		current_processing_ctx = ctx;

		/* execute pre-script callbacks, if any;
		 * if some of the callbacks said not to continue with
		 * script processing, don't do so;
		 * if we are here basic sanity checks are already done
		 * (like presence of at least one via), so you can count
		 * on via1 being parsed in a pre-script callback --andrei
		 */
		rc = exec_pre_req_cb(msg);
		if (rc == SCB_DROP_MSG) {
			update_stat( drp_reqs, 1);
			goto end; /* drop the message */
		}

		/* exec the routing script */
		if (rc & SCB_RUN_TOP_ROUTE)
			/* run the main request route and skip post_script callbacks
			 * if the TOBE_CONTINUE flag is returned */
			if ( run_top_route(rlist[DEFAULT_RT].a, msg) & ACT_FL_TBCONT )
				goto end;

		/* execute post request-script callbacks */
		if (rc & SCB_RUN_POST_CBS)
			exec_post_req_cb(msg);

	} else if (msg->first_line.type==SIP_REPLY) {
		update_stat( rcv_rpls, 1);
		/* sanity checks */
		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
			/* no via, send back error ? */
			LM_ERR("no via found in reply\n");
			update_stat( err_rpls, 1);
			goto parse_error;
		}

		/* set reply route type --bogdan*/
		set_route_type( ONREPLY_ROUTE );

		/* prepare and set a new processing context for this reply */
		prepare_context( ctx, parse_error );
		current_processing_ctx = ctx;

		/* execute pre-script callbacks, if any ;
		 * if some of the callbacks said not to continue with
		 * script processing, don't do so ;
		 * if we are here, basic sanity checks are already done
		 * (like presence of at least one via), so you can count
		 * on via1 being parsed in a pre-script callback --andrei
		 */
		rc = exec_pre_rpl_cb(msg);
		if (rc == SCB_DROP_MSG) {
			update_stat( drp_rpls, 1);
			goto end; /* drop the reply */
		}

		/* exec the onreply routing script */
		if (rc & SCB_RUN_TOP_ROUTE &&  onreply_rlist[DEFAULT_RT].a &&
		    (run_top_route(onreply_rlist[DEFAULT_RT].a,msg) & ACT_FL_DROP)
		    && msg->REPLY_STATUS < 200) {

			LM_DBG("dropping provisional reply %d\n", msg->REPLY_STATUS);
			update_stat( drp_rpls, 1);
			goto end; /* drop the message */
		} else {
			/* send the msg */
			forward_reply(msg);
			/* TODO - TX reply stat */
		}

		/* execute post reply-script callbacks */
		if (rc & SCB_RUN_POST_CBS)
			exec_post_rpl_cb(msg);
	}

end:

	/* if someone else set the context, then we should also "release" the
	 * static ctx. */
	if (current_processing_ctx == NULL)
		ctx = NULL;
	else
		context_destroy(CONTEXT_GLOBAL, ctx);

	current_processing_ctx = NULL;
	stop_expire_timer( start, execmsgthreshold, "msg processing",
		msg->buf, msg->len, 0);
	reset_longest_action_list(execmsgthreshold);

	/* free possible loaded avps -bogdan */
	reset_avps();
	LM_DBG("cleaning up\n");
	free_sip_msg(msg);
	pkg_free(msg);
	if (in_buff.s != buf)
		pkg_free(in_buff.s);
	return 0;
parse_error:
	exec_parse_err_cb(msg);
	free_sip_msg(msg);
	pkg_free(msg);
error:
	if (in_buff.s != buf)
		pkg_free(in_buff.s);
	return -1;
}
Esempio n. 23
0
ac_maxval_p ac_get_maxval(ac_tm_p _atp)
{
	struct tm _tm;
	int _v;
	ac_maxval_p _amp = NULL;

	if(!_atp)
		return NULL;
	_amp = (ac_maxval_p)pkg_malloc(sizeof(ac_maxval_t));
	if(!_amp)
		return NULL;
	
	// the number of the days in theyear
	_amp->yday = 365 + is_leap_year(_atp->t.tm_year+1900);

	// the number of the days in the month
	switch(_atp->t.tm_mon)
	{
		case 1:
			if(_amp->yday == 366)
				_amp->mday = 29;
			else
				_amp->mday = 28;
		break;
		case 3: case 5: case 8: case 10:
			_amp->mday = 30;
		break;
		default:
			_amp->mday = 31;
	}
	
	// maximum ocurrences of a week day in the year
	memset(&_tm, 0, sizeof(struct tm));
	_tm.tm_year = _atp->t.tm_year;
	_tm.tm_mon = 11;
	_tm.tm_mday = 31;
	mktime(&_tm);
	_v = 0;
	if(_atp->t.tm_wday > _tm.tm_wday)
		_v = _atp->t.tm_wday - _tm.tm_wday + 1;
	else
		_v = _tm.tm_wday - _atp->t.tm_wday;
	_amp->ywday = (int)((_tm.tm_yday-_v)/7) + 1;
	
	// maximum number of weeks in the year
	_amp->yweek = ac_get_yweek(&_tm) + 1;
	
	// maximum number of the week day in the month
	_amp->mwday=(int)((_amp->mday-1-(_amp->mday-_atp->t.tm_mday)%7)/7)+1;
	
	// maximum number of weeks in the month
	_v = (_atp->t.tm_wday + (_amp->mday - _atp->t.tm_mday)%7)%7;
#ifdef USE_YWEEK_U
	_amp->mweek = (int)((_amp->mday-1)/7+(7-_v+(_amp->mday-1)%7)/7)+1;
#else
	_amp->mweek = (int)((_amp->mday-1)/7+(7-(6+_v)%7+(_amp->mday-1)%7)/7)+1;
#endif

	_atp->mv = _amp;
	return _amp;
}
Esempio n. 24
0
void timer_check(unsigned int ticks, void* param)
{
	unsigned int i=hash_index;
	reg_record_t *rec;
	char *p;
	int len;
	time_t now;
	str str_now = {NULL, 0};

	now = time(0);

	p = int2str((unsigned long)(time(0)), &len);
	if (p && len>0) {
		str_now.s = (char *)pkg_malloc(len);
		if (str_now.s) {
			memcpy(str_now.s, p, len);
			str_now.len = len;
		} else {
			LM_ERR("oom\n");
			return;
		}
	}

	lock_get(&reg_htable[i].lock);
	//LM_DBG("checking ... [%d] on htable[%d]\n", (unsigned int)now, i);
	rec = reg_htable[i].first;
	while (rec) {
		switch(rec->state){
		case REGISTERING_STATE:
		case AUTHENTICATING_STATE:
		case WRONG_CREDENTIALS_STATE:
			break;
		case REGISTER_TIMEOUT_STATE:
		case INTERNAL_ERROR_STATE:
		case REGISTRAR_ERROR_STATE:
			reg_print_record(rec);
			new_call_id_ftag_4_record(rec, &str_now);
			if(send_register(i, rec, NULL)==1) {
				rec->last_register_sent = now;
				rec->state = REGISTERING_STATE;
			} else {
				rec->registration_timeout = now + rec->expires - timer_interval;
				rec->state = INTERNAL_ERROR_STATE;
			}
			break;
		case REGISTERED_STATE:
			/* check if we need to re-register */
			if (now < rec->registration_timeout) {
				break;
			}
		case NOT_REGISTERED_STATE:
			if(send_register(i, rec, NULL)==1) {
				rec->last_register_sent = now;
				rec->state = REGISTERING_STATE;
			} else {
				rec->registration_timeout = now + rec->expires - timer_interval;
				rec->state = INTERNAL_ERROR_STATE;
			}
			break;
		default:
			LM_ERR("Unexpected state [%d] for rec [%p]\n", rec->state, rec);
		}
		rec = rec->next;
	}
	lock_release(&reg_htable[i].lock);

	if (str_now.s) {pkg_free(str_now.s);}

	hash_index = (++i)%reg_hsize;

	return;
}
Esempio n. 25
0
int dlg_th_onreply(struct dlg_cell *dlg, struct sip_msg *rpl, int init_req, int dir)
{
	struct hdr_field *it;
	char* buf = rpl->buf;
	int peer_leg;
	struct lump* lmp;
	int size;
	char* route;
	str lv_str;
	struct dlg_leg* leg;

	LM_DBG("start\n");

	/* parse all headers to be sure that all RR and Contact hdrs are found */
	if (parse_headers(rpl, HDR_EOH_F, 0)< 0) {
		LM_ERR("Failed to parse reply\n");
		return -1;
	}

	/* replace contact */
	if(dlg_replace_contact(rpl, dlg) < 0) {
		LM_ERR("Failed to replace contact\n");
		return -1;
	}

	if(dir == DLG_DIR_UPSTREAM)
		peer_leg = DLG_CALLER_LEG;
	else
		peer_leg = callee_idx(dlg);
	leg = &dlg->legs[peer_leg];

	LM_DBG("peer_leg = %d\n", peer_leg);
	LM_DBG("first RR hdr = %p\n", rpl->record_route);
	/* delete record route */
	for (it=rpl->record_route; it; it=it->sibling) { /* changed here for contact - it was & it->sibling */
		/* skip the one added by this proxy */
		if ((lmp = del_lump(rpl, it->name.s - buf, it->len,HDR_RECORDROUTE_T)) == 0) {
			LM_ERR("del_lump failed \n");
			return -1;
		}
		LM_DBG("Delete record route: [%.*s]\n", it->len, it->name.s);
	}

	/* add Via headers */
	lmp = anchor_lump(rpl,rpl->headers->name.s - buf,0,0);
	if (lmp == 0)
	{
		LM_ERR("failed anchoring new lump\n");
		return -1;
	}
	if(pkg_str_dup(&lv_str, &leg->last_vias) < 0) {
		LM_ERR("Failed to duplicate memory\n");
		return 1;
	}
	if ((lmp = insert_new_lump_after(lmp, lv_str.s, lv_str.len, HDR_VIA_T)) == 0) {
		LM_ERR("failed inserting new vias\n");
		pkg_free(lv_str.s);
		return -1;
	}
	LM_DBG("Added Via headers [%.*s] leg=%p\n", lv_str.len, lv_str.s, leg);

	/* if dialog not confirmed and 200OK for Invite */
	/* pass the record route headers for this leg */
	if(init_req && dir == DLG_DIR_UPSTREAM && rpl->first_line.u.reply.statuscode==200
			&& leg->route_set.s) {

		/* changed here for contact ( take care to insert the routes after own) */

		/* pass record route headers */
		size = leg->route_set.len + RECORD_ROUTE_LEN + CRLF_LEN;
		route = pkg_malloc(size);
		if (route == NULL) {
			LM_ERR("no more pkg memory\n");
			return -1;
		}

		memcpy(route, RECORD_ROUTE, RECORD_ROUTE_LEN);
		memcpy(route+RECORD_ROUTE_LEN, leg->route_set.s, leg->route_set.len);
		memcpy(route+RECORD_ROUTE_LEN+leg->route_set.len, CRLF, CRLF_LEN);

		/* put after Via */
		if ((lmp = insert_new_lump_after(lmp, route, size, HDR_RECORDROUTE_T)) == 0) {
			LM_ERR("failed inserting new route set\n");
			pkg_free(route);
			return -1;
		}
		LM_DBG("Added record route [%.*s]\n", size, route);
	}

	return 0;
}
Esempio n. 26
0
/* convert the value to the requested type */
int convert_val(unsigned int val_type, void *val,
			unsigned int var_type, void **new_val)
{
	static str	s;
	char		*end;
	int		i;
	static char	buf[INT2STR_MAX_LEN];

	/* we have to convert from val_type to var_type */
	switch (CFG_INPUT_MASK(var_type)) {
	case CFG_INPUT_INT:
		if (val_type == CFG_VAR_INT) {
			*new_val = val;
			break;

		} else if (val_type == CFG_VAR_STRING) {
			if (!val || (((char *)val)[0] == '\0')) {
				LOG(L_ERR, "ERROR: convert_val(): "
					"cannot convert NULL string value to integer\n");
				return -1;
			}
			*new_val = (void *)(long)strtol((char *)val, &end, 10);
			if (*end != '\0') {
				LOG(L_ERR, "ERROR: convert_val(): "
					"cannot convert string to integer '%s'\n",
					(char *)val);
				return -1;
			}
			break;

		} else if (val_type == CFG_VAR_STR) {
			if (!((str *)val)->len || !((str *)val)->s) {
				LOG(L_ERR, "ERROR: convert_val(): "
					"cannot convert NULL str value to integer\n");
				return -1;
			}
			if (str2sint((str *)val, &i)) {
				LOG(L_ERR, "ERROR: convert_val(): "
					"cannot convert string to integer '%.*s'\n",
					((str *)val)->len, ((str *)val)->s);
				return -1;
			}
			*new_val = (void *)(long)i;
			break;
		}
		goto error;

	case CFG_INPUT_STRING:
		if (val_type == CFG_VAR_INT) {
			buf[snprintf(buf, sizeof(buf)-1, "%ld", (long)val)] = '\0';
			*new_val = buf;
			break;

		} else if (val_type == CFG_VAR_STRING) {
			*new_val = val;
			break;

		} else if (val_type == CFG_VAR_STR) {
			if (!((str *)val)->s) {
				*new_val = NULL;
				break;
			}
			/* the value may not be zero-terminated, thus,
			a new variable has to be allocated with larger memory space */
			if (temp_string) pkg_free(temp_string);
			temp_string = (char *)pkg_malloc(sizeof(char) * (((str *)val)->len + 1));
			if (!temp_string) {
				LOG(L_ERR, "ERROR: convert_val(): not enough memory\n");
				return -1;
			}
			memcpy(temp_string, ((str *)val)->s, ((str *)val)->len);
			temp_string[((str *)val)->len] = '\0';
			*new_val = (void *)temp_string;
			break;

		}
		goto error;

	case CFG_INPUT_STR:
		if (val_type == CFG_VAR_INT) {
			s.len = snprintf(buf, sizeof(buf)-1, "%ld", (long)val);
			buf[s.len] = '\0';
			s.s = buf;
			*new_val = (void *)&s;
			break;

		} else if (val_type == CFG_VAR_STRING) {
			s.s = (char *)val;
			s.len = (s.s) ? strlen(s.s) : 0;
			*new_val = (void *)&s;
			break;

		} else if (val_type == CFG_VAR_STR) {
			*new_val = val;
			break;			
		}
		goto error;
	}

	return 0;

error:
	LOG(L_ERR, "ERROR: convert_val(): got a value with type %u, but expected %u\n",
			val_type, CFG_INPUT_MASK(var_type));
	return -1;
}
Esempio n. 27
0
static int lua_sr_modf (lua_State *L)
{
	int ret;
	char *luav[MAX_ACTIONS];
	char *argv[MAX_ACTIONS];
	int argc;
	int i;
	int mod_type;
	struct run_act_ctx ra_ctx;
	unsigned modver;
	struct action *act;
	sr31_cmd_export_t* expf;
	sr_lua_env_t *env_L;

	ret = 1;
	act = NULL;
	argc = 0;
	memset(luav, 0, MAX_ACTIONS*sizeof(char*));
	memset(argv, 0, MAX_ACTIONS*sizeof(char*));
	env_L = sr_lua_env_get();
	if(env_L->msg==NULL)
		goto error;

#if 0
	app_lua_dump_stack(L);
#endif
	argc = lua_gettop(L);
	if(argc==0)
	{
		LM_ERR("name of module function not provided\n");
		goto error;
	}
	if(argc>=MAX_ACTIONS)
	{
		LM_ERR("too many parameters\n");
		goto error;
	}
	/* first is function name, then parameters */
	for(i=1; i<=argc; i++)
	{
		if (!lua_isstring(L, i))
		{
			LM_ERR("invalid parameter type (%d)\n", i);
			goto error;
		}
		luav[i-1] = (char*)lua_tostring(L, i);
	}
	/* pkg copy only parameters */
	for(i=1; i<MAX_ACTIONS; i++)
	{
		if(luav[i]!=NULL)
		{
			argv[i] = (char*)pkg_malloc(strlen(luav[i])+1);
			if(argv[i]==NULL)
			{
				LM_ERR("no more pkg\n");
				goto error;
			}
			strcpy(argv[i], luav[i]);
		}
	}

	expf = find_export_record(luav[0], argc-1, 0, &modver);
	if (expf==NULL) {
		LM_ERR("function '%s' is not available\n", luav[0]);
		goto error;
	}
	/* check fixups */
	if (expf->fixup!=NULL && expf->free_fixup==NULL) {
		LM_ERR("function '%s' has fixup - cannot be used\n", luav[0]);
		goto error;
	}
	switch(expf->param_no) {
		case 0:
			mod_type = MODULE0_T;
			break;
		case 1:
			mod_type = MODULE1_T;
			break;
		case 2:
			mod_type = MODULE2_T;
			break;
		case 3:
			mod_type = MODULE3_T;
			break;
		case 4:
			mod_type = MODULE4_T;
			break;
		case 5:
			mod_type = MODULE5_T;
			break;
		case 6:
			mod_type = MODULE6_T;
			break;
		case VAR_PARAM_NO:
			mod_type = MODULEX_T;
			break;
		default:
			LM_ERR("unknown/bad definition for function '%s' (%d params)\n",
					luav[0], expf->param_no);
			goto error;
	}

	act = mk_action(mod_type,  argc+1   /* number of (type, value) pairs */,
					MODEXP_ST, expf,    /* function */
					NUMBER_ST, argc-1,  /* parameter number */
					STRING_ST, argv[1], /* param. 1 */
					STRING_ST, argv[2], /* param. 2 */
					STRING_ST, argv[3], /* param. 3 */
					STRING_ST, argv[4], /* param. 4 */
					STRING_ST, argv[5], /* param. 5 */
					STRING_ST, argv[6]  /* param. 6 */
			);

	if (act==NULL) {
		LM_ERR("action structure could not be created for '%s'\n", luav[0]);
		goto error;
	}

	/* handle fixups */
	if (expf->fixup) {
		if(argc==1)
		{ /* no parameters */
			if(expf->fixup(0, 0)<0)
			{
				LM_ERR("Error in fixup (0) for '%s'\n", luav[0]);
				goto error;
			}
		} else {
			for(i=1; i<argc; i++)
			{
				if(expf->fixup(&(act->val[i+1].u.data), i)<0)
				{
					LM_ERR("Error in fixup (%d) for '%s'\n", i, luav[0]);
					goto error;
				}
				act->val[i+1].type = MODFIXUP_ST;
			}
		}
	}
	init_run_actions_ctx(&ra_ctx);
	ret = do_action(&ra_ctx, act, env_L->msg);

	/* free fixups */
	if (expf->fixup) {
		for(i=1; i<argc; i++)
		{
			if ((act->val[i+1].type == MODFIXUP_ST) && (act->val[i+1].u.data))
			{
				expf->free_fixup(&(act->val[i+1].u.data), i);
			}
		}
	}
	pkg_free(act);
	lua_pushinteger(L, ret);
	return 1;

error:
	if(act!=NULL)
		pkg_free(act);
	for(i=0; i<MAX_ACTIONS; i++)
	{
		if(argv[i]!=NULL) pkg_free(argv[i]);
		argv[i] = 0;
	}
	lua_pushinteger(L, -1);
	return 1;
}
Esempio n. 28
0
/* sets the value of a variable but does not commit the change
 *
 * return value:
 *   0: success
 *  -1: error
 *   1: variable has not been found
 */
int cfg_set_delayed(cfg_ctx_t *ctx, str *group_name, str *var_name,
			void *val, unsigned int val_type)
{
	cfg_group_t	*group;
	cfg_mapping_t	*var;
	void		*v;
	char		*temp_handle;
	int		temp_handle_created;
	cfg_changed_var_t	*changed = NULL;
	int		size;
	str		s;

	if (!cfg_shmized)
		/* the cfg has not been shmized yet, there is no
		point in registering the change and committing it later */
		return cfg_set_now(ctx, group_name, var_name,
					val, val_type);

	if (!ctx) {
		LOG(L_ERR, "ERROR: cfg_set_delayed(): context is undefined\n");
		return -1;
	}

	/* look-up the group and the variable */
	if (cfg_lookup_var(group_name, var_name, &group, &var))
		return 1;

	/* check whether the variable is read-only */
	if (var->def->type & CFG_READONLY) {
		LOG(L_ERR, "ERROR: cfg_set_delayed(): variable is read-only\n");
		goto error0;
	}

	/* check whether we have to convert the type */
	if (convert_val(val_type, val, CFG_INPUT_TYPE(var), &v))
		goto error0;

	if ((CFG_INPUT_TYPE(var) == CFG_INPUT_INT) 
	&& (var->def->min || var->def->max)) {
		/* perform a simple min-max check for integers */
		if (((int)(long)v < var->def->min)
		|| ((int)(long)v > var->def->max)) {
			LOG(L_ERR, "ERROR: cfg_set_delayed(): integer value is out of range\n");
			goto error0;
		}
	}

	/* the ctx must be locked while reading and writing
	the list of changed variables */
	CFG_CTX_LOCK(ctx);

	if (var->def->on_change_cb) {
		/* The fixup function must see also the
		not yet committed values, so a temporary handle
		must be prepared that points to the new config.
		Only the values within the group are applied,
		other modifications are not visible to the callback.
		The local config is the base. */

		if (ctx->changed_first) {
			temp_handle = (char *)pkg_malloc(group->size);
			if (!temp_handle) {
				LOG(L_ERR, "ERROR: cfg_set_delayed(): "
					"not enough memory\n");
				goto error;
			}
			temp_handle_created = 1;
			memcpy(temp_handle, *(group->handle), group->size);

			/* apply the changes */
			for (	changed = ctx->changed_first;
				changed;
				changed = changed->next
			) {
				if (changed->group != group) continue;

				memcpy(	temp_handle + changed->var->offset,
					changed->new_val.vraw,
					cfg_var_size(changed->var));
			}
		} else {
			/* there is not any change */
			temp_handle = *(group->handle);
			temp_handle_created = 0;
		}
			
		if (var->def->on_change_cb(temp_handle,
						group_name,
						var_name,
						&v) < 0) {
			LOG(L_ERR, "ERROR: cfg_set_delayed(): fixup failed\n");
			if (temp_handle_created) pkg_free(temp_handle);
			goto error;
		}
		if (temp_handle_created) pkg_free(temp_handle);

	}

	/* everything went ok, we can add the new value to the list */
	size = sizeof(cfg_changed_var_t) -
			sizeof(((cfg_changed_var_t*)0)->new_val) + cfg_var_size(var);
	changed = (cfg_changed_var_t *)shm_malloc(size);
	if (!changed) {
		LOG(L_ERR, "ERROR: cfg_set_delayed(): not enough shm memory\n");
		goto error;
	}
	memset(changed, 0, size);
	changed->group = group;
	changed->var = var;

	switch (CFG_VAR_TYPE(var)) {

	case CFG_VAR_INT:
		changed->new_val.vint = (int)(long)v;
		break;

	case CFG_VAR_STRING:
		/* clone the string to shm mem */
		s.s = v;
		s.len = (s.s) ? strlen(s.s) : 0;
		if (cfg_clone_str(&s, &s)) goto error;
		changed->new_val.vp = s.s;
		break;

	case CFG_VAR_STR:
		/* clone the string to shm mem */
		s = *(str *)v;
		if (cfg_clone_str(&s, &s)) goto error;
		changed->new_val.vstr=s;
		break;

	case CFG_VAR_POINTER:
		changed->new_val.vp=v;
		break;

	}

	/* Add the new item to the end of the linked list,
	The commit will go though the list from the first item,
	so the list is kept in order */
	if (ctx->changed_first)
		ctx->changed_last->next = changed;
	else
		ctx->changed_first = changed;

	ctx->changed_last = changed;

	CFG_CTX_UNLOCK(ctx);

	if (val_type == CFG_VAR_INT)
		LOG(L_INFO, "INFO: cfg_set_delayed(): %.*s.%.*s "
			"is going to be changed to %d "
			"[context=%p]\n",
			group_name->len, group_name->s,
			var_name->len, var_name->s,
			(int)(long)val,
			ctx);

	else if (val_type == CFG_VAR_STRING)
		LOG(L_INFO, "INFO: cfg_set_delayed(): %.*s.%.*s "
			"is going to be changed to \"%s\" "
			"[context=%p]\n",
			group_name->len, group_name->s,
			var_name->len, var_name->s,
			(char *)val,
			ctx);

	else /* str type */
		LOG(L_INFO, "INFO: cfg_set_delayed(): %.*s.%.*s "
			"is going to be changed to \"%.*s\" "
			"[context=%p]\n",
			group_name->len, group_name->s,
			var_name->len, var_name->s,
			((str *)val)->len, ((str *)val)->s,
			ctx);

	convert_val_cleanup();
	return 0;

error:
	CFG_CTX_UNLOCK(ctx);
	if (changed) shm_free(changed);
error0:
	LOG(L_ERR, "ERROR: cfg_set_delayed(): failed to set the variable: %.*s.%.*s\n",
			group_name->len, group_name->s,
			var_name->len, var_name->s);

	convert_val_cleanup();
	return -1;
}
Esempio n. 29
0
struct lb_res_str_list *parse_resources_list(char *r_list, int has_val)
{
	struct lb_res_str_list *lb_rl;
	unsigned int n;
	unsigned int len;
	char *p;
	char *s;
	char *end;
	str name;
	str val;

	/* validate and count */
	n = 0;
	len = 0;

	p = r_list;
	do {
		/* eat spaces */
		for( ; *p && isspace(*p) ; p++);
		if (!*p) break;
		/* name and value */
		end = strchr(p,';');
		if (end)
			*end = 0;
		name.s = p;
		p = strchr(p,'=');
		if (end)
			*end = ';';
		if (p) {
			if (!has_val) {
				LM_ERR("resource must not has value!\n");
				goto error;
			}
		} else {
			if (has_val) {
				LM_ERR("resource must has value!\n");
				goto error;
			}
			p = end?end:(r_list+strlen(r_list));
		}
		for(; (p-1)!=name.s && isspace(*(p-1)) ; p-- );
		if (p==name.s) {
			LM_ERR("empty resource name around %d\n",(unsigned int)(p-r_list));
			goto error;
		}
		name.len = p-name.s;
		/* mark */
		n++;
		len += name.len;
		/* next */
		p = end+1;
	} while(end && *p);

	if (n==0) {
		LM_ERR("empty list of resorces\n");
		goto error;
	}
	LM_DBG("discovered %d resources\n",n);

	/* allocate stuff*/
	lb_rl = (struct lb_res_str_list *)pkg_malloc
		(sizeof(struct lb_res_str_list) + n*sizeof(struct lb_res_str) + len);
	if (lb_rl==NULL) {
		LM_ERR("no more pkg memory\n");
		goto error;
	}

	/* init the strucuture */
	lb_rl->n = n;
	lb_rl->resources =(struct lb_res_str*)(lb_rl+1);
	s = (char*)(lb_rl->resources + n);


	/* fill in the structures*/
	p = r_list;
	n = 0;
	do {
		/* eat spaces */
		for( ; *p && isspace(*p) ; p++);
		if (!*p) break;
		/* name .... */
		end = strchr(p,';');
		if (end)
			*end = 0;
		name.s = p;
		val.s = 0;
		p = strchr(p,'=');
		if (end)
			*end = ';';
		if (!p) {
			p = end?end:(r_list+strlen(r_list));
		} else {
			val.s = p+1;
		}
		for(; (p-1)!=name.s && isspace(*(p-1)) ; p-- );
		name.len = p-name.s;
		lb_rl->resources[n].name.len = name.len;
		lb_rl->resources[n].name.s = s;
		memcpy( s, name.s, name.len );
		s += name.len;
		/* ....and value */
		if (has_val) {
			/* eat spaces */
			for( ; *val.s && isspace(*val.s) ; val.s++);
			if (!*val.s) {
				LM_ERR("empty val !\n");
				goto error1;
			}
			val.len = ( end?end:(r_list+strlen(r_list)) ) - val.s;
			for( ; isspace(val.s[val.len-1]) ; val.len--);
			if (str2int( &val , &lb_rl->resources[n].val)!=0) {
				LM_ERR("invalid value [%.*s]\n",val.len,val.s);
				goto error1;
			}
		} else {
			lb_rl->resources[n].val = 0;
		}
		/* next */
		n++;
		p = end+1;
	} while(end && *p);

	return lb_rl;

error1:
	pkg_free(lb_rl);
error:
	return NULL;
}
Esempio n. 30
0
/*
 * call it with a vb initialized to 0
 * returns: pointer after the parsed parts and sets vb->error
 * WARNING: don't forget to cleanup on error with free_via_list(vb)!
 */
char* parse_via(char* buffer, char* end, struct via_body *vbody)
{
	char* tmp;
	char* param_start;
	unsigned char state;
	unsigned char saved_state;
	int c_nest;
	int err;
	struct via_body* vb;
	struct via_param* param;

	vb=vbody; /* keep orignal vbody value, needed to set the error member
				 in case of multiple via bodies in the same header */
parse_again:
	vb->error=PARSE_ERROR;
	/* parse start of via ( SIP/2.0/UDP    )*/
	state=F_SIP;
	saved_state=0; /*it should generate error if it's used without set*/
	param_start=0;
	for(tmp=buffer;tmp<end;tmp++){
		switch(*tmp){
			case ' ':
			case'\t':
				switch(state){
					case L_VER: /* eat space */
					case L_PROTO:
					case F_SIP:
					case F_VER:
					case F_PROTO:
						break;
					case FIN_UDP:
						vb->transport.len=tmp-vb->transport.s;
						vb->proto=PROTO_UDP;
						state=F_HOST; /* start looking for host*/
						goto main_via;
					case FIN_TCP:
						/* finished proto parsing */
						vb->transport.len=tmp-vb->transport.s;
						vb->proto=PROTO_TCP;
						state=F_HOST; /* start looking for host*/
						goto main_via;
					case FIN_TLS:
						/* finished proto parsing */
						vb->transport.len=tmp-vb->transport.s;
						vb->proto=PROTO_TLS;
						state=F_HOST; /* start looking for host*/
						goto main_via;
					case FIN_SCTP:
						/* finished proto parsing */
						vb->transport.len=tmp-vb->transport.s;
						vb->proto=PROTO_SCTP;
						state=F_HOST; /* start looking for host*/
						goto main_via;
					case FIN_SIP:
						vb->name.len=tmp-vb->name.s;
						state=L_VER;
						break;
					case FIN_VER:
						vb->version.len=tmp-vb->version.s;
						state=L_PROTO;
						break;
					case F_LF:
					case F_CRLF:
					case F_CR: /* header continues on this line */
						state=saved_state;
						break;
					default:
						LM_ERR("bad char <%c> on state %d\n", *tmp, state);
						goto parse_error;
				}
				break;
			case '\n':
				switch(state){
					case L_VER:
					case F_SIP:
					case F_VER:
					case F_PROTO:
					case L_PROTO:
						saved_state=state;
						state=F_LF;
						break;
					case FIN_UDP:
						vb->transport.len=tmp-vb->transport.s;
						vb->proto=PROTO_UDP;
						state=F_LF;
						saved_state=F_HOST; /* start looking for host*/
						goto main_via;
					case FIN_TCP:
						vb->transport.len=tmp-vb->transport.s;
						vb->proto=PROTO_TCP;
						state=F_LF;
						saved_state=F_HOST; /* start looking for host*/
						goto main_via;
					case FIN_TLS:
						vb->transport.len=tmp-vb->transport.s;
						vb->proto=PROTO_TLS;
						state=F_LF;
						saved_state=F_HOST; /* start looking for host*/
						goto main_via;
					case FIN_SIP:
						vb->name.len=tmp-vb->name.s;
						state=F_LF;
						saved_state=L_VER;
						break;
					case FIN_VER:
						vb->version.len=tmp-vb->version.s;
						state=F_LF;
						saved_state=L_PROTO;
						break;
					case F_CR:
						state=F_CRLF;
						break;
					case F_LF:
					case F_CRLF:
						state=saved_state;
						goto endofheader;
					default:
						LM_ERR("bad char <%c> on state %d\n", *tmp, state);
						goto parse_error;
				}
				break;
			case '\r':
				switch(state){
					case L_VER:
					case F_SIP:
					case F_VER:
					case F_PROTO:
					case L_PROTO:
						saved_state=state;
						state=F_CR;
						break;
					case FIN_UDP:
						vb->transport.len=tmp-vb->transport.s;
						vb->proto=PROTO_UDP;
						state=F_CR;
						saved_state=F_HOST;
						goto main_via;
					case FIN_TCP:
						vb->transport.len=tmp-vb->transport.s;
						vb->proto=PROTO_TCP;
						state=F_CR;
						saved_state=F_HOST;
						goto main_via;
					case FIN_TLS:
						vb->transport.len=tmp-vb->transport.s;
						vb->proto=PROTO_TLS;
						state=F_CR;
						saved_state=F_HOST;
						goto main_via;
					case FIN_SIP:
						vb->name.len=tmp-vb->name.s;
						state=F_CR;
						saved_state=L_VER;
						break;
					case FIN_VER:
						vb->version.len=tmp-vb->version.s;
						state=F_CR;
						saved_state=L_PROTO;
						break;
					case F_LF: /*end of line ?next header?*/
					case F_CR:
					case F_CRLF:
						state=saved_state;
						goto endofheader;
					default:
						LM_ERR("bad char <%c> on state %d\n", *tmp, state);
						goto parse_error;
				}
				break;
			
			case '/':
				switch(state){
					case FIN_SIP:
						vb->name.len=tmp-vb->name.s;
						state=F_VER;
						break;
					case FIN_VER:
						vb->version.len=tmp-vb->version.s;
						state=F_PROTO;
						break;
					case L_VER:
						state=F_VER;
						break;
					case L_PROTO:
						state=F_PROTO;
						break;
					default:
						LM_ERR("bad char <%c> on state %d\n", *tmp, state);
						goto parse_error;
				}
				break;
				/* match SIP*/
			case 'S':
			case 's':
				switch(state){
					case F_SIP:
						state=SIP1;
						vb->name.s=tmp;
						break;
					case TLS2:
						state=FIN_TLS;
						break;
					case F_PROTO:
						state=SCTP1;
						vb->transport.s=tmp;
						break;
					default:
						LM_ERR("bad char <%c> on state %d\n", *tmp, state);
						goto parse_error;
				}
				break;
			case 'I':
			case 'i':
				switch(state){
					case SIP1:
						state=SIP2;
						break;
					default:
						LM_ERR("bad char <%c> on state %d\n", *tmp, state);
						goto parse_error;
				}
				break;
			case 'p':
			case 'P':
				switch(state){
					case SIP2:
						state=FIN_SIP;
						break;
					/* allow p in PROTO */
					case UDP2:
						state=FIN_UDP;
						break;
					case TCP2:
						state=FIN_TCP;
						break;
					case SCTP3:
						state=FIN_SCTP;
						break;
					default:
						LM_ERR("bad char <%c> on state %d\n", *tmp, state);
						goto parse_error;
				}
				break;
			case 'U':
			case 'u':
				switch(state){
					case F_PROTO:
						state=UDP1;
						vb->transport.s=tmp;
						break;
					default:
						LM_ERR("bad char <%c> on state %d\n", *tmp, state);
						goto parse_error;
				}
				break;
			case 'D':
			case 'd':
				switch(state){
					case UDP1:
						state=UDP2;
						break;
					default:
						LM_ERR("bad char <%c> on state %d\n", *tmp, state);
						goto parse_error;
				}
				break;
			case 'T':
			case 't':
				switch(state){
					case F_PROTO:
						state=TCP_TLS1;
						vb->transport.s=tmp;
						break;
					case SCTP2:
						state=SCTP3;
						break;
					default:
						LM_ERR("bad char <%c> on state %d\n", *tmp, state);
						goto parse_error;
				}
				break;
			case 'C':
			case 'c':
				switch(state){
					case TCP_TLS1:
						state=TCP2;
						break;
					case SCTP1:
						state=SCTP2;
						break;
					default:
						LM_ERR("bad char <%c> on state %d\n", *tmp, state);
						goto parse_error;
				}
				break;
			case 'L':
			case 'l':
				switch(state){
					case TCP_TLS1:
						state=TLS2;
						break;
					default:
						LM_ERR("bad char <%c> on state %d\n", *tmp, state);
						goto parse_error;
				}
				break;
			/*match 2.0*/
			case '2':
				switch(state){
					case F_VER:
						state=VER1;
						vb->version.s=tmp;
						break;
					default:
						LM_ERR("bad char <%c> on state %d\n", *tmp, state);
						goto parse_error;
				}
				break;
			case '.':
				switch(state){
					case VER1:
						state=VER2;
						break;
					default:
						LM_ERR("bad char <%c> on state %d\n", *tmp, state);
						goto parse_error;
				}
				 break;
			case '0':
				switch(state){
					case VER2:
						state=FIN_VER;
						break;
					default:
						LM_ERR("bad char <%c> on state %d\n", *tmp, state);
						goto parse_error;
				}
				break;
			
			default:
						LM_ERR("bad char <%c> on state %d\n", *tmp, state);
						goto parse_error;
				break;
		}
	} /* for tmp*/

	/* we should not be here! if everything is ok > main_via*/
	LM_ERR("bad via: end of packet on state=%d\n", state);
	goto parse_error;

 main_via:
	/* inc tmp to point to the next char*/
	tmp++;
	c_nest=0;
	/*state should always be F_HOST here*/;
	for(;*tmp;tmp++){
		switch(*tmp){
		case ' ':
		case '\t':
			switch(state){
					case F_HOST:/*eat the spaces*/
						break;
					case P_HOST:
						 /*mark end of host*/
						 vb->host.len=tmp-vb->host.s;
						 state=L_PORT;
						 break;
					case L_PORT: /*eat the spaces*/
					case F_PORT:
						break;
					case P_PORT:
						/*end of port */
						vb->port_str.len=tmp-vb->port_str.s;
						state=L_PARAM;
						break;
					case L_PARAM: /* eat the space */
					case F_PARAM:
						break;
					case P_PARAM:
					/*	*tmp=0;*/ /*!?end of param*/
						state=L_PARAM;
						break;
					case L_VIA:
					case F_VIA: /* eat the space */
						break;
					case F_COMMENT:
					case P_COMMENT:
						break;
					case F_IP6HOST: /*no spaces allowed*/
					case P_IP6HOST:
						LM_ERR("bad ipv6 reference\n");
						goto parse_error;
					case F_CRLF:
					case F_LF:
					case F_CR:
						/*previous=crlf and now =' '*/
						state=saved_state;
						break;
					default:
						LM_CRIT("on <%c>, state=%d\n",*tmp, state);
						goto parse_error;
				}
			break;
			case '\n':
				switch(state){
					case F_HOST:/*eat the spaces*/
					case L_PORT: /*eat the spaces*/
					case F_PORT:
					case L_PARAM: /* eat the space */
					case F_PARAM:
					case F_VIA: /* eat the space */
					case L_VIA:
					case F_COMMENT:
					case P_COMMENT:
					case F_IP6HOST:
					case P_IP6HOST:
						saved_state=state;
						state=F_LF;
						break;
					case P_HOST:
						 /*mark end of host*/
						 vb->host.len=tmp-vb->host.s;
						 saved_state=L_PORT;
						 state=F_LF;
						 break;
					case P_PORT:
						/*end of port */
						vb->port_str.len=tmp-vb->port_str.s;
						saved_state=L_PARAM;
						state=F_LF;
						break;
					case P_PARAM:
					/*	*tmp=0;*/ /*!?end of param*/
						saved_state=L_PARAM;
						state=F_LF;
						break;
					case F_CR:
						state=F_CRLF;
						break;
					case F_CRLF:
					case F_LF:
						state=saved_state;
						goto endofheader;
					default:
						LM_CRIT("BUG on <%c>\n",*tmp);
						goto  parse_error;
				}
			break;
		case '\r':
				switch(state){
					case F_HOST:/*eat the spaces*/
					case L_PORT: /*eat the spaces*/
					case F_PORT:
					case L_PARAM: /* eat the space */
					case F_PARAM:
					case F_VIA: /* eat the space */
					case L_VIA:
					case F_COMMENT:
					case P_COMMENT:
					case F_IP6HOST:
					case P_IP6HOST:
						saved_state=state;
						state=F_CR;
						break;
					case P_HOST:
						 /*mark end of host*/
						 vb->host.len=tmp-vb->host.s;
						 saved_state=L_PORT;
						 state=F_CR;
						 break;
					case P_PORT:
						/*end of port */
						vb->port_str.len=tmp-vb->port_str.s;
						saved_state=L_PARAM;
						state=F_CR;
						break;
					case P_PARAM:
					/*	*tmp=0;*/ /*!?end of param*/
						saved_state=L_PARAM;
						state=F_CR;
						break;
					case F_CRLF:
					case F_CR:
					case F_LF:
						state=saved_state;
						goto endofheader;
					default:
						LM_CRIT("on <%c>\n",*tmp);
						goto parse_error;
				}
			break;
			
			case ':':
				switch(state){
					case F_HOST:
					case F_IP6HOST:
						state=P_IP6HOST;
						break;
					case P_IP6HOST:
						break;
					case P_HOST:
						/*mark  end of host*/
						vb->host.len=tmp-vb->host.s;
						state=F_PORT;
						break;
					case L_PORT:
						state=F_PORT;
						break;
					case P_PORT:
						LM_ERR("bad port\n");
						goto parse_error;
					case L_PARAM:
					case F_PARAM:
					case P_PARAM:
						LM_ERR("bad char <%c> in state %d\n",
							*tmp,state);
						goto parse_error;
					case L_VIA:
					case F_VIA:
						LM_ERR("bad char in compact via\n");
						goto parse_error;
					case F_CRLF:
					case F_LF:
					case F_CR:
						/*previous=crlf and now !=' '*/
						goto endofheader;
					case F_COMMENT:/*everything is allowed in a comment*/
						vb->comment.s=tmp;
						state=P_COMMENT;
						break;
					case P_COMMENT: /*everything is allowed in a comment*/
						break;
					default:
						LM_CRIT("on <%c> state %d\n", *tmp, state);
						goto parse_error;
				}
				break;
			case ';':
				switch(state){
					case F_HOST:
					case F_IP6HOST:
						LM_ERR(" no host found\n");
						goto parse_error;
					case P_IP6HOST:
						LM_ERR(" bad ipv6 reference\n");
						goto parse_error;
					case P_HOST:
						vb->host.len=tmp-vb->host.s;
						state=F_PARAM;
						param_start=tmp+1;
						break;
					case P_PORT:
						/*mark the end*/
						vb->port_str.len=tmp-vb->port_str.s;
					case L_PORT:
					case L_PARAM:
						state=F_PARAM;
						param_start=tmp+1;
						break;
					case F_PORT:
						LM_ERR(" bad char <%c> in state %d\n",
							*tmp,state);
						goto parse_error;
					case F_PARAM:
						LM_ERR("null param?\n");
						goto parse_error;
					case P_PARAM:
						/*hmm next, param?*/
						state=F_PARAM;
						param_start=tmp+1;
						break;
					case L_VIA:
					case F_VIA:
						LM_ERR("bad char <%c> in next via\n", *tmp);
						goto parse_error;
					case F_CRLF:
					case F_LF:
					case F_CR:
						/*previous=crlf and now !=' '*/
						goto endofheader;
					case F_COMMENT:/*everything is allowed in a comment*/
						vb->comment.s=tmp;
						state=P_COMMENT;
						break;
					case P_COMMENT: /*everything is allowed in a comment*/
						break;
					
					default:
						LM_CRIT("on <%c> state %d\n", *tmp, state);
						goto parse_error;
				}
			break;
			case ',':
				switch(state){
					case F_HOST:
					case F_IP6HOST:
						LM_ERR("no host found\n");
						goto parse_error;
					case P_IP6HOST:
						LM_ERR(" bad ipv6 reference\n");
						goto parse_error;
					case P_HOST:
						/*mark the end*/
						vb->host.len=tmp-vb->host.s;
						state=F_VIA;
						break;
					case P_PORT:
						/*mark the end*/
						vb->port_str.len=tmp-vb->port_str.s;
						state=F_VIA;
						break;
					case L_PORT:
					case L_PARAM:
					case P_PARAM:
					case L_VIA:
						state=F_VIA;
						break;
					case F_PORT:
					case F_PARAM:
						LM_ERR("invalid char <%c> in state %d\n", *tmp,state);
						goto parse_error;
					case F_VIA:
						/* do  nothing,  eat ","*/
						break;	
					case F_CRLF:
					case F_LF:
					case F_CR:
						/*previous=crlf and now !=' '*/
						goto endofheader;
					case F_COMMENT:/*everything is allowed in a comment*/
						vb->comment.s=tmp;
						state=P_COMMENT;
						break;
					case P_COMMENT: /*everything is allowed in a comment*/
						break;
					default:
						LM_CRIT("on <%c> state %d\n",*tmp, state);
						goto  parse_error;
				}
			break;
			case '(':
				switch(state){
					case F_HOST:
					case F_PORT:
					case F_PARAM:
					case F_VIA:
					case F_IP6HOST:
					case P_IP6HOST: /*must be terminated in ']'*/
						LM_ERR(" on <%c> state %d\n", *tmp, state);
						goto  parse_error;
					case P_HOST:
						/*mark the end*/
						vb->host.len=tmp-vb->host.s;
						state=F_COMMENT;
						c_nest++;
						break;
					case P_PORT:
						/*mark the end*/
						vb->port_str.len=tmp-vb->port_str.s;
						state=F_COMMENT;
						c_nest++;
						break;
					case P_PARAM:
						/*mark the end*/
						vb->params.len=tmp-vb->params.s;
						state=F_COMMENT;
						c_nest++;
						break;
					case L_PORT:
					case L_PARAM:
					case L_VIA:
						state=F_COMMENT;
						vb->params.len=tmp-vb->params.s;
						c_nest++;
						break;
					case P_COMMENT:
					case F_COMMENT:
						c_nest++;
						break;
					case F_CRLF:
					case F_LF:
					case F_CR:
						/*previous=crlf and now !=' '*/
						goto endofheader;
					default:
						LM_CRIT("on <%c> state %d\n", *tmp, state);
						goto  parse_error;
				}
			break;
			case ')':
				switch(state){
					case F_COMMENT:
					case P_COMMENT:
						if (c_nest){
							c_nest--;
							if(c_nest==0){
								state=L_VIA;
								vb->comment.len=tmp-vb->comment.s;
								break;
							}
						}else{
							LM_ERR(" missing '(' - nesting= %d\n", c_nest);
							 goto parse_error;
						}
						break;
					case F_HOST:
					case F_PORT:
					case F_PARAM:
					case F_VIA:
					case P_HOST:
					case P_PORT:
					case P_PARAM:
					case L_PORT:
					case L_PARAM:
					case L_VIA:
					case F_IP6HOST:
					case P_IP6HOST:
						LM_ERR(" on <%c> state %d\n",*tmp, state);
						goto  parse_error;
					case F_CRLF:
					case F_LF:
					case F_CR:
						/*previous=crlf and now !=' '*/
						goto endofheader;
					default:
						LM_CRIT("on <%c> state %d\n", *tmp, state);
						goto  parse_error;
				}
				break;
			case '[':
				switch(state){
					case F_HOST:
						vb->host.s=tmp; /* mark start here (include [])*/
						state=F_IP6HOST;
						break;
					case F_COMMENT:/*everything is allowed in a comment*/
						vb->comment.s=tmp;
						state=P_COMMENT;
						break;
					case P_COMMENT:
						break;
					case F_CRLF:
					case F_LF:
					case F_CR:
						/*previous=crlf and now !=' '*/
						goto endofheader;
					default:
						LM_ERR("on <%c> state %d\n",*tmp, state);
						goto  parse_error;
				}
				break;
			case ']':
				switch(state){
					case P_IP6HOST:
						/*mark the end*/
						vb->host.len=(tmp-vb->host.s)+1; /* include "]" */
						state=L_PORT;
						break;
					case F_CRLF:
					case F_LF:
					case F_CR:
						/*previous=crlf and now !=' '*/
						goto endofheader;
					case F_COMMENT:/*everything is allowed in a comment*/
						vb->comment.s=tmp;
						state=P_COMMENT;
						break;
					case P_COMMENT:
						break;
					default:
						LM_ERR("on <%c> state %d\n",*tmp, state);
						goto  parse_error;
				}
				break;
						
			default:
				switch(state){
					case F_HOST:
						state=P_HOST;
						vb->host.s=tmp;
						//break;
					case P_HOST:
						/*check if host allowed char*/
						if ( (*tmp<'a' || *tmp>'z') && (*tmp<'A' || *tmp>'Z')
						&& (*tmp<'0' || *tmp>'9') && *tmp!='-' && *tmp!='.')
							goto parse_error;
						break;
					case F_PORT:
						state=P_PORT;
						vb->port_str.s=tmp;
						//break;
					case P_PORT:
						/*check if number*/
						if ( *tmp<'0' || *tmp>'9' )
							goto parse_error;
						break;
					case F_PARAM:
						/*state=P_PARAM*/;
						if(vb->params.s==0) vb->params.s=param_start;
						param=pkg_malloc(sizeof(struct via_param));
						if (param==0){
							LM_ERR("no pkg memory left\n");
							goto error;
						}
						memset(param,0, sizeof(struct via_param));
						param->start=param_start;
						tmp=parse_via_param(tmp, end, &state, &saved_state,
											param);

						switch(state){
							case F_PARAM:
								param_start=tmp+1;
							case L_PARAM:
							case F_LF:
							case F_CR:
								vb->params.len=tmp - vb->params.s;
								break;
							case F_VIA:
								vb->params.len=param->start+param->size
												-vb->params.s;
								break;
							case END_OF_HEADER:
								vb->params.len=param->start+param->size
												-vb->params.s;
								break;
							case PARAM_ERROR:
								pkg_free(param);
								goto parse_error;
							default:
								pkg_free(param);
								LM_ERR(" after parse_via_param: invalid "
										"char <%c> on state %d\n",*tmp, state);
								goto parse_error;
						}
						/*add param to the list*/
						if (vb->last_param)	vb->last_param->next=param;
						else				vb->param_lst=param;
						vb->last_param=param;
						/* update param. shortcuts */
						switch(param->type){
							case PARAM_BRANCH:
								vb->branch=param;
								break;
							case PARAM_RECEIVED:
								vb->received=param;
								break;
							case PARAM_RPORT:
								vb->rport=param;
								break;
							case PARAM_I:
								vb->i=param;
								break;
							case PARAM_ALIAS:
								vb->alias=param;
								break;
							case PARAM_MADDR:
								vb->maddr=param;
								break;
						}
						
						if (state==END_OF_HEADER){
							state=saved_state;
							goto endofheader;
						}
						break;
					case P_PARAM:
						break;
					case F_VIA:
						/*vb->next=tmp;*/ /*???*/
						goto nextvia;
					case L_PORT:
					case L_PARAM:
					case L_VIA:
						LM_ERR("on <%c> state %d (default)\n",*tmp, state);
						goto  parse_error;
					case F_COMMENT:
						state=P_COMMENT;
						vb->comment.s=tmp;
						break;
					case P_COMMENT:
						break;
					case F_IP6HOST:
						state=P_IP6HOST;
						//break;
					case P_IP6HOST:
						/*check if host allowed char*/
						if ( (*tmp<'a' || *tmp>'f') && (*tmp<'A' || *tmp>'F')
						&& (*tmp<'0' || *tmp>'9') && *tmp!=':')
							goto parse_error;
						break;
					case F_CRLF:
					case F_LF:
					case F_CR:
						/*previous=crlf and now !=' '*/
						goto endofheader;
					default:
						LM_CRIT("invalid char <%c> in state %d\n",*tmp, state);
						goto parse_error;
				}


		}
	}

	LM_DBG("end of packet reached, state=%d\n", state);
	goto endofpacket; /*end of packet, probably should be goto error*/
	
endofheader:
	state=saved_state;
	LM_DBG("end of header reached, state=%d\n", state);
endofpacket:
	/* check if error*/
	switch(state){
		case P_HOST:
		case L_PORT:
		case P_PORT:
		case L_PARAM:
		case P_PARAM:
		case P_VALUE:
		case GEN_PARAM:
		case FIN_HIDDEN:
		case L_VIA:
			break;
		default:
			LM_ERR(" invalid via - end of header in state %d\n", state);
			goto parse_error;
	}


	/*
	if (proto) printf("<SIP/2.0/%s>\n", proto);
	if (host) printf("host= <%s>\n", host);
	if (port_str) printf("port= <%s>\n", port_str);
	if (param) printf("params= <%s>\n", param);
	if (comment) printf("comment= <%s>\n", comment);
	if(next_via) printf("next_via= <%s>\n", next_via);
	*/
	/*LM_DBG("rest=<%s>\n", tmp);*/

	vb->error=PARSE_OK;
	vb->bsize=tmp-buffer;
	if (vb->port_str.s){
		vb->port=str2s(vb->port_str.s, vb->port_str.len, &err);
		if (err){
					LM_ERR(" invalid port number <%.*s>\n",
						vb->port_str.len, ZSW(vb->port_str.s));
					goto parse_error;
		}
	}
	return tmp;
nextvia:
	LM_DBG("next_via\n");
	vb->error=PARSE_OK;
	vb->bsize=tmp-buffer;
	if (vb->port_str.s){
		vb->port=str2s(vb->port_str.s, vb->port_str.len, &err);
		if (err){
					LM_ERR(" invalid port number <%.*s>\n",
						vb->port_str.len, ZSW(vb->port_str.s));
					goto parse_error;
		}
	}
	vb->next=pkg_malloc(sizeof(struct via_body));
	if (vb->next==0){
		LM_ERR(" out of pkg memory\n");
		goto error;
	}
	vb=vb->next;
	memset(vb, 0, sizeof(struct via_body));
	buffer=tmp;
	goto parse_again;

parse_error:
	if (end>buffer){
		LM_ERR(" <%.*s>\n", (int)(end-buffer), ZSW(buffer));
	}
	if ((tmp>buffer)&&(tmp<end)){
		LM_ERR("parsed so far:<%.*s>\n",
				(int)(tmp-buffer), ZSW(buffer) );
	}else{
		LM_ERR("via parse failed\n");
	}
error:
	vb->error=PARSE_ERROR;
	vbody->error=PARSE_ERROR; /* make sure the first via body is marked
								 as bad also */
	return tmp;
}