sgsn: Allow to specify the DNS servers that should be used

If no server is specified the default list will be used. This
allows to separate the servers for the local network and GRX
from each other.
diff --git a/openbsc/include/openbsc/sgsn.h b/openbsc/include/openbsc/sgsn.h
index a92bfc6..0b61da9 100644
--- a/openbsc/include/openbsc/sgsn.h
+++ b/openbsc/include/openbsc/sgsn.h
@@ -68,6 +68,7 @@
 	struct osmo_timer_list ares_timer;
 	struct llist_head ares_fds;
 	ares_channel ares_channel;
+	struct ares_addr_node *ares_servers;
 };
 
 extern struct sgsn_instance *sgsn;
diff --git a/openbsc/src/gprs/sgsn_ares.c b/openbsc/src/gprs/sgsn_ares.c
index 825b01c..c4012a4 100644
--- a/openbsc/src/gprs/sgsn_ares.c
+++ b/openbsc/src/gprs/sgsn_ares.c
@@ -157,10 +157,16 @@
 
 	optmask = ARES_OPT_FLAGS | ARES_OPT_SOCK_STATE_CB;
 
-	/*| ARES_OPT_SERVERS ... TODO..*/
+	if (sgsn->ares_servers)
+		optmask |= ARES_OPT_SERVERS;
 
 	ares_library_init(ARES_LIB_INIT_ALL);
 	rc = ares_init_options(&sgsn->ares_channel, &options, optmask);
+	if (rc != ARES_SUCCESS)
+		return rc;
+
+	if (sgsn->ares_servers)
+		rc = ares_set_servers(sgsn->ares_channel, sgsn->ares_servers);
 
 	return rc;
 }
diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c
index 65b5a39..70d299b 100644
--- a/openbsc/src/gprs/sgsn_vty.c
+++ b/openbsc/src/gprs/sgsn_vty.c
@@ -128,6 +128,7 @@
 	struct sgsn_ggsn_ctx *gctx;
 	struct imsi_acl_entry *acl;
 	struct apn_ctx *actx;
+	struct ares_addr_node *server;
 
 	vty_out(vty, "sgsn%s", VTY_NEWLINE);
 
@@ -147,6 +148,9 @@
 	if (sgsn->cfg.dynamic_lookup)
 		vty_out(vty, " ggsn dynamic%s", VTY_NEWLINE);
 
+	for (server = sgsn->ares_servers; server; server = server->next)
+		vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
+
 	vty_out(vty, " auth-policy %s%s",
 		get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
 		VTY_NEWLINE);
@@ -250,6 +254,19 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
+	"grx-dns-add A.B.C.D",
+	"Add DNS server\nIPv4 address\n")
+{
+	struct ares_addr_node *node = talloc_zero(tall_bsc_ctx, struct ares_addr_node);
+	node->family = AF_INET;
+	inet_aton(argv[0], &node->addr.addr4);
+
+	node->next = sgsn->ares_servers;
+	sgsn->ares_servers = node;
+	return CMD_SUCCESS;
+}
+
 #define APN_STR	"Configure the information per APN\n"
 #define APN_GW_STR "The APN gateway name optionally prefixed by '*' (wildcard)\n"
 
@@ -893,6 +910,7 @@
 	install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
 	install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
 	install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
+	install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
 
 	return 0;
 }