enum.c 4.12 KiB
/*
 * Copyright (c) 2010-2022 Belledonne Communications SARL.
 * This file is part of Liblinphone
 * (see https://gitlab.linphone.org/BC/public/liblinphone).
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
/* enum lookup code */
#ifndef _WIN32_WCE
#include <errno.h>
#endif
#include <string.h>
#include "enum.h"
#define DNS_ANSWER_MAX_SIZE 2048
static char *create_enum_domain(const char *number) {
	long len = (long)strlen(number);
	char *domain = reinterpret_cast<char *>(ms_malloc((size_t)(len * 2) + 10));
	long i, j;
	for (i = 0, j = len - 1; j >= 0; j--) {
		domain[i] = number[j];
		i++;
		domain[i] = '.';
		i++;
	strcpy(&domain[i], "e164.arpa");
	ms_message("enum domain for %s is %s", number, domain);
	return domain;
static bool_t is_a_number(const char *str) {
	char *p = (char *)str;
	bool_t res = FALSE;
	bool_t space_found = FALSE;
	for (;; p++) {
		switch (p[0]) {
			case '9':
			case '8':
			case '7':
			case '6':
			case '5':
			case '4':
			case '3':
			case '2':
			case '1':
			case '0':
				res = TRUE;
				if (space_found) return FALSE; /* avoid splited numbers */
				break;
			case '\0':
				return res;
				break;
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
case ' ': space_found = TRUE; break; default: return FALSE; } } return FALSE; } // 4970072278724 bool_t is_enum(const char *sipaddress, char **enum_domain) { const char *p; p = strstr(sipaddress, "sip:"); if (p == NULL) return FALSE; /* enum should look like sip:4369959250*/ else p += 4; if (is_a_number(p)) { if (enum_domain != NULL) { *enum_domain = create_enum_domain(p); } return TRUE; } return FALSE; } int enum_lookup(const char *enum_domain, enum_lookup_res_t **res) { int err; // char dns_answer[DNS_ANSWER_MAX_SIZE]; char *begin, *end; char *host_result, *command; int i; bool_t forkok; /* ns_msg handle; int count; memset(&handle,0,sizeof(handle)); *res=NULL; ms_message("Resolving %s...",enum_domain); err=res_search(enum_domain,ns_c_in,ns_t_naptr,dns_answer,DNS_ANSWER_MAX_SIZE); if (err<0){ ms_warning("Error resolving enum:",herror(h_errno)); return -1; } ns_initparse(dns_answer,DNS_ANSWER_MAX_SIZE,&handle); count=ns_msg_count(handle,ns_s_an); for(i=0;i<count;i++){ ns_rr rr; memset(&rr,0,sizeof(rr)); ns_parserr(&handle,ns_s_an,i,&rr); ms_message("data=%s",ns_rr_rdata(rr)); } */ command = ms_strdup_printf("host -t naptr %s", enum_domain); forkok = lp_spawn_command_line_sync(command, &host_result, &err); ms_free(command); if (forkok) { if (err != 0) { ms_warning("Host exited with %i error status.", err); return -1; } } else { ms_warning("Could not spawn the \'host\' command."); return -1; } ms_message("Answer received from dns (err=%i): %s", err, host_result); begin = strstr(host_result, "sip:"); if (begin == 0) {
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
ms_warning("No sip address found in dns naptr answer."); return -1; } *res = reinterpret_cast<enum_lookup_res_t *>(ms_malloc0(sizeof(enum_lookup_res_t))); err = 0; for (i = 0; i < MAX_ENUM_LOOKUP_RESULTS; i++) { end = strstr(begin, "!"); if (end == NULL) goto parse_error; end[0] = '\0'; (*res)->sip_address[i] = ms_strdup(begin); err++; begin = strstr(end + 1, "sip:"); if (begin == NULL) break; } ms_free(host_result); return err; parse_error: ms_free(*res); ms_free(host_result); *res = NULL; ms_warning("Parse error in enum_lookup()."); return -1; } void enum_lookup_res_free(enum_lookup_res_t *res) { int i; for (i = 0; i < MAX_ENUM_LOOKUP_RESULTS; i++) { if (res->sip_address[i] != NULL) ms_free(res->sip_address[i]); } ms_free(res); }