Example #1
0
/*
 * Used when converting values to be used in a DB query
 */
int db_mysql_val2str(const db_con_t* _c, const db_val_t* _v, char* _s, int* _len)
{
	int l;
	char* old_s;

	if (!_c || !_v || !_s || !_len || !*_len) {
		LM_ERR("invalid parameter value\n");
		return -1;
	}

	if (VAL_NULL(_v)) {
		if (*_len < sizeof("NULL")) {
			LM_ERR("buffer too small\n");
			return -1;
		}
		*_len = snprintf(_s, *_len, "NULL");
		return 0;
	}
	
	switch(VAL_TYPE(_v)) {
	case DB_INT:
		if (db_int2str(VAL_INT(_v), _s, _len) < 0) {
			LM_ERR("error while converting string to int\n");
			return -2;
		} else {
			return 0;
		}
		break;

	case DB_BIGINT:
		if (db_bigint2str(VAL_BIGINT(_v), _s, _len) < 0) {
			LM_ERR("error while converting bigint to string\n");
			return -2;
		} else {
			return 0;
		}
		break;


	case DB_BITMAP:
		if (db_int2str(VAL_BITMAP(_v), _s, _len) < 0) {
			LM_ERR("error while converting string to int\n");
			return -3;
		} else {
			return 0;
		}
		break;

	case DB_DOUBLE:
		if (db_double2str(VAL_DOUBLE(_v), _s, _len) < 0) {
			LM_ERR("error while converting string to double\n");
			return -4;
		} else {
			return 0;
		}
		break;

	case DB_STRING:
		l = strlen(VAL_STRING(_v));
		if (*_len < (l * 2 + 3)) {
			LM_ERR("destination buffer too short\n");
			return -5;
		} else {
			old_s = _s;
			*_s++ = '\'';
			_s += mysql_real_escape_string(CON_CONNECTION(_c), _s, VAL_STRING(_v), l);
			*_s++ = '\'';
			*_s = '\0'; /* FIXME */
			*_len = _s - old_s;
			return 0;
		}
		break;

	case DB_STR:
		if (*_len < (VAL_STR(_v).len * 2 + 3)) {
			LM_ERR("destination buffer too short\n");
			return -6;
		} else {
			old_s = _s;
			*_s++ = '\'';
			_s += mysql_real_escape_string(CON_CONNECTION(_c), _s, VAL_STR(_v).s, VAL_STR(_v).len);
			*_s++ = '\'';
			*_s = '\0';
			*_len = _s - old_s;
			return 0;
		}
		break;

	case DB_DATETIME:
		if (db_time2str(VAL_TIME(_v), _s, _len) < 0) {
			LM_ERR("error while converting string to time_t\n");
			return -7;
		} else {
			return 0;
		}
		break;

	case DB_BLOB:
		l = VAL_BLOB(_v).len;
		if (*_len < (l * 2 + 3)) {
			LM_ERR("destination buffer too short\n");
			return -8;
		} else {
			old_s = _s;
			*_s++ = '\'';
			_s += mysql_real_escape_string(CON_CONNECTION(_c), _s, VAL_STR(_v).s, l);
			*_s++ = '\'';
			*_s = '\0';
			*_len = _s - old_s;
			return 0;
		}			
		break;

	default:
		LM_DBG("unknown data type\n");
		return -9;
	}
	/*return -8; --not reached*/
}
Example #2
0
File: val.c Project: NormB/opensips
/*
 * Used when converting result from a query
 */
int db_postgres_val2str(const db_con_t* _con, const db_val_t* _v,
														char* _s, int* _len)
{
	int l, ret;
	int pgret;
	char *tmp_s;
	size_t tmp_len;
	char* old_s;

	if ((!_v) || (!_s) || (!_len) || (!*_len)) {
		LM_ERR("invalid parameter value\n");
		return -1;
	}

	if (VAL_NULL(_v)) {
		if ( *_len < (l=(int)sizeof("NULL")-1)) {
			LM_ERR("buffer too short to print NULL\n");
			return -1;
		}
		memcpy(_s, "NULL", l);
		*_len = l;
		return 0;
	}

	switch(VAL_TYPE(_v)) {
	case DB_INT:
		if (db_int2str(VAL_INT(_v), _s, _len) < 0) {
			LM_ERR("failed to convert string to int\n");
			return -2;
		} else {
			return 0;
		}
		break;

	case DB_BIGINT:
		if (db_bigint2str(VAL_BIGINT(_v), _s, _len) < 0) {
			LM_ERR("failed to convert string to big int\n");
			return -2;
		} else {
			return 0;
		}
		break;

	case DB_BITMAP:
		if (db_int2str(VAL_BITMAP(_v), _s, _len) < 0) {
			LM_ERR("failed to convert string to int\n");
			return -3;
		} else {
			return 0;
		}
		break;

	case DB_DOUBLE:
		if (db_double2str(VAL_DOUBLE(_v), _s, _len) < 0) {
			LM_ERR("failed to convert string to double\n");
			return -3;
		} else {
			return 0;
		}
		break;

	case DB_STRING:
		l = strlen(VAL_STRING(_v));
		if (*_len < (l * 2 + 3)) {
			LM_ERR("destination STRING buffer too short (have %d, need %d)\n",
			       *_len, l * 2 + 3);
			return -4;
		} else {
			old_s = _s;
			*_s++ = '\'';
			ret = PQescapeStringConn(CON_CONNECTION(_con), _s, VAL_STRING(_v),
					l, &pgret);
			if(pgret!=0)
			{
				LM_ERR("PQescapeStringConn failed\n");
				return -4;
			}
			LM_DBG("PQescapeStringConn: in: %d chars,"
				" out: %d chars\n", l, ret);
			_s += ret;
			*_s++ = '\'';
			*_s = '\0'; /* FIXME */
			*_len = _s - old_s;
			return 0;
		}
		break;

	case DB_STR:
		l = VAL_STR(_v).len;
		if (*_len < (l * 2 + 3)) {
			LM_ERR("destination STR buffer too short (have %d, need %d)\n",
			       *_len, l * 2 + 3);
			return -5;
		} else {
			old_s = _s;
			*_s++ = '\'';
			ret = PQescapeStringConn(CON_CONNECTION(_con), _s, VAL_STRING(_v),
					l, &pgret);
			if(pgret!=0)
			{
				LM_ERR("PQescapeStringConn failed \n");
				return -5;
			}
	        LM_DBG("PQescapeStringConn: in: %d chars, out: %d chars\n", l, ret);
			_s += ret;
			*_s++ = '\'';
			*_s = '\0'; /* FIXME */
			*_len = _s - old_s;
			return 0;
		}
		break;

	case DB_DATETIME:
		if (db_time2str(VAL_TIME(_v), _s, _len) < 0) {
			LM_ERR("failed to convert string to time_t\n");
			return -6;
		} else {
			return 0;
		}
		break;

	case DB_BLOB:
		l = VAL_BLOB(_v).len;
		/* this estimation is not always correct, thus we need to check later again */
		if (*_len < (l * 2 + 3)) {
			LM_ERR("destination BLOB buffer too short (have %d, need %d)\n",
			       *_len, l * 2 + 3);
			return -7;
		} else {
			*_s++ = '\'';
			tmp_s = (char*)PQescapeByteaConn(CON_CONNECTION(_con), (unsigned char*)VAL_STRING(_v),
					(size_t)l, (size_t*)&tmp_len);
			if(tmp_s==NULL)
			{
				LM_ERR("PQescapeBytea failed\n");
				return -7;
			}
			if (tmp_len > *_len) {
				LM_ERR("escaped result too long\n");
				return -7;
			}
			memcpy(_s, tmp_s, tmp_len);
			PQfreemem(tmp_s);
			tmp_len = strlen(_s);
			*(_s + tmp_len) = '\'';
			*(_s + tmp_len + 1) = '\0';
			*_len = tmp_len + 2;
			return 0;
		}
		break;

	default:
		LM_DBG("unknown data type\n");
		return -7;
	}
}
Example #3
0
/*!
 * \brief Get all contacts from the database, in partitions if wanted
 * \see get_all_ucontacts
 * \param buf target buffer
 * \param len length of buffer
 * \param flags contact flags
 * \param part_idx part index
 * \param part_max maximal part
 * \param GAU options
 * \return 0 on success, positive if buffer size was not sufficient, negative on failure
 */
static inline int get_all_db_ucontacts(void *buf, int len, unsigned int flags,
								unsigned int part_idx, unsigned int part_max,
								int options)
{
	struct socket_info *sock;
	unsigned int dbflags;
	db1_res_t* res = NULL;
	db_row_t *row;
	dlist_t *dom;
	str now;
	char now_s[25];
	int port, proto;
	char *p;
	str addr;
	str recv;
	str path;
	str ruid;
	str host;
	unsigned int aorhash;
	int i;
	void *cp;
	int shortage, needed;
	db_key_t keys1[4]; /* where */
	db_val_t vals1[4];
	db_op_t  ops1[4];
	db_key_t keys2[6]; /* select */
	int n[2] = {2,6}; /* number of dynamic values used on key1/key2 */

	cp = buf;
	shortage = 0;
	/* Reserve space for terminating 0000 */
	len -= sizeof(addr.len);

	/* get the current time in DB format */
	now.len = 25;
	now.s = now_s;
	if (db_time2str( time(0), now.s, &now.len)!=0) {
		LM_ERR("failed to print now time\n");
		return -1;
	}
	aorhash = 0;

	/* select fields */
	keys2[0] = &received_col;
	keys2[1] = &contact_col;
	keys2[2] = &sock_col;
	keys2[3] = &cflags_col;
	keys2[4] = &path_col;
	keys2[5] = &ruid_col;

	/* where fields */
	keys1[0] = &expires_col;
	ops1[0] = OP_GT;
	vals1[0].type = DB1_STR;
	vals1[0].nul = 0;
	vals1[0].val.str_val = now;

	keys1[1] = &partition_col;
	ops1[1] = OP_EQ;
	vals1[1].type = DB1_INT;
	vals1[1].nul = 0;
	if(_ul_max_partition>0)
		vals1[1].val.int_val = part_idx;
	else
		vals1[1].val.int_val = 0;

	if (flags & nat_bflag) {
		keys1[n[0]] = &keepalive_col;
		ops1[n[0]] = OP_EQ;
		vals1[n[0]].type = DB1_INT;
		vals1[n[0]].nul = 0;
		vals1[n[0]].val.int_val = 1;
		n[0]++;
	}
	if(options&GAU_OPT_SERVER_ID) {
		keys1[n[0]] = &srv_id_col;
		ops1[n[0]] = OP_EQ;
		vals1[n[0]].type = DB1_INT;
		vals1[n[0]].nul = 0;
		vals1[n[0]].val.int_val = server_id;
		n[0]++;
	}

	/* TODO: use part_idx and part_max on keys1 */

	for (dom = root; dom!=NULL ; dom=dom->next) {
		if (ul_dbf.use_table(ul_dbh, dom->d->name) < 0) {
			LM_ERR("sql use_table failed\n");
			return -1;
		}
		if (ul_dbf.query(ul_dbh, keys1, ops1, vals1, keys2,
							n[0], n[1], NULL, &res) <0 ) {
			LM_ERR("query error\n");
			return -1;
		}
		if( RES_ROW_N(res)==0 ) {
			ul_dbf.free_result(ul_dbh, res);
			continue;
		}

		for(i = 0; i < RES_ROW_N(res); i++) {
			row = RES_ROWS(res) + i;


			/* received */
			recv.s = (char*)VAL_STRING(ROW_VALUES(row));
			if ( VAL_NULL(ROW_VALUES(row)) || recv.s==0 || recv.s[0]==0 ) {
				recv.s = NULL;
				recv.len = 0;
			}
			else {
				recv.len = strlen(recv.s);
			}

			/* contact */
			addr.s = (char*)VAL_STRING(ROW_VALUES(row)+1);
			if (VAL_NULL(ROW_VALUES(row)+1) || addr.s==0 || addr.s[0]==0) {
				LM_ERR("empty contact -> skipping\n");
				continue;
			}
			else {
				addr.len = strlen(addr.s);
			}

			/* path */
			path.s = (char*)VAL_STRING(ROW_VALUES(row)+4);
			if (VAL_NULL(ROW_VALUES(row)+4) || path.s==0 || path.s[0]==0){
				path.s = NULL;
				path.len = 0;
			} else {
				path.len = strlen(path.s);
			}

			/* ruid */
			ruid.s = (char*)VAL_STRING(ROW_VALUES(row)+5);
			if (VAL_NULL(ROW_VALUES(row)+5) || ruid.s==0 || ruid.s[0]==0){
				ruid.s = NULL;
				ruid.len = 0;
			} else {
				ruid.len = strlen(ruid.s);
			}

			needed = (int)(sizeof(addr.len) + addr.len
					+ sizeof(recv.len) + recv.len
					+ sizeof(sock) + sizeof(dbflags)
					+ sizeof(path.len) + path.len
					+ sizeof(ruid.len) + ruid.len
					+ sizeof(aorhash));
			if (len < needed) {
				shortage += needed ;
				continue;
			}

			/* write contact */
			memcpy(cp, &addr.len, sizeof(addr.len));
			cp = (char*)cp + sizeof(addr.len);
			memcpy(cp, addr.s, addr.len);
			cp = (char*)cp + addr.len;

			/* write received */
			memcpy(cp, &recv.len, sizeof(recv.len));
			cp = (char*)cp + sizeof(recv.len);
			/* copy received only if exist */
			if(recv.len){
				memcpy(cp, recv.s, recv.len);
				cp = (char*)cp + recv.len;
			}

			/* sock */
			p  = (char*)VAL_STRING(ROW_VALUES(row) + 2);
			if (VAL_NULL(ROW_VALUES(row)+2) || p==0 || p[0]==0){
				sock = 0;
			} else {
				if (parse_phostport( p, &host.s, &host.len,
				&port, &proto)!=0) {
					LM_ERR("bad socket <%s>...set to 0\n", p);
					sock = 0;
				} else {
					sock = grep_sock_info( &host, (unsigned short)port, proto);
					if (sock==0) {
						LM_DBG("non-local socket <%s>...set to 0\n", p);
					}
				}
			}

			/* flags */
			dbflags = VAL_BITMAP(ROW_VALUES(row) + 3);

			/* write sock and flags */
			memcpy(cp, &sock, sizeof(sock));
			cp = (char*)cp + sizeof(sock);
			memcpy(cp, &dbflags, sizeof(dbflags));
			cp = (char*)cp + sizeof(dbflags);

			/* write path */
			memcpy(cp, &path.len, sizeof(path.len));
			cp = (char*)cp + sizeof(path.len);
			/* copy path only if exist */
			if(path.len){
				memcpy(cp, path.s, path.len);
				cp = (char*)cp + path.len;
			}

			/* write ruid */
			memcpy(cp, &ruid.len, sizeof(ruid.len));
			cp = (char*)cp + sizeof(ruid.len);
			/* copy ruid only if exist */
			if(ruid.len){
				memcpy(cp, ruid.s, ruid.len);
				cp = (char*)cp + ruid.len;
			}
			/* aorhash not used for db-only records, but it is added
			 * (as 0) to match the struct used for mem records */
			memcpy(cp, &aorhash, sizeof(aorhash));
			cp = (char*)cp + sizeof(aorhash);

			len -= needed;
		} /* row cycle */

		ul_dbf.free_result(ul_dbh, res);
	} /* domain cycle */

	/* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */
	if (len >= 0)
		memset(cp, 0, sizeof(addr.len));

	/* Shouldn't happen */
	if (shortage > 0 && len > shortage) {
		abort();
	}

	shortage -= len;

	return shortage > 0 ? shortage : 0;
}
Example #4
0
/*
 * Used when converting values to be used in a DB query
 */
int db_sqlite_val2str(const db_con_t* _c, const db_val_t* _v, char* _s, int* _len)
{
	int l;

	if (!_c || !_v || !_s || !_len || !*_len) {
		LM_ERR("invalid parameter value\n");
		return -1;
	}

	if (VAL_NULL(_v)) {
		if (*_len < sizeof("NULL")) {
			LM_ERR("buffer too small\n");
			return -1;
		}
		*_len = snprintf(_s, *_len, "NULL");
		return 0;
	}

	switch(VAL_TYPE(_v)) {
	case DB_INT:
		if (db_int2str(VAL_INT(_v), _s, _len) < 0) {
			LM_ERR("error while converting string to int\n");
			return -2;
		} else {
			return 0;
		}
		break;

	case DB_BIGINT:
		if (db_bigint2str(VAL_BIGINT(_v), _s, _len) < 0) {
			LM_ERR("error while converting bigint to string\n");
			return -2;
		} else {
			return 0;
		}
		break;


	case DB_BITMAP:
		if (db_int2str(VAL_BITMAP(_v), _s, _len) < 0) {
			LM_ERR("error while converting string to int\n");
			return -3;
		} else {
			return 0;
		}
		break;

	case DB_DOUBLE:
		if (db_double2str(VAL_DOUBLE(_v), _s, _len) < 0) {
			LM_ERR("error while converting string to double\n");
			return -4;
		} else {
			return 0;
		}
		break;

	case DB_STRING:
		/* TODO check escpaing */
		l = strlen(VAL_STRING(_v));
		if (*_len < l )
		{	LM_ERR("Destination buffer too short for string\n");
			return -4;
		}
		else
		{	LM_DBG("Converted string to string\n");
			strncpy(_s, VAL_STRING(_v) , l);
			_s[l] = 0;
			*_len = l+1; /* count the 0 also */
			return 0;
		}
		break;

	case DB_STR:
		/* TODO check escpaing */
		l = VAL_STR(_v).len;
		if (*_len < l)
		{
			LM_ERR("Destination buffer too short for str\n");
			return -5;
		}
		else
		{
			LM_DBG("Converted str to string\n");
			strncpy(_s, VAL_STR(_v).s , l);
			*_len = l;
			return 0;
		}
		break;


		break;

	case DB_DATETIME:
		if (db_time2str(VAL_TIME(_v), _s, _len) < 0) {
			LM_ERR("error while converting string to time_t\n");
			return -7;
		} else {
			return 0;
		}
		break;

	case DB_BLOB:
		/* TODO check escpaing */

		l = VAL_BLOB(_v).len;
		if (*_len < l)
		{
			LM_ERR("Destination buffer too short for blob\n");
			return -7;
		}
		else
		{
			strncpy(_s, VAL_BLOB(_v).s , l);
			LM_DBG("Converting BLOB [%.*s]\n", l,_s);
			*_len = l;
			return 0;
		}
		break;

	default:
		LM_DBG("unknown data type\n");
		return -9;
	}
}
Example #5
0
/*!
 * \brief Get all contacts from the database, in partitions if wanted
 * \see get_all_ucontacts
 * \param buf target buffer
 * \param len length of buffer
 * \param flags contact flags
 * \param part_idx part index
 * \param part_max maximal part
 * \return 0 on success, positive if buffer size was not sufficient, negative on failure
 */
static inline int get_all_db_ucontacts(void *buf, int len, unsigned int flags,
								unsigned int part_idx, unsigned int part_max)
{
	static char query_buf[512];
	static str query_str;

	struct socket_info *sock;
	unsigned int dbflags;
	db1_res_t* res = NULL;
	db_row_t *row;
	dlist_t *dom;
	char now_s[25];
	int now_len;
	int port, proto;
	char *p;
	str addr;
	str path;
	str ruid;
	str host;
	unsigned int aorhash;
	int i;
	void *cp;
	int shortage, needed;

	if(ul_dbf.raw_query==NULL) {
		LM_WARN("DB raw query support is required, but not implemented\n");
		return -1;
	}

	cp = buf;
	shortage = 0;
	/* Reserve space for terminating 0000 */
	len -= sizeof(addr.len);

	/* get the current time in DB format */
	now_len = 25;
	if (db_time2str( time(0), now_s, &now_len)!=0) {
		LM_ERR("failed to print now time\n");
		return -1;
	}
	aorhash = 0;

	for (dom = root; dom!=NULL ; dom=dom->next) {
		/* build query */
		i = snprintf( query_buf, sizeof(query_buf), "select %.*s, %.*s, %.*s,"
			" %.*s, %.*s, %.*s from %s where %.*s > %.*s and"
#ifdef ORACLE_USRLOC
			" bitand(%.*s, %d) = %d and mod(id, %u) = %u",
#else
			" %.*s & %d = %d and id %% %u = %u",
#endif
			received_col.len, received_col.s,
			contact_col.len, contact_col.s,
			sock_col.len, sock_col.s,
			cflags_col.len, cflags_col.s,
			path_col.len, path_col.s,
			ruid_col.len, ruid_col.s,
			dom->d->name->s,
			expires_col.len, expires_col.s,
			now_len, now_s,
			cflags_col.len, cflags_col.s,
			flags, flags, part_max, part_idx);
		if ( i>=sizeof(query_buf) ) {
			LM_ERR("DB query too long\n");
			return -1;
		}
		query_str.s = query_buf;
		query_str.len = i;
		if ( ul_dbf.raw_query( ul_dbh, &query_str, &res)<0 ) {
			LM_ERR("raw_query failed\n");
			return -1;
		}
		if( RES_ROW_N(res)==0 ) {
			ul_dbf.free_result(ul_dbh, res);
			continue;
		}

		for(i = 0; i < RES_ROW_N(res); i++) {
			row = RES_ROWS(res) + i;

			/* received */
			addr.s = (char*)VAL_STRING(ROW_VALUES(row));
			if ( VAL_NULL(ROW_VALUES(row)) || addr.s==0 || addr.s[0]==0 ) {
				/* contact */
				addr.s = (char*)VAL_STRING(ROW_VALUES(row)+1);
				if (VAL_NULL(ROW_VALUES(row)+1) || addr.s==0 || addr.s[0]==0) {
					LM_ERR("empty contact -> skipping\n");
					continue;
				}
			}
			addr.len = strlen(addr.s);

			/* path */
			path.s = (char*)VAL_STRING(ROW_VALUES(row)+4);
			if (VAL_NULL(ROW_VALUES(row)+4) || path.s==0 || path.s[0]==0){
				path.s = NULL;
				path.len = 0;
			} else {
				path.len = strlen(path.s);
			}

			/* ruid */
			ruid.s = (char*)VAL_STRING(ROW_VALUES(row)+5);
			if (VAL_NULL(ROW_VALUES(row)+5) || ruid.s==0 || ruid.s[0]==0){
				ruid.s = NULL;
				ruid.len = 0;
			} else {
				ruid.len = strlen(ruid.s);
			}

			needed = (int)(sizeof(addr.len) + addr.len
					+ sizeof(sock) + sizeof(dbflags)
					+ sizeof(path.len) + path.len
					+ sizeof(ruid.len) + ruid.len
					+ sizeof(aorhash));
			if (len < needed) {
				shortage += needed ;
				continue;
			}

			/* write received/contact */
			memcpy(cp, &addr.len, sizeof(addr.len));
			cp = (char*)cp + sizeof(addr.len);
			memcpy(cp, addr.s, addr.len);
			cp = (char*)cp + addr.len;

			/* sock */
			p  = (char*)VAL_STRING(ROW_VALUES(row) + 2);
			if (VAL_NULL(ROW_VALUES(row)+2) || p==0 || p[0]==0){
				sock = 0;
			} else {
				if (parse_phostport( p, &host.s, &host.len,
				&port, &proto)!=0) {
					LM_ERR("bad socket <%s>...set to 0\n", p);
					sock = 0;
				} else {
					sock = grep_sock_info( &host, (unsigned short)port, proto);
					if (sock==0) {
						LM_DBG("non-local socket <%s>...set to 0\n", p);
					}
				}
			}

			/* flags */
			dbflags = VAL_BITMAP(ROW_VALUES(row) + 3);

			/* write sock and flags */
			memcpy(cp, &sock, sizeof(sock));
			cp = (char*)cp + sizeof(sock);
			memcpy(cp, &dbflags, sizeof(dbflags));
			cp = (char*)cp + sizeof(dbflags);

			/* write path */
			memcpy(cp, &path.len, sizeof(path.len));
			cp = (char*)cp + sizeof(path.len);
			/* copy path only if exist */
			if(path.len){
				memcpy(cp, path.s, path.len);
				cp = (char*)cp + path.len;
			}

			/* write ruid */
			memcpy(cp, &ruid.len, sizeof(ruid.len));
			cp = (char*)cp + sizeof(ruid.len);
			/* copy ruid only if exist */
			if(ruid.len){
				memcpy(cp, ruid.s, ruid.len);
				cp = (char*)cp + ruid.len;
			}
			/* aorhash not used for db-only records, but it is added
			 * (as 0) to match the struct used for mem records */
			memcpy(cp, &aorhash, sizeof(aorhash));
			cp = (char*)cp + sizeof(aorhash);

			len -= needed;
		} /* row cycle */

		ul_dbf.free_result(ul_dbh, res);
	} /* domain cycle */

	/* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */
	if (len >= 0)
		memset(cp, 0, sizeof(addr.len));

	/* Shouldn't happen */
	if (shortage > 0 && len > shortage) {
		abort();
	}

	shortage -= len;

	return shortage > 0 ? shortage : 0;
}
Example #6
0
static inline int get_all_db_ucontacts(void *buf, int len, unsigned int flags,
								unsigned int part_idx, unsigned int part_max)
{
	static char query_buf[512];
	static str query_str;

	struct socket_info *sock;
	unsigned int dbflags;
	db_res_t* res = NULL;
	db_row_t *row;
	dlist_t *dom;
	char *p, *p1;
	char now_s[25];
	int now_len;
	int port, proto, p_len, p1_len;
	str host;
	int i;
	void *cp;
	int shortage, needed;

	cp = buf;
	shortage = 0;
	/* Reserve space for terminating 0000 */
	len -= sizeof(p_len);

	/* get the current time in DB format */
	now_len = 25;
	if (db_time2str( time(0), now_s, &now_len)!=0) {
		LM_ERR("failed to print now time\n");
		return -1;
	}

	for (dom = root; dom!=NULL ; dom=dom->next) {
		/* build query */
		i = snprintf( query_buf, sizeof(query_buf), "select %.*s, %.*s, %.*s,"
#ifdef ORACLE_USRLOC
			" %.*s, %.*s from %s where %.*s > %.*s and "
			"bitand(%.*s, %d) = %d and mod(id, %u) = %u",
#else
			" %.*s, %.*s from %s where %.*s > %.*s and %.*s & %d = %d and "
			"id %% %u = %u",
#endif
			received_col.len, received_col.s,
			contact_col.len, contact_col.s,
			sock_col.len, sock_col.s,
			cflags_col.len, cflags_col.s,
			path_col.len, path_col.s,
			dom->d->name->s,
			expires_col.len, expires_col.s,
			now_len, now_s,
			cflags_col.len, cflags_col.s,
			flags, flags, part_max, part_idx);
		if ( i>=sizeof(query_buf) ) {
			LM_ERR("DB query too long\n");
			return -1;
		}
		query_str.s = query_buf;
		query_str.len = i;
		if ( ul_dbf.raw_query( ul_dbh, &query_str, &res)<0 ) {
			LM_ERR("raw_query failed\n");
			return -1;
		}
		if( RES_ROW_N(res)==0 ) {
			ul_dbf.free_result(ul_dbh, res);
			continue;
		}

		for(i = 0; i < RES_ROW_N(res); i++) {
			row = RES_ROWS(res) + i;

			/* received */
			p = (char*)VAL_STRING(ROW_VALUES(row));
			if ( VAL_NULL(ROW_VALUES(row)) || p==0 || p[0]==0 ) {
				/* contact */
				p = (char*)VAL_STRING(ROW_VALUES(row)+1);
				if (VAL_NULL(ROW_VALUES(row)+1) || p==0 || p[0]==0) {
					LM_ERR("empty contact -> skipping\n");
					continue;
				}
			}
			p_len = strlen(p);

			/* path */
			p1 = (char*)VAL_STRING(ROW_VALUES(row)+4);
			if (VAL_NULL(ROW_VALUES(row)+4) || p1==0 || p1[0]==0){
				p1 = NULL;
				p1_len = 0;
			} else {
				p1_len = strlen(p1);
			}

			needed = (int)(sizeof(p_len)+p_len+sizeof(sock)+sizeof(dbflags)+
				sizeof(p1_len)+p1_len);
			if (len < needed) {
				shortage += needed ;
				continue;
			}

			/* write received/contact */
			memcpy(cp, &p_len, sizeof(p_len));
			cp = (char*)cp + sizeof(p_len);
			memcpy(cp, p, p_len);
			cp = (char*)cp + p_len;

			/* sock */
			p  = (char*)VAL_STRING(ROW_VALUES(row) + 2);
			if (VAL_NULL(ROW_VALUES(row)+2) || p==0 || p[0]==0){
				sock = 0;
			} else {
				if (parse_phostport( p, strlen(p), &host.s, &host.len,
				&port, &proto)!=0) {
					LM_ERR("bad socket <%s>...ignoring\n", p);
					sock = 0;
				} else {
					sock = grep_sock_info( &host, (unsigned short)port, proto);
					if (sock==0) {
						LM_DBG("non-local socket <%s>...ignoring\n", p);
					}
				}
			}

			/* flags */
			dbflags = VAL_BITMAP(ROW_VALUES(row) + 3);

			/* write sock and flags */
			memcpy(cp, &sock, sizeof(sock));
			cp = (char*)cp + sizeof(sock);
			memcpy(cp, &dbflags, sizeof(dbflags));
			cp = (char*)cp + sizeof(dbflags);

			/* write path */
			memcpy(cp, &p1_len, sizeof(p1_len));
			cp = (char*)cp + sizeof(p1_len);
			memcpy(cp, p1, p1_len);
			cp = (char*)cp + p1_len;

			len -= needed;
		} /* row cycle */

		ul_dbf.free_result(ul_dbh, res);
	} /* domain cycle */

	/* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */
	if (len >= 0)
		memset(cp, 0, sizeof(p_len));

	/* Shouldn't happen */
	if (shortage > 0 && len > shortage) {
		abort();
	}

	shortage -= len;

	return shortage > 0 ? shortage : 0;
}
Example #7
0
static int get_all_db_ucontacts(void *buf, int len, unsigned int flags,
                                unsigned int part_idx, unsigned int part_max)
{
	static char query_buf[512];
	static str query_str;
	static struct sip_uri puri;

	struct socket_info *sock;
	struct proxy_l next_hop;
	db_res_t *res = NULL;
	db_row_t *row;
	db_val_t *val;
	dlist_t *dom;
	str uri, host, flag_list;
	int i, no_rows = 10;
	int now_len;
	char now_s[25];
	char *p, *p1;
	int port, proto, p_len, p1_len;
	unsigned int dbflags;
	int needed;
	int shortage = 0;

	shortage = 0;
	/* Reserve space for terminating 0000 */
	len -= sizeof p_len;

	/* get the current time in DB format */
	now_len = 25;
	if (db_time2str(time(NULL), now_s, &now_len) != 0) {
		LM_ERR("failed to print now time\n");
		return -1;
	}

	LM_DBG("buf: %p. flags: %d\n", buf, flags);

	/* for each table */
	for (dom = root; dom; dom = dom->next) {
		if (db_check_table_version(&ul_dbf, ul_dbh, dom->d->name, UL_TABLE_VERSION))
			goto error;

		/* read the destinations */
		if (ul_dbf.use_table(ul_dbh, dom->d->name) < 0) {
			LM_ERR("cannot select table \"%.*s\"\n", dom->d->name->len,
			       dom->d->name->s);
			goto error;
		}

		i = snprintf(query_buf, sizeof query_buf, "select %.*s, %.*s, %.*s,"
#ifdef ORACLE_USRLOC
		" %.*s, %.*s from %s where %.*s > %.*s and mod(id, %u) = %u",
#else
		" %.*s, %.*s from %s where %.*s > %.*s and id %% %u = %u",
#endif
			received_col.len, received_col.s,
			contact_col.len, contact_col.s,
			sock_col.len, sock_col.s,
			cflags_col.len, cflags_col.s,
			path_col.len, path_col.s,
			dom->d->name->s,
			expires_col.len, expires_col.s,
			now_len, now_s,
			part_max, part_idx);

		LM_DBG("query: %.*s\n", (int)(sizeof query_buf), query_buf);
		if (i >= sizeof query_buf) {
			LM_ERR("DB query too long\n");
			goto error;
		}

		query_str.s = query_buf;
		query_str.len = i;

		if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
			if (ul_dbf.raw_query(ul_dbh, &query_str, 0) < 0) {
				LM_ERR("raw_query failed\n");
				goto error;
			}

			no_rows = estimate_available_rows(20+128+20+128+64, 5);
			if (no_rows == 0)
				no_rows = 10;

			LM_DBG("fetching %d rows\n", no_rows);

			if (ul_dbf.fetch_result(ul_dbh, &res, no_rows) < 0) {
				LM_ERR("Error fetching rows\n");
				goto error;
			}
		} else if (ul_dbf.raw_query(ul_dbh, &query_str, &res) < 0) {
			LM_ERR("raw_query failed\n");
			goto error;
		}

		do {
			for (i = 0; i < RES_ROW_N(res); i++) {
				row = RES_ROWS(res) + i;
				val = ROW_VALUES(row) + 3; /* cflags */
				flag_list.s   = (char *)VAL_STRING(val);
				flag_list.len = strlen(flag_list.s);

				LM_DBG("contact cflags: '%.*s'\n", flag_list.len, flag_list.s);

				/* contact is not flagged at all */
				if (flags && (val->nul || !flag_list.s))
					continue;

				dbflags = flag_list_to_bitmask(&flag_list,
				                FLAG_TYPE_BRANCH, FLAG_DELIM);

				LM_DBG("masks: param: %d --- %d :db\n", flags, dbflags);

				/* check if contact flags match the given bitmask */
				if ((dbflags & flags) != flags)
					continue;

				/* received */
				p = (char*)VAL_STRING(ROW_VALUES(row));
				if (VAL_NULL(ROW_VALUES(row)) || !p || !p[0]) {
					/* contact */
					p = (char*)VAL_STRING(ROW_VALUES(row) + 1);
					if (VAL_NULL(ROW_VALUES(row) + 1) || !p || *p == '\0') {
						LM_ERR("empty contact -> skipping\n");
						continue;
					}
				}
				p_len = strlen(p);

				/* path */
				p1 = (char*)VAL_STRING(ROW_VALUES(row) + 4);
				if (VAL_NULL(ROW_VALUES(row) + 4) || !p1 || *p1 == '\0') {
					p1 = NULL;
					p1_len = 0;
				} else
					p1_len = strlen(p1);

				needed = (int)(p_len + sizeof p_len + p1_len + sizeof p1_len +
				               sizeof sock + sizeof dbflags + sizeof next_hop);

				LM_DBG("len: %d, needed: %d\n", len, needed);

				if (len < needed) {
					shortage += needed;
					continue;
				}

				/* determine and parse the URI of this contact's next hop */
				if (p1_len > 0) {
					/* send to first URI in path */
					host.s   = p1;
					host.len = p1_len;
					if (get_path_dst_uri(&host, &uri) < 0) {
						LM_ERR("failed to get dst_uri for Path\n");
						continue;
					}
					if (parse_uri(uri.s, uri.len, &puri) < 0) {
						LM_ERR("failed to parse path URI of next hop: '%*.s'\n",
						        p1_len, p1);
						return -1;
					}
				} else {
					if (parse_uri(p, p_len, &puri) < 0) {
						LM_ERR("failed to parse contact of next hop: '%*.s'\n",
						        p_len, p);
						return -1;
					}
				}

				/* write received/contact */
				memcpy(buf, &p_len, sizeof p_len);
				buf += sizeof p_len;
				memcpy(buf, p, p_len);
				buf += p_len;

				/* write path */
				memcpy(buf, &p1_len, sizeof p1_len);
				buf += sizeof p1_len;
				memcpy(buf, p1, p1_len);
				buf += p1_len;

				/* sock */
				p  = (char*)VAL_STRING(ROW_VALUES(row) + 2);
				if (VAL_NULL(ROW_VALUES(row)+2) || !p || *p == '\0') {
					sock = NULL;
				} else {
					if (parse_phostport(p, strlen(p), &host.s, &host.len,
					    &port, &proto) != 0) {
						LM_ERR("bad socket <%s>...ignoring\n", p);
						sock = NULL;
					} else {
						sock = grep_sock_info(&host, (unsigned short)port, proto);
						if (!sock)
							LM_DBG("non-local socket <%s>...ignoring\n", p);
					}
				}

				/* write sock and flags */
				memcpy(buf, &sock, sizeof sock);
				buf += sizeof sock;
				memcpy(buf, &dbflags, sizeof dbflags);
				buf += sizeof dbflags;

				memset(&next_hop, 0, sizeof next_hop);
				next_hop.port  = puri.port_no;
				next_hop.proto = puri.proto;
				next_hop.name  = puri.host;

				/* write the next hop */
				memcpy(buf, &next_hop, sizeof next_hop);
				buf += sizeof next_hop;

				len -= needed;
			}

			if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
				if (ul_dbf.fetch_result(ul_dbh, &res, no_rows) < 0) {
					LM_ERR("fetching rows (1)\n");
					goto error;
				}
			} else
				break;

		} while (RES_ROW_N(res) > 0);

		ul_dbf.free_result(ul_dbh, res);
	}

	/* len < 0 is possible, if size of the buffer < sizeof c->c.len */
	if (len >= 0)
		memset(buf, 0, sizeof p_len);

	/* Shouldn't happen */
	if (shortage > 0 && len > shortage)
		abort();

	shortage -= len;

	return shortage > 0 ? shortage : 0;

error:
	if (res)
		ul_dbf.free_result(ul_dbh, res);
	return -1;
}