Fix disabling DNS relay causes no IP on lan network

This commit is contained in:
suvendhu 2023-09-04 14:52:43 +05:30 committed by Vivek Kumar Dutta
parent 8610bef0a3
commit d0d3480ef6
6 changed files with 217 additions and 14 deletions

View file

@ -74,6 +74,7 @@ All supported tools are presented in this file[BBFDM Tools](./docs/guide/tools.m
* [Explain the different Network Deployment Scenarios](./docs/guide/network_depoyment_scenarios.md)
* [How to Configure MACVLAN](./docs/guide/macvlan_interface.md)
* [Explain Policy Based Routing Management](./docs/guide/policy_based_routing.md)
* [TR181 DNS datamodel](./docs/guide/device_dns.md)
## External dependencies for datamodel objects

75
docs/guide/device_dns.md Normal file
View file

@ -0,0 +1,75 @@
# TR181 DNS datamodel
Aim of this document is to explain how the DNS Client and Relay datamodel objects are mapped in dnsmasq uci.
As per the definition in TR-181, Device.DNS.Client resolves FQDN on behalf of device internal application and Device.DNS.Relay allows the forwarding of local network DNS queries to local or external DNS servers.
For DNS resolution `dnsmasq` package has been used and as per the default configuration of `dnsmasq` it listens on all interfaces and performs the role of both the DNS client and DNS relay by default.
## Default config
```bash
config dnsmasq
option domainneeded '1'
option boguspriv '1'
option filterwin2k '0'
option localise_queries '1'
option rebind_protection '0'
option rebind_localhost '1'
option local '/lan/'
option domain 'lan'
option expandhosts '1'
option nonegcache '0'
option authoritative '1'
option readethers '1'
option leasefile '/tmp/dhcp.leases'
option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
option nonwildcard '1'
option localservice '1'
option dhcpscript '/usr/lib/dnsmasq/user-dhcp-script.sh'
option ednspacket_max '1232'
```
Now datamodel gives the provision to enable/disable DNS relay/client. So if any user disables the DNS relay that means resolution of the DNS queries from LAN network will stop but internal DNS queries from the device itself will be resolved and if the DNS client has been disabled then internal DNS queries will not resolve but DNS queries from LAN network should be resolved.
To achieve this requirement whenever DNS client or relay object gets disabled we add a new section of dnsmasq in the UCI. This new section is then dedicated to DNS client and the section is named as `dns_client`, where as the existing dnsmasq section is then used for DNS relay only. We introduce two separate `dnsmasq` sections one for client and one for relay so that, at any point of time we can enable/disable the client and/or the relay without any effect to the other's work.
## UCI with added new section for DNS client
```bash
config dnsmasq
option domainneeded '1'
option boguspriv '1'
option filterwin2k '0'
option localise_queries '1'
option rebind_protection '0'
option rebind_localhost '1'
option local '/lan/'
option domain 'lan'
option expandhosts '1'
option nonegcache '0'
option authoritative '1'
option readethers '1'
option leasefile '/tmp/dhcp.leases'
option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
option nonwildcard '1'
option localservice '1'
option dhcpscript '/usr/lib/dnsmasq/user-dhcp-script.sh'
option ednspacket_max '1232'
list notinterface 'loopback'
config dnsmasq 'dns_client'
option domainneeded '1'
option boguspriv '1'
option filterwin2k '0'
option localise_queries '1'
option localservice '0'
option rebind_protection '0'
option rebind_localhost '1'
option expandhosts '1'
option nonegcache '0'
option authoritative '1'
option readethers '1'
option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
option nonwildcard '1'
option ednspacket_max '1232'
list interface 'loopback'
```

View file

@ -12,6 +12,7 @@
*/
#include "dhcpv4.h"
#include "dns.h"
#define DHCP_OPTION_VENDORID 60
#define DHCP_OPTION_CLIENTID 61
@ -570,12 +571,14 @@ static char *get_dhcp_option_name(int tag)
/*#Device.DHCPv4.Server.Pool.{i}.!UCI:dhcp/dhcp/dmmap_dhcp*/
static int browseDHCPv4ServerPoolInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
char *ignore = NULL, *interface, *inst = NULL, *v;
char *ignore = NULL, *interface, *inst = NULL, *v, *instance;
struct dhcp_args curr_dhcp_args = {0};
struct dmmap_dup *p = NULL;
LIST_HEAD(leases);
LIST_HEAD(dup_list);
char *relay_sec = get_dnsmasq_section_name();
synchronize_specific_config_sections_with_dmmap("dhcp", "dhcp", "dmmap_dhcp", &dup_list);
if (!list_empty(&dup_list))
@ -588,6 +591,11 @@ static int browseDHCPv4ServerPoolInst(struct dmctx *dmctx, DMNODE *parent_node,
if (ignore && DM_LSTRCMP(ignore, "1") == 0)
continue;
// if dns_relay instance not present, add in the section
dmuci_get_value_by_section_string(p->config_section, "instance", &instance);
if (DM_STRLEN(instance) == 0)
dmuci_set_value_by_section(p->config_section, "instance", relay_sec);
dmuci_get_value_by_section_string(p->config_section, "interface", &interface);
init_dhcp_args(&curr_dhcp_args, p, interface);
@ -995,6 +1003,7 @@ static int addObjDHCPv4ServerPool(char *refparam, struct dmctx *ctx, void *data,
dmuci_rename_section_by_section(s, dhcp_sname);
dmuci_set_value_by_section(s, "ignore", "0");
dmuci_set_value_by_section(s, "dhcpv4", "disabled");
dmuci_set_value_by_section(s, "instance", get_dnsmasq_section_name());
// Defaults to uci defaults value
dmuci_set_value_by_section(s, "start", "100");
dmuci_set_value_by_section(s, "limit", "150");
@ -2776,13 +2785,19 @@ static int set_DHCPv4ClientReqOption_Tag(char *refparam, struct dmctx *ctx, void
/*#Device.DHCPv4.Server.Enable!UCI:dhcp/dnsmasq,@dnsmasq[0]/dhcpv4server*/
static int get_DHCPv4Server_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = dmuci_get_option_value_fallback_def("dhcp", "@dnsmasq[0]", "dhcpv4server", "1");
char *sec = get_dnsmasq_section_name();
if (DM_STRLEN(sec) == 0)
return 0;
*value = dmuci_get_option_value_fallback_def("dhcp", sec, "dhcpv4server", "1");
return 0;
}
static int set_DHCPv4Server_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
bool b;
char *sec;
switch (action) {
case VALUECHECK:
@ -2790,8 +2805,12 @@ static int set_DHCPv4Server_Enable(char *refparam, struct dmctx *ctx, void *data
return FAULT_9007;
return 0;
case VALUESET:
sec = get_dnsmasq_section_name();
if (DM_STRLEN(sec) == 0)
return 0;
string_to_bool(value, &b);
dmuci_set_value("dhcp", "@dnsmasq[0]", "dhcpv4server", b ? "1" : "0");
dmuci_set_value("dhcp", sec, "dhcpv4server", b ? "1" : "0");
return 0;
}
return 0;

View file

@ -11,6 +11,20 @@
#include "dmdiagnostics.h"
#include "dns.h"
/* Returns dnsmasq section name belongs to LAN network */
char *get_dnsmasq_section_name(void)
{
struct uci_section *s = NULL;
uci_foreach_sections("dhcp", "dnsmasq", s) {
char *sec = section_name(s);
if (DM_STRCMP(sec, "dns_client") != 0)
return sec;
}
return "";
}
/*************************************************************
* COMMON FUNCTIONS
**************************************************************/
@ -125,6 +139,57 @@ static int dmmap_synchronizeDNSClientRelayServer(struct dmctx *dmctx, DMNODE *pa
return 0;
}
static void sync_dns_client_relay_section(void)
{
struct uci_section *s = NULL;
struct uci_section *relay_sec = NULL;
struct uci_section *client_sec = NULL;
uci_foreach_sections("dhcp", "dnsmasq", s) {
char *name = section_name(s);
if (DM_STRCMP(name, "dns_client") == 0)
client_sec = s;
else
relay_sec = s;
}
if (client_sec) // already synced
return;
if (relay_sec) {
s = NULL;
uci_foreach_sections("dhcp", "dhcp", s) {
char *str;
dmuci_get_value_by_section_string(s, "ignore", &str);
if (str[0] == '1')
continue;
dmuci_set_value_by_section(s, "instance", section_name(relay_sec));
}
dmuci_add_list_value_by_section(relay_sec, "notinterface", "loopback");
}
dmuci_add_section("dhcp", "dnsmasq", &client_sec);
dmuci_rename_section_by_section(client_sec, "dns_client");
dmuci_set_value_by_section(client_sec, "domainneeded", "1");
dmuci_set_value_by_section(client_sec, "boguspriv", "1");
dmuci_set_value_by_section(client_sec, "filterwin2k", "0");
dmuci_set_value_by_section(client_sec, "localise_queries", "1");
dmuci_set_value_by_section(client_sec, "localservice", "0");
dmuci_set_value_by_section(client_sec, "rebind_protection", "0");
dmuci_set_value_by_section(client_sec, "rebind_localhost", "1");
dmuci_set_value_by_section(client_sec, "expandhosts", "1");
dmuci_set_value_by_section(client_sec, "nonegcache", "0");
dmuci_set_value_by_section(client_sec, "authoritative", "1");
dmuci_set_value_by_section(client_sec, "readethers", "1");
dmuci_set_value_by_section(client_sec, "resolvfile",
dmuci_get_value_by_section_fallback_def(relay_sec, "resolvfile", "/tmp/resolv.conf.d/resolv.conf.auto"));
dmuci_set_value_by_section(client_sec, "nonwildcard", "1");
dmuci_set_value_by_section(client_sec, "ednspacket_max", "1232");
dmuci_add_list_value_by_section(client_sec, "interface", "loopback");
}
/*************************************************************
* ENTRY METHOD
**************************************************************/
@ -222,13 +287,19 @@ static int get_dns_supported_record_types(char *refparam, struct dmctx *ctx, voi
static int get_client_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = "1";
char *v;
dmuci_get_option_value_string("dhcp", "dns_client", "port", &v);
*value = (*v == '0') ? "0" : "1";
return 0;
}
static int get_client_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = "Enabled";
char *v;
dmuci_get_option_value_string("dhcp", "dns_client", "port", &v);
*value = (*v == '0') ? "Disabled" : "Enabled";
return 0;
}
@ -291,17 +362,27 @@ static int get_dns_type(char *refparam, struct dmctx *ctx, void *data, char *ins
static int get_relay_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
char *path = "/etc/rc.d/*dnsmasq";
if (check_file(path))
*value = "1";
else
*value = "0";
char *v, *sec;
sec = get_dnsmasq_section_name();
if (DM_STRLEN(sec) == 0)
return 0;
dmuci_get_option_value_string("dhcp", sec, "port", &v);
*value = (*v == '0') ? "0" : "1";
return 0;
}
static int get_relay_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = (check_file("/etc/rc.d/*dnsmasq")) ? "Enabled" : "Disabled";
char *v, *sec;
sec = get_dnsmasq_section_name();
if (DM_STRLEN(sec) == 0)
return 0;
dmuci_get_option_value_string("dhcp", sec, "port", &v);
*value = (*v == '0') ? "Disabled" : "Enabled";
return 0;
}
@ -426,12 +507,19 @@ static int get_result_response_time(char *refparam, struct dmctx *ctx, void *dat
static int set_client_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
bool b;
sync_dns_client_relay_section();
switch (action) {
case VALUECHECK:
if (bbfdm_validate_boolean(ctx, value))
return FAULT_9007;
break;
case VALUESET:
string_to_bool(value, &b);
char *port = b ? "" : "0";
dmuci_set_value("dhcp", "dns_client", "port", port);
break;
}
return 0;
@ -570,6 +658,9 @@ static int set_dns_interface(char *refparam, struct dmctx *ctx, void *data, char
static int set_relay_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
bool b;
char *port, *sec;
sync_dns_client_relay_section();
switch (action) {
case VALUECHECK:
@ -577,8 +668,13 @@ static int set_relay_enable(char *refparam, struct dmctx *ctx, void *data, char
return FAULT_9007;
break;
case VALUESET:
sec = get_dnsmasq_section_name();
if (DM_STRLEN(sec) == 0)
return 0;
string_to_bool(value, &b);
dmcmd("/etc/init.d/dnsmasq", 1, b ? "enable" : "disable");
port = b ? "" : "0";
dmuci_set_value("dhcp", sec, "port", port);
break;
}
return 0;

View file

@ -27,4 +27,5 @@ extern DMLEAF tDNSDiagnosticsNSLookupDiagnosticsParams[];
extern DMOBJ tDNSDiagnosticsNSLookupDiagnosticsObj[];
extern DMLEAF tDNSDiagnosticsNSLookupDiagnosticsResultParams[];
char *get_dnsmasq_section_name(void);
#endif

View file

@ -9,6 +9,7 @@
*/
#include "dhcpv4.h"
#include "dns.h"
#include "routeradvertisement.h"
struct radv_option_args {
@ -193,13 +194,19 @@ static int delObjRouterAdvertisementInterfaceSettingOption(char *refparam, struc
/*#Device.RouterAdvertisement.Enable!UCI:dhcp/dnsmasq,@dnsmasq[0]/raserver*/
static int get_RouterAdvertisement_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = dmuci_get_option_value_fallback_def("dhcp", "@dnsmasq[0]", "raserver", "1");
char *sec = get_dnsmasq_section_name();
if (DM_STRLEN(sec) == 0)
return 0;
*value = dmuci_get_option_value_fallback_def("dhcp", sec, "raserver", "1");
return 0;
}
static int set_RouterAdvertisement_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
bool b;
char *sec;
switch (action) {
case VALUECHECK:
@ -207,8 +214,12 @@ static int set_RouterAdvertisement_Enable(char *refparam, struct dmctx *ctx, voi
return FAULT_9007;
break;
case VALUESET:
sec = get_dnsmasq_section_name();
if (DM_STRLEN(sec) == 0)
return 0;
string_to_bool(value, &b);
dmuci_set_value("dhcp", "@dnsmasq[0]", "raserver", b ? "1" : "0");
dmuci_set_value("dhcp", sec, "raserver", b ? "1" : "0");
break;
}
return 0;