From 475fc3de545bfa145da8410fa968edc27b9a3ae4 Mon Sep 17 00:00:00 2001
From: Mark Spencer <markster@digium.com>
Date: Thu, 1 May 2003 04:29:25 +0000
Subject: [PATCH] Add ENUM configurable search path

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@946 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 asterisk.c               |   5 ++
 configs/enum.conf.sample |  11 +++++
 enum.c                   | 100 ++++++++++++++++++++++++++++++++++++---
 include/asterisk/enum.h  |   2 +
 loader.c                 |   3 +-
 5 files changed, 113 insertions(+), 8 deletions(-)
 create mode 100755 configs/enum.conf.sample

diff --git a/asterisk.c b/asterisk.c
index e083b42240..551c72e32f 100755
--- a/asterisk.c
+++ b/asterisk.c
@@ -26,6 +26,7 @@
 #include <asterisk/term.h>
 #include <asterisk/manager.h>
 #include <asterisk/pbx.h>
+#include <asterisk/enum.h>
 #include <sys/resource.h>
 #include <fcntl.h>
 #include <stdio.h>
@@ -1333,6 +1334,10 @@ int main(int argc, char *argv[])
 		printf(term_quit());
 		exit(1);
 	}
+	if (ast_enum_init()) {
+		printf(term_quit());
+		exit(1);
+	}
 	/* We might have the option of showing a console, but for now just
 	   do nothing... */
 	if (option_console && !option_verbose)
diff --git a/configs/enum.conf.sample b/configs/enum.conf.sample
new file mode 100755
index 0000000000..d8c412f2c3
--- /dev/null
+++ b/configs/enum.conf.sample
@@ -0,0 +1,11 @@
+;
+; ENUM Configuration for resolving phone numbers over DNS
+;
+; Sample config for Asterisk
+;
+[general]
+;
+; The search list for domains may be customized.  Domains are searched
+; in the order they are listed here.
+;
+search => e164.arpa
diff --git a/enum.c b/enum.c
index d606232ac7..cfd2bcf82f 100755
--- a/enum.c
+++ b/enum.c
@@ -1,11 +1,12 @@
 /*
- * ENUM support
- *
- *
  * ENUM Support for Asterisk
  *
  * Copyright (C) 2003 Digium
  *
+ * Written by Mark Spencer <markster@digium.com>
+ *
+ * Funding provided by nic.at
+ *
  * Distributed under the terms of the GNU GPL
  *
  */
@@ -21,11 +22,20 @@
 #include <asterisk/options.h>
 #include <asterisk/enum.h>
 #include <asterisk/channel.h>
+#include <asterisk/config.h>
 
 #define MAX_SIZE 4096
 
 #define TOPLEV "e164.arpa."
 
+static struct enum_search {
+	char toplev[80];
+	struct enum_search *next;
+} *toplevs;
+
+static int enumver = 0;
+
+static pthread_mutex_t enumlock = AST_MUTEX_INITIALIZER;
 
 static int skip_name(unsigned char *s, int len)
 {
@@ -220,11 +230,13 @@ static int parse_answer(unsigned char *dst, int dstlen, unsigned char *tech, int
 int ast_get_enum(struct ast_channel *chan, const char *number, char *dst, int dstlen, char *tech, int techlen)
 {
 	unsigned char answer[MAX_SIZE];
-	char tmp[259 + strlen(TOPLEV)];
+	char tmp[259 + 80];
 	int pos = strlen(number) - 1;
 	int newpos=0;
-	int res;
+	int res = -1;
 	int ret = -1;
+	struct enum_search *s = NULL;
+	int version = -1;
 	struct __res_state enumstate;
 	res_ninit(&enumstate);	
 	if (chan && ast_autoservice_start(chan) < 0)
@@ -236,11 +248,28 @@ int ast_get_enum(struct ast_channel *chan, const char *number, char *dst, int ds
 		tmp[newpos++] = number[pos--];
 		tmp[newpos++] = '.';
 	}
-	strcpy(tmp + newpos, TOPLEV);
 #if 0
 	printf("Looking for '%s'\n", tmp);
 #endif	
-	res = res_nsearch(&enumstate, tmp, C_IN, T_NAPTR, answer, sizeof(answer));
+	
+	for(;;) {
+		ast_pthread_mutex_lock(&enumlock);
+		if (version != enumver) {
+			/* Ooh, a reload... */
+			s = toplevs;
+		} else {
+			s = s->next;
+		}
+		if (s) {
+			strcpy(tmp + newpos, s->toplev);
+		}
+		ast_pthread_mutex_unlock(&enumlock);
+		if (!s)
+			break;
+		res = res_nsearch(&enumstate, tmp, C_IN, T_NAPTR, answer, sizeof(answer));
+		if (res > 0)
+			break;
+	}
 	if (res > 0) {
 		if ((res = parse_answer(dst, dstlen, tech, techlen, answer, res))) {
 			ast_log(LOG_WARNING, "Parse error returned %d\n", res);
@@ -258,3 +287,60 @@ int ast_get_enum(struct ast_channel *chan, const char *number, char *dst, int ds
 	res_nclose(&enumstate);
 	return ret;
 }
+
+static struct enum_search *enum_newtoplev(char *s)
+{
+	struct enum_search *tmp;
+	tmp = malloc(sizeof(struct enum_search));
+	if (tmp) {
+		memset(tmp, 0, sizeof(struct enum_search));
+		strncpy(tmp->toplev, s, sizeof(tmp->toplev) - 1);
+	}
+	return tmp;
+}
+
+int ast_enum_init(void)
+{
+	struct ast_config *cfg;
+	struct enum_search *s, *sl;
+	struct ast_variable *v;
+
+	/* Destroy existing list */
+	ast_pthread_mutex_lock(&enumlock);
+	s = toplevs;
+	while(s) {
+		sl = s;
+		s = s->next;
+		free(sl);
+	}
+	toplevs = NULL;
+	cfg = ast_load("enum.conf");
+	if (cfg) {
+		sl = NULL;
+		v = ast_variable_browse(cfg, "general");
+		while(v) {
+			if (!strcasecmp(v->name, "search")) {
+				s = enum_newtoplev(v->value);
+				if (s) {
+					if (sl)
+						sl->next = s;
+					else
+						toplevs = s;
+					sl = s;
+				}
+			}
+			v = v->next;
+		}
+		ast_destroy(cfg);
+	} else {
+		toplevs = enum_newtoplev(TOPLEV);
+	}
+	enumver++;
+	ast_pthread_mutex_unlock(&enumlock);
+	return 0;
+}
+
+int ast_enum_reload(void)
+{
+	return ast_enum_init();
+}
diff --git a/include/asterisk/enum.h b/include/asterisk/enum.h
index 4f945e95ed..684276860c 100755
--- a/include/asterisk/enum.h
+++ b/include/asterisk/enum.h
@@ -17,4 +17,6 @@
 /* Lookup entry in ENUM Returns 1 if found, 0 if not found, -1 on hangup */
 extern int ast_get_enum(struct ast_channel *chan, const char *number, char *location, int maxloc, char *technology, int maxtech);
 
+extern int ast_enum_init(void);
+extern int ast_enum_reload(void);
 #endif
diff --git a/loader.c b/loader.c
index b47077a772..564a72340f 100755
--- a/loader.c
+++ b/loader.c
@@ -23,9 +23,9 @@
 #include <asterisk/channel.h>
 #include <asterisk/term.h>
 #include <asterisk/manager.h>
+#include <asterisk/enum.h>
 #include <dlfcn.h>
 #include <asterisk/md5.h>
-#define __USE_GNU
 #include <pthread.h>
 #include "asterisk.h"
 #include "astconf.h"
@@ -145,6 +145,7 @@ void ast_module_reload(void)
 
 	/* We'll do the logger and manager the favor of calling its reload here first */
 	reload_manager();
+	ast_enum_reload();
 
 	ast_pthread_mutex_lock(&modlock);
 	m = module_list;
-- 
GitLab