static int update2_curl(const char *url, const char *unused, const struct ast_variable *lookup_fields, const struct ast_variable *update_fields)
{
	struct ast_str *query, *buffer;
	char buf1[200], buf2[200];
	const struct ast_variable *field;
	char *stringp;
	unsigned int start = 1;
	int rowcount = -1;

	if (!ast_custom_function_find("CURL")) {
		ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
		return -1;
	}

	if (!(query = ast_str_thread_get(&query_buf, 1000)))
		return -1;

	if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
		return -1;
	}

	ast_str_set(&query, 0, "${CURL(%s/update?", url);

	for (field = lookup_fields; field; field = field->next) {
		ast_uri_encode(field->name, buf1, sizeof(buf1), ast_uri_http);
		ast_uri_encode(field->value, buf2, sizeof(buf2), ast_uri_http);
		ast_str_append(&query, 0, "%s%s=%s", !start ? "" : "&", buf1, buf2);
		start = 0;
	}
	ast_str_append(&query, 0, ",");
	start = 1;

	for (field = update_fields; field; field = field->next) {
		ast_uri_encode(field->name, buf1, sizeof(buf1), ast_uri_http);
		ast_uri_encode(field->value, buf2, sizeof(buf2), ast_uri_http);
		ast_str_append(&query, 0, "%s%s=%s", !start ? "" : "&", buf1, buf2);
		start = 0;
	}

	ast_str_append(&query, 0, ")}");
	/* Proxies work, by setting CURLOPT options in the [globals] section of
	 * extensions.conf.  Unfortunately, this means preloading pbx_config.so
	 * so that they have an opportunity to be set prior to startup realtime
	 * queries. */
	ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));

	/* Line oriented output */
	stringp = ast_str_buffer(buffer);
	while (*stringp <= ' ') {
		stringp++;
	}
	sscanf(stringp, "%30d", &rowcount);

	if (rowcount >= 0) {
		return (int)rowcount;
	}

	return -1;
}
static int require_curl(const char *url, const char *unused, va_list ap)
{
	struct ast_str *query, *buffer;
	char *elm, field[256];
	int type, size, i = 0;

	if (!ast_custom_function_find("CURL")) {
		ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
		return -1;
	}

	if (!(query = ast_str_thread_get(&query_buf, 100))) {
		return -1;
	}

	if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
		return -1;
	}

	ast_str_set(&query, 0, "${CURL(%s/require,", url);

	while ((elm = va_arg(ap, char *))) {
		type = va_arg(ap, require_type);
		size = va_arg(ap, int);
		ast_uri_encode(elm, field, sizeof(field), ast_uri_http);
		ast_str_append(&query, 0, "%s%s=%s%%3A%d",
			i > 0 ? "&" : "",
			field,
			type == RQ_CHAR ? "char" :
			type == RQ_INTEGER1 ? "integer1" :
			type == RQ_UINTEGER1 ? "uinteger1" :
			type == RQ_INTEGER2 ? "integer2" :
			type == RQ_UINTEGER2 ? "uinteger2" :
			type == RQ_INTEGER3 ? "integer3" :
			type == RQ_UINTEGER3 ? "uinteger3" :
			type == RQ_INTEGER4 ? "integer4" :
			type == RQ_UINTEGER4 ? "uinteger4" :
			type == RQ_INTEGER8 ? "integer8" :
			type == RQ_UINTEGER8 ? "uinteger8" :
			type == RQ_DATE ? "date" :
			type == RQ_DATETIME ? "datetime" :
			type == RQ_FLOAT ? "float" :
			"unknown", size);
		i++;
	}

	ast_str_append(&query, 0, ")}");
	ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
	return atoi(ast_str_buffer(buffer));
}
/*!
 * \brief Execute an DELETE query
 * \param url
 * \param unused
 * \param keyfield where clause field
 * \param lookup value of field for where clause
 * \param fields list containing one or more field/value set(s)
 *
 * Delete a row from a database table, prepare the sql statement using keyfield and lookup
 * control the number of records to change. Additional params to match rows are stored in ap list.
 * Sub-in the values to the prepared statement and execute it.
 *
 * \retval number of rows affected
 * \retval -1 on failure
*/
static int destroy_curl(const char *url, const char *unused, const char *keyfield, const char *lookup, const struct ast_variable *fields)
{
	struct ast_str *query, *buffer;
	char buf1[200], buf2[200];
	const struct ast_variable *field;
	char *stringp;
	int start = 1, rowcount = -1;

	if (!ast_custom_function_find("CURL")) {
		ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
		return -1;
	}

	if (!(query = ast_str_thread_get(&query_buf, 1000))) {
		return -1;
	}

	if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
		return -1;
	}

	ast_uri_encode(keyfield, buf1, sizeof(buf1), ast_uri_http);
	ast_uri_encode(lookup, buf2, sizeof(buf2), ast_uri_http);
	ast_str_set(&query, 0, "${CURL(%s/destroy,%s=%s&", url, buf1, buf2);

	for (field = fields; field; field = field->next) {
		ast_uri_encode(field->name, buf1, sizeof(buf1), ast_uri_http);
		ast_uri_encode(field->value, buf2, sizeof(buf2), ast_uri_http);
		ast_str_append(&query, 0, "%s%s=%s", !start ? "&" : "", buf1, buf2);
		start = 0;
	}

	ast_str_append(&query, 0, ")}");
	ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));

	/* Line oriented output */
	stringp = ast_str_buffer(buffer);
	while (*stringp <= ' ') {
		stringp++;
	}
	sscanf(stringp, "%30d", &rowcount);

	if (rowcount >= 0) {
		return (int)rowcount;
	}

	return -1;
}
Example #4
0
static void security_event_cb(const struct ast_event *event, void *data)
{
    struct ast_str *str;
    enum ast_security_event_type event_type;

    if (!(str = ast_str_thread_get(&security_event_buf,
                                   SECURITY_EVENT_BUF_INIT_LEN))) {
        return;
    }

    /* Note that the event type is guaranteed to be valid here. */
    event_type = ast_event_get_ie_uint(event, AST_EVENT_IE_SECURITY_EVENT);
    ast_assert(event_type >= 0 && event_type < AST_SECURITY_EVENT_NUM_TYPES);

    ast_str_set(&str, 0, "%s=\"%s\"",
                ast_event_get_ie_type_name(AST_EVENT_IE_SECURITY_EVENT),
                ast_security_event_get_name(event_type));

    append_ies(&str, event,
               ast_security_event_get_required_ies(event_type), REQUIRED);
    append_ies(&str, event,
               ast_security_event_get_optional_ies(event_type), NOT_REQUIRED);

    ast_log_dynamic_level(LOG_SECURITY, "%s\n", ast_str_buffer(str));
}
Example #5
0
static void security_event_stasis_cb(struct ast_json *json)
{
	struct ast_str *str;
	struct ast_json *event_type_json;
	enum ast_security_event_type event_type;

	event_type_json = ast_json_object_get(json, "SecurityEvent");
	event_type = ast_json_integer_get(event_type_json);

	ast_assert(event_type >= 0 && event_type < AST_SECURITY_EVENT_NUM_TYPES);

	if (!(str = ast_str_thread_get(&security_event_buf,
			SECURITY_EVENT_BUF_INIT_LEN))) {
		return;
	}

	ast_str_set(&str, 0, "SecurityEvent=\"%s\"",
			ast_security_event_get_name(event_type));

	append_json(&str, json,
			ast_security_event_get_required_ies(event_type), REQUIRED);
	append_json(&str, json,
			ast_security_event_get_optional_ies(event_type), NOT_REQUIRED);

	ast_log_dynamic_level(LOG_SECURITY, "%s\n", ast_str_buffer(str));
}
Example #6
0
char *__netsock_stringify_fmt(const struct sockaddr_storage *sockAddrStorage, int format)
{
	const struct sockaddr_storage *sockAddrStorage_tmp;
	char host[NI_MAXHOST] = "";
	char port[NI_MAXSERV] = "";
	struct ast_str *str;
	int e;
	static const size_t size = sizeof(host) - 1 + sizeof(port) - 1 + 4;

	if (!sockAddrStorage) {
		return "(null)";
	}

	if (!(str = ast_str_thread_get(&sccp_netsock_stringify_buf, size))) {
		return "";
	}
	//if (sccp_netsock_ipv4_mapped(sockAddrStorage, &sockAddrStorage_tmp_ipv4)) {
	//	struct sockaddr_storage sockAddrStorage_tmp_ipv4;
	//	sockAddrStorage_tmp = &sockAddrStorage_tmp_ipv4;
	//#if DEBUG
	//	sccp_log(0)("SCCP: ipv4 mapped in ipv6 address\n");
	//#endif
	//} else {
	sockAddrStorage_tmp = sockAddrStorage;
	//}

	if ((e = getnameinfo((struct sockaddr *) sockAddrStorage_tmp, sccp_netsock_sizeof(sockAddrStorage_tmp), format & SCCP_SOCKADDR_STR_ADDR ? host : NULL, format & SCCP_SOCKADDR_STR_ADDR ? sizeof(host) : 0, format & SCCP_SOCKADDR_STR_PORT ? port : 0, format & SCCP_SOCKADDR_STR_PORT ? sizeof(port) : 0, NI_NUMERICHOST | NI_NUMERICSERV))) {
		sccp_log(DEBUGCAT_SOCKET) (VERBOSE_PREFIX_3 "SCCP: getnameinfo(): %s \n", gai_strerror(e));
		return "";
	}

	if ((format & SCCP_SOCKADDR_STR_REMOTE) == SCCP_SOCKADDR_STR_REMOTE) {
		char *p;

		if (sccp_netsock_is_ipv6_link_local(sockAddrStorage_tmp) && (p = strchr(host, '%'))) {
			*p = '\0';
		}
	}
	switch ((format & SCCP_SOCKADDR_STR_FORMAT_MASK)) {
		case SCCP_SOCKADDR_STR_DEFAULT:
			ast_str_set(&str, 0, sockAddrStorage_tmp->ss_family == AF_INET6 ? "[%s]:%s" : "%s:%s", host, port);
			break;
		case SCCP_SOCKADDR_STR_ADDR:
			ast_str_set(&str, 0, "%s", host);
			break;
		case SCCP_SOCKADDR_STR_HOST:
			ast_str_set(&str, 0, sockAddrStorage_tmp->ss_family == AF_INET6 ? "[%s]" : "%s", host);
			break;
		case SCCP_SOCKADDR_STR_PORT:
			ast_str_set(&str, 0, "%s", port);
			break;
		default:
			pbx_log(LOG_ERROR, "Invalid format\n");
			return "";
	}

	return ast_str_buffer(str);
}
Example #7
0
static int system_exec_helper(struct ast_channel *chan, const char *data, int failmode)
{
	int res = 0;
	struct ast_str *buf = ast_str_thread_get(&buf_buf, 16);
	char *cbuf;

	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "System requires an argument(command)\n");
		pbx_builtin_setvar_helper(chan, chanvar, "FAILURE");
		return failmode;
	}

	ast_autoservice_start(chan);

	/* Do our thing here */
	ast_str_get_encoded_str(&buf, 0, (char *) data);
	cbuf = ast_str_buffer(buf);

	if (strchr("\"'", cbuf[0]) && cbuf[ast_str_strlen(buf) - 1] == cbuf[0]) {
		cbuf[ast_str_strlen(buf) - 1] = '\0';
		cbuf++;
		ast_log(LOG_NOTICE, "It is not necessary to quote the argument to the System application.\n");
	}

	res = ast_safe_system(cbuf);

	if ((res < 0) && (errno != ECHILD)) {
		ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data);
		pbx_builtin_setvar_helper(chan, chanvar, "FAILURE");
		res = failmode;
	} else if (res == 127) {
		ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data);
		pbx_builtin_setvar_helper(chan, chanvar, "FAILURE");
		res = failmode;
	} else {
		if (res < 0) 
			res = 0;
		if (res != 0)
			pbx_builtin_setvar_helper(chan, chanvar, "APPERROR");
		else
			pbx_builtin_setvar_helper(chan, chanvar, "SUCCESS");
		res = 0;
	} 

	ast_autoservice_stop(chan);

	return res;
}
Example #8
0
static int system_exec_helper(struct ast_channel *chan, void *data, int failmode)
{
	int res = 0;
	struct ast_str *buf = ast_str_thread_get(&buf_buf, 16);
	
	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "System requires an argument(command)\n");
		pbx_builtin_setvar_helper(chan, chanvar, "FAILURE");
		return failmode;
	}

	ast_autoservice_start(chan);

	/* Do our thing here */
	ast_str_get_encoded_str(&buf, 0, (char *) data);
	res = ast_safe_system(ast_str_buffer(buf));

	if ((res < 0) && (errno != ECHILD)) {
		ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data);
		pbx_builtin_setvar_helper(chan, chanvar, "FAILURE");
		res = failmode;
	} else if (res == 127) {
		ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data);
		pbx_builtin_setvar_helper(chan, chanvar, "FAILURE");
		res = failmode;
	} else {
		if (res < 0) 
			res = 0;
		if (res != 0)
			pbx_builtin_setvar_helper(chan, chanvar, "APPERROR");
		else
			pbx_builtin_setvar_helper(chan, chanvar, "SUCCESS");
		res = 0;
	} 

	ast_autoservice_stop(chan);

	return res;
}
Example #9
0
static int dumpchan_exec(struct ast_channel *chan, const char *data)
{
	struct ast_str *vars = ast_str_thread_get(&ast_str_thread_global_buf, 16);
	char info[2048];
	int level = 0;
	static char *line = "================================================================================";

	if (!ast_strlen_zero(data))
		level = atoi(data);

	serialize_showchan(chan, info, sizeof(info));
	pbx_builtin_serialize_variables(chan, &vars);
	ast_verb(level, "\n"
		 "Dumping Info For Channel: %s:\n"
		 "%s\n"
		 "Info:\n"
		 "%s\n"
		 "Variables:\n"
		 "%s%s\n", ast_channel_name(chan), line, info, ast_str_buffer(vars), line);

	return 0;
}
/*!
 * \brief Execute a curl query and return ast_variable list
 * \param url The base URL from which to retrieve data
 * \param unused Not currently used
 * \param fields list containing one or more field/operator/value set.
 *
 * \retval var on success
 * \retval NULL on failure
*/
static struct ast_variable *realtime_curl(const char *url, const char *unused, const struct ast_variable *fields)
{
	struct ast_str *query, *buffer;
	char buf1[256], buf2[256];
	const struct ast_variable *field;
	char *stringp, *pair, *key;
	unsigned int start = 1;
	struct ast_variable *var = NULL, *prev = NULL;

	if (!ast_custom_function_find("CURL")) {
		ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
		return NULL;
	}

	if (!(query = ast_str_thread_get(&query_buf, 16))) {
		return NULL;
	}

	if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
		return NULL;
	}

	ast_str_set(&query, 0, "${CURL(%s/single,", url);

	for (field = fields; field; field = field->next) {
		ast_uri_encode(field->name, buf1, sizeof(buf1), ast_uri_http);
		ast_uri_encode(field->value, buf2, sizeof(buf2), ast_uri_http);
		ast_str_append(&query, 0, "%s%s=%s", !start ? "&" : "", buf1, buf2);
		start = 0;
	}

	ast_str_append(&query, 0, ")}");
	ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));

	/* Remove any trailing newline characters */
	if ((stringp = strchr(ast_str_buffer(buffer), '\r')) || (stringp = strchr(ast_str_buffer(buffer), '\n'))) {
		*stringp = '\0';
	}

	stringp = ast_str_buffer(buffer);
	while ((pair = strsep(&stringp, "&"))) {
		key = strsep(&pair, "=");
		ast_uri_decode(key, ast_uri_http);
		if (pair) {
			ast_uri_decode(pair, ast_uri_http);
		}

		if (!ast_strlen_zero(key)) {
			if (prev) {
				prev->next = ast_variable_new(key, S_OR(pair, ""), "");
				if (prev->next) {
					prev = prev->next;
				}
			} else {
				prev = var = ast_variable_new(key, S_OR(pair, ""), "");
			}
		}
	}

	return var;
}
static struct ast_config *config_curl(const char *url, const char *unused, const char *file, struct ast_config *cfg, struct ast_flags flags, const char *sugg_incl, const char *who_asked)
{
	struct ast_str *query, *buffer;
	char buf1[200];
	char *stringp, *line, *pair, *key;
	int last_cat_metric = -1, cat_metric = -1;
	struct ast_category *cat = NULL;
	char *cur_cat = "";
	char *category = "", *var_name = "", *var_val = "";
	struct ast_flags loader_flags = { 0 };

	if (!ast_custom_function_find("CURL")) {
		ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
		return NULL;
	}

	if (!(query = ast_str_thread_get(&query_buf, 100))) {
		return NULL;
	}

	if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
		return NULL;
	}

	ast_uri_encode(file, buf1, sizeof(buf1), ast_uri_http);
	ast_str_set(&query, 0, "${CURL(%s/static?file=%s)}", url, buf1);

	/* Do the CURL query */
	ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));

	/* Line oriented output */
	stringp = ast_str_buffer(buffer);
	cat = ast_config_get_current_category(cfg);

	while ((line = strsep(&stringp, "\r\n"))) {
		if (ast_strlen_zero(line)) {
			continue;
		}

		while ((pair = strsep(&line, "&"))) {
			key = strsep(&pair, "=");
			ast_uri_decode(key, ast_uri_http);
			if (pair) {
				ast_uri_decode(pair, ast_uri_http);
			}

			if (!strcasecmp(key, "category")) {
				category = S_OR(pair, "");
			} else if (!strcasecmp(key, "var_name")) {
				var_name = S_OR(pair, "");
			} else if (!strcasecmp(key, "var_val")) {
				var_val = S_OR(pair, "");
			} else if (!strcasecmp(key, "cat_metric")) {
				cat_metric = pair ? atoi(pair) : 0;
			}
		}

		if (!strcmp(var_name, "#include")) {
			if (!ast_config_internal_load(var_val, cfg, loader_flags, "", who_asked))
				return NULL;
		}

		if (!cat || strcmp(category, cur_cat) || last_cat_metric != cat_metric) {
			if (!(cat = ast_category_new(category, "", 99999)))
				break;
			cur_cat = category;
			last_cat_metric = cat_metric;
			ast_category_append(cfg, cat);
		}
		ast_variable_append(cat, ast_variable_new(var_name, var_val, ""));
	}

	return cfg;
}
/*!
 * \brief Excute an Select query and return ast_config list
 * \param url
 * \param unused
 * \param fields list containing one or more field/operator/value set.
 *
 * \retval struct ast_config pointer on success
 * \retval NULL on failure
*/
static struct ast_config *realtime_multi_curl(const char *url, const char *unused, const struct ast_variable *fields)
{
	struct ast_str *query, *buffer;
	char buf1[256], buf2[256];
	const struct ast_variable *field;
	char *stringp, *line, *pair, *key, *initfield = NULL;
	int start = 1;
	struct ast_variable *var = NULL;
	struct ast_config *cfg = NULL;
	struct ast_category *cat = NULL;

	if (!ast_custom_function_find("CURL")) {
		ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
		return NULL;
	}

	if (!(query = ast_str_thread_get(&query_buf, 16))) {
		return NULL;
	}

	if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
		return NULL;
	}

	ast_str_set(&query, 0, "${CURL(%s/multi,", url);

	for (field = fields; field; field = field->next) {
		if (start) {
			char *op;
			initfield = ast_strdupa(field->name);
			if ((op = strchr(initfield, ' ')))
				*op = '\0';
		}
		ast_uri_encode(field->name, buf1, sizeof(buf1), ast_uri_http);
		ast_uri_encode(field->value, buf2, sizeof(buf2), ast_uri_http);
		ast_str_append(&query, 0, "%s%s=%s", !start ? "&" : "", buf1, buf2);
		start = 0;
	}

	ast_str_append(&query, 0, ")}");

	/* Do the CURL query */
	ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));

	if (!(cfg = ast_config_new())) {
		return NULL;
	}

	/* Line oriented output */
	stringp = ast_str_buffer(buffer);
	while ((line = strsep(&stringp, "\r\n"))) {
		if (ast_strlen_zero(line)) {
			continue;
		}

		if (!(cat = ast_category_new("", "", 99999))) {
			continue;
		}

		while ((pair = strsep(&line, "&"))) {
			key = strsep(&pair, "=");
			ast_uri_decode(key, ast_uri_http);
			if (pair) {
				ast_uri_decode(pair, ast_uri_http);
			}

			if (!strcasecmp(key, initfield) && pair) {
				ast_category_rename(cat, pair);
			}

			if (!ast_strlen_zero(key)) {
				var = ast_variable_new(key, S_OR(pair, ""), "");
				ast_variable_append(cat, var);
			}
		}
		ast_category_append(cfg, cat);
	}

	return cfg;
}
Example #13
0
char *ast_sockaddr_stringify_fmt(const struct ast_sockaddr *sa, int format)
{
	struct ast_sockaddr sa_ipv4;
	const struct ast_sockaddr *sa_tmp;
	char host[NI_MAXHOST];
	char port[NI_MAXSERV];
	struct ast_str *str;
	int e;
	static const size_t size = sizeof(host) - 1 + sizeof(port) - 1 + 4;


	if (ast_sockaddr_isnull(sa)) {
		return "(null)";
	}

	if (!(str = ast_str_thread_get(&ast_sockaddr_stringify_buf, size))) {
		return "";
	}

	if (ast_sockaddr_ipv4_mapped(sa, &sa_ipv4)) {
		sa_tmp = &sa_ipv4;
	} else {
		sa_tmp = sa;
	}

	if ((e = getnameinfo((struct sockaddr *)&sa_tmp->ss, sa_tmp->len,
			     format & AST_SOCKADDR_STR_ADDR ? host : NULL,
			     format & AST_SOCKADDR_STR_ADDR ? sizeof(host) : 0,
			     format & AST_SOCKADDR_STR_PORT ? port : 0,
			     format & AST_SOCKADDR_STR_PORT ? sizeof(port): 0,
			     NI_NUMERICHOST | NI_NUMERICSERV))) {
		ast_log(LOG_ERROR, "getnameinfo(): %s\n", gai_strerror(e));
		return "";
	}

	if ((format & AST_SOCKADDR_STR_REMOTE) == AST_SOCKADDR_STR_REMOTE) {
		char *p;
		if (ast_sockaddr_is_ipv6_link_local(sa) && (p = strchr(host, '%'))) {
			*p = '\0';
		}
	}

	switch ((format & AST_SOCKADDR_STR_FORMAT_MASK))  {
	case AST_SOCKADDR_STR_DEFAULT:
		ast_str_set(&str, 0, sa_tmp->ss.ss_family == AF_INET6 ?
				"[%s]:%s" : "%s:%s", host, port);
		break;
	case AST_SOCKADDR_STR_ADDR:
		ast_str_set(&str, 0, "%s", host);
		break;
	case AST_SOCKADDR_STR_HOST:
		ast_str_set(&str, 0,
			    sa_tmp->ss.ss_family == AF_INET6 ? "[%s]" : "%s", host);
		break;
	case AST_SOCKADDR_STR_PORT:
		ast_str_set(&str, 0, "%s", port);
		break;
	default:
		ast_log(LOG_ERROR, "Invalid format\n");
		return "";
	}

	return ast_str_buffer(str);
}