mirror of
https://github.com/samba-team/samba.git
synced 2025-01-08 21:18:16 +03:00
s4-rpc: dnsserver: Fix enumeration of IPv4 and IPv6 addresses
In the initial implementation only IPv4 addresses were supported. Add IPv6 (and mixed IPv4/IPv6) support and all further needed conversion routines to support w2k, dotnet, longhorn clients. Signed-off-by: Guenter Kukkukk <linux@kukkukk.com> Reviewed-by: Amitay Isaacs <amitay@gmail.com> Autobuild-User(master): Amitay Isaacs <amitay@samba.org> Autobuild-Date(master): Wed Nov 26 03:44:07 CET 2014 on sn-devel-104
This commit is contained in:
parent
d5af53c537
commit
3ac4355f3e
@ -202,8 +202,10 @@ static WERROR dnsserver_query_server(struct dnsserver_state *dsstate,
|
||||
r->ServerInfoW2K->fDsAvailable = serverinfo->fDsAvailable;
|
||||
r->ServerInfoW2K->pszServerName = talloc_strdup(mem_ctx, serverinfo->pszServerName);
|
||||
r->ServerInfoW2K->pszDsContainer = talloc_strdup(mem_ctx, serverinfo->pszDsContainer);
|
||||
r->ServerInfoW2K->aipServerAddrs = ip4_array_copy(mem_ctx, serverinfo->aipServerAddrs);
|
||||
r->ServerInfoW2K->aipListenAddrs = ip4_array_copy(mem_ctx, serverinfo->aipListenAddrs);
|
||||
r->ServerInfoW2K->aipServerAddrs = dns_addr_array_to_ip4_array(mem_ctx,
|
||||
serverinfo->aipServerAddrs);
|
||||
r->ServerInfoW2K->aipListenAddrs = dns_addr_array_to_ip4_array(mem_ctx,
|
||||
serverinfo->aipListenAddrs);
|
||||
r->ServerInfoW2K->aipForwarders = ip4_array_copy(mem_ctx, serverinfo->aipForwarders);
|
||||
r->ServerInfoW2K->dwLogLevel = serverinfo->dwLogLevel;
|
||||
r->ServerInfoW2K->dwDebugLevel = serverinfo->dwDebugLevel;
|
||||
@ -244,8 +246,10 @@ static WERROR dnsserver_query_server(struct dnsserver_state *dsstate,
|
||||
r->ServerInfoDotNet->fDsAvailable = serverinfo->fDsAvailable;
|
||||
r->ServerInfoDotNet->pszServerName = talloc_strdup(mem_ctx, serverinfo->pszServerName);
|
||||
r->ServerInfoDotNet->pszDsContainer = talloc_strdup(mem_ctx, serverinfo->pszDsContainer);
|
||||
r->ServerInfoDotNet->aipServerAddrs = ip4_array_copy(mem_ctx, serverinfo->aipServerAddrs);
|
||||
r->ServerInfoDotNet->aipListenAddrs = ip4_array_copy(mem_ctx, serverinfo->aipListenAddrs);
|
||||
r->ServerInfoDotNet->aipServerAddrs = dns_addr_array_to_ip4_array(mem_ctx,
|
||||
serverinfo->aipServerAddrs);
|
||||
r->ServerInfoDotNet->aipListenAddrs = dns_addr_array_to_ip4_array(mem_ctx,
|
||||
serverinfo->aipListenAddrs);
|
||||
r->ServerInfoDotNet->aipForwarders = ip4_array_copy(mem_ctx, serverinfo->aipForwarders);
|
||||
r->ServerInfoDotNet->aipLogFilter = ip4_array_copy(mem_ctx, serverinfo->aipLogFilter);
|
||||
r->ServerInfoDotNet->pwszLogFilePath = talloc_strdup(mem_ctx, serverinfo->pwszLogFilePath);
|
||||
@ -299,8 +303,8 @@ static WERROR dnsserver_query_server(struct dnsserver_state *dsstate,
|
||||
r->ServerInfo->fDsAvailable = serverinfo->fDsAvailable;
|
||||
r->ServerInfo->pszServerName = talloc_strdup(mem_ctx, serverinfo->pszServerName);
|
||||
r->ServerInfo->pszDsContainer = talloc_strdup(mem_ctx, serverinfo->pszDsContainer);
|
||||
r->ServerInfo->aipServerAddrs = ip4_array_to_dns_addr_array(mem_ctx, serverinfo->aipServerAddrs);
|
||||
r->ServerInfo->aipListenAddrs = ip4_array_to_dns_addr_array(mem_ctx, serverinfo->aipListenAddrs);
|
||||
r->ServerInfo->aipServerAddrs = serverinfo->aipServerAddrs;
|
||||
r->ServerInfo->aipListenAddrs = serverinfo->aipListenAddrs;
|
||||
r->ServerInfo->aipForwarders = ip4_array_to_dns_addr_array(mem_ctx, serverinfo->aipForwarders);
|
||||
r->ServerInfo->aipLogFilter = ip4_array_to_dns_addr_array(mem_ctx, serverinfo->aipLogFilter);
|
||||
r->ServerInfo->pwszLogFilePath = talloc_strdup(mem_ctx, serverinfo->pwszLogFilePath);
|
||||
@ -700,9 +704,9 @@ static WERROR dnsserver_query_server(struct dnsserver_state *dsstate,
|
||||
is_addresses = 1;
|
||||
} else if (strcasecmp(operation, "ListenAddresses") == 0) {
|
||||
if (client_version == DNS_CLIENT_VERSION_LONGHORN) {
|
||||
answer_addrarray = ip4_array_to_dns_addr_array(mem_ctx, serverinfo->aipListenAddrs);
|
||||
answer_addrarray = serverinfo->aipListenAddrs;
|
||||
} else {
|
||||
answer_iparray = ip4_array_copy(mem_ctx, serverinfo->aipListenAddrs);
|
||||
answer_iparray = dns_addr_array_to_ip4_array(mem_ctx, serverinfo->aipListenAddrs);
|
||||
}
|
||||
is_addresses = 1;
|
||||
} else if (strcasecmp(operation, "BreakOnReceiveFrom") == 0) {
|
||||
|
@ -91,6 +91,62 @@ struct DNS_ADDR_ARRAY *ip4_array_to_dns_addr_array(TALLOC_CTX *mem_ctx,
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct IP4_ARRAY *dns_addr_array_to_ip4_array(TALLOC_CTX *mem_ctx,
|
||||
struct DNS_ADDR_ARRAY *ip)
|
||||
{
|
||||
struct IP4_ARRAY *ret;
|
||||
int i, count, curr;
|
||||
|
||||
if (ip == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
/* We must only return IPv4 addresses.
|
||||
The passed DNS_ADDR_ARRAY may contain:
|
||||
- only ipv4 addresses
|
||||
- only ipv6 addresses
|
||||
- a mixture of both
|
||||
- an empty array
|
||||
*/
|
||||
ret = talloc_zero(mem_ctx, struct IP4_ARRAY);
|
||||
if (!ret) {
|
||||
return ret;
|
||||
}
|
||||
if (ip->AddrCount == 0 || ip->Family == AF_INET6) {
|
||||
ret->AddrCount = 0;
|
||||
return ret;
|
||||
}
|
||||
/* Now only ipv4 addresses or a mixture are left */
|
||||
count = 0;
|
||||
for (i = 0; i < ip->AddrCount; i++) {
|
||||
if (ip->AddrArray[i].MaxSa[0] == 0x02) {
|
||||
/* Is ipv4 */
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count == 0) {
|
||||
/* should not happen */
|
||||
ret->AddrCount = 0;
|
||||
return ret;
|
||||
}
|
||||
ret->AddrArray = talloc_zero_array(mem_ctx, uint32_t, count);
|
||||
if (ret->AddrArray) {
|
||||
curr = 0;
|
||||
for (i = 0; i < ip->AddrCount; i++) {
|
||||
if (ip->AddrArray[i].MaxSa[0] == 0x02) {
|
||||
/* Is ipv4 */
|
||||
memcpy(&ret->AddrArray[curr],
|
||||
&ip->AddrArray[i].MaxSa[4],
|
||||
sizeof(uint32_t));
|
||||
curr++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
talloc_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
ret->AddrCount = curr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct DNS_ADDR_ARRAY *dns_addr_array_copy(TALLOC_CTX *mem_ctx,
|
||||
struct DNS_ADDR_ARRAY *addr)
|
||||
|
@ -46,8 +46,8 @@ struct dnsserver_serverinfo {
|
||||
char * pszDomainDirectoryPartition;
|
||||
char * pszForestDirectoryPartition;
|
||||
|
||||
struct IP4_ARRAY * aipServerAddrs;
|
||||
struct IP4_ARRAY * aipListenAddrs;
|
||||
struct DNS_ADDR_ARRAY * aipServerAddrs;
|
||||
struct DNS_ADDR_ARRAY * aipListenAddrs;
|
||||
struct IP4_ARRAY * aipForwarders;
|
||||
|
||||
struct IP4_ARRAY * aipLogFilter;
|
||||
@ -179,6 +179,8 @@ struct dns_tree {
|
||||
|
||||
struct IP4_ARRAY *ip4_array_copy(TALLOC_CTX *mem_ctx, struct IP4_ARRAY *ip4);
|
||||
struct DNS_ADDR_ARRAY *ip4_array_to_dns_addr_array(TALLOC_CTX *mem_ctx, struct IP4_ARRAY *ip4);
|
||||
struct IP4_ARRAY *dns_addr_array_to_ip4_array(TALLOC_CTX *mem_ctx,
|
||||
struct DNS_ADDR_ARRAY *ip);
|
||||
struct DNS_ADDR_ARRAY *dns_addr_array_copy(TALLOC_CTX *mem_ctx, struct DNS_ADDR_ARRAY *addr);
|
||||
|
||||
int dns_split_name_components(TALLOC_CTX *mem_ctx, const char *name, char ***components);
|
||||
@ -217,7 +219,6 @@ struct ldb_dn *dnsserver_name_to_dn(TALLOC_CTX *mem_ctx, struct dnsserver_zone *
|
||||
const char *name);
|
||||
uint32_t dnsserver_zone_to_request_filter(const char *zone);
|
||||
|
||||
|
||||
/* Database functions from dnsdb.c */
|
||||
|
||||
struct dnsserver_partition *dnsserver_db_enumerate_partitions(TALLOC_CTX *mem_ctx,
|
||||
|
@ -24,7 +24,78 @@
|
||||
#include "rpc_server/common/common.h"
|
||||
#include "dsdb/samdb/samdb.h"
|
||||
#include "lib/socket/netif.h"
|
||||
#include "lib/util/util_net.h"
|
||||
|
||||
static struct DNS_ADDR_ARRAY *fill_dns_addr_array(TALLOC_CTX *mem_ctx,
|
||||
struct loadparm_context *lp_ctx,
|
||||
bool listen_only)
|
||||
{
|
||||
struct interface *ifaces;
|
||||
int num_interfaces, i;
|
||||
struct DNS_ADDR_ARRAY *dns_addr_array;
|
||||
const char *ipstr;
|
||||
bool have_ipv4, have_ipv6;
|
||||
uint16_t family;
|
||||
|
||||
have_ipv4 = have_ipv6 = false;
|
||||
|
||||
if (!listen_only) {
|
||||
/*
|
||||
Return all interfaces from kernel
|
||||
Not implemented!
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Only the used interfaces */
|
||||
load_interface_list(mem_ctx, lp_ctx, &ifaces);
|
||||
num_interfaces = iface_list_count(ifaces);
|
||||
|
||||
dns_addr_array = talloc_zero(mem_ctx, struct DNS_ADDR_ARRAY);
|
||||
if (dns_addr_array == NULL) {
|
||||
goto nomem;
|
||||
}
|
||||
dns_addr_array->MaxCount = num_interfaces;
|
||||
dns_addr_array->AddrCount = num_interfaces;
|
||||
if (num_interfaces == 0) {
|
||||
goto nomem;
|
||||
}
|
||||
|
||||
dns_addr_array->AddrArray = talloc_zero_array(mem_ctx, struct DNS_ADDR,
|
||||
num_interfaces);
|
||||
if (!dns_addr_array->AddrArray) {
|
||||
TALLOC_FREE(dns_addr_array);
|
||||
goto nomem;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_interfaces; i++) {
|
||||
ipstr = iface_list_n_ip(ifaces, i);
|
||||
if (is_ipaddress_v4(ipstr)) {
|
||||
have_ipv4 = true;
|
||||
dns_addr_array->AddrArray[i].MaxSa[0] = 0x02;
|
||||
inet_pton(AF_INET, ipstr,
|
||||
&dns_addr_array->AddrArray[i].MaxSa[4]);
|
||||
} else {
|
||||
have_ipv6 = true;
|
||||
dns_addr_array->AddrArray[i].MaxSa[0] = 0x17;
|
||||
inet_pton(AF_INET6, ipstr,
|
||||
&dns_addr_array->AddrArray[i].MaxSa[8]);
|
||||
}
|
||||
}
|
||||
|
||||
if (have_ipv4 && have_ipv6) {
|
||||
family = 0; /* mixed: MS-DNSP */
|
||||
} else if (have_ipv4 && !have_ipv6) {
|
||||
family = AF_INET;
|
||||
} else {
|
||||
family = AF_INET6;
|
||||
}
|
||||
dns_addr_array->Family = family;
|
||||
|
||||
nomem:
|
||||
talloc_free(ifaces);
|
||||
return dns_addr_array;
|
||||
}
|
||||
|
||||
struct dnsserver_serverinfo *dnsserver_init_serverinfo(TALLOC_CTX *mem_ctx,
|
||||
struct loadparm_context *lp_ctx,
|
||||
@ -33,8 +104,6 @@ struct dnsserver_serverinfo *dnsserver_init_serverinfo(TALLOC_CTX *mem_ctx,
|
||||
struct dnsserver_serverinfo *serverinfo;
|
||||
struct dcerpc_server_info *dinfo;
|
||||
struct ldb_dn *domain_dn, *forest_dn;
|
||||
struct interface *ifaces;
|
||||
int num_interfaces, i;
|
||||
|
||||
serverinfo = talloc_zero(mem_ctx, struct dnsserver_serverinfo);
|
||||
if (serverinfo == NULL) {
|
||||
@ -80,31 +149,14 @@ struct dnsserver_serverinfo *dnsserver_init_serverinfo(TALLOC_CTX *mem_ctx,
|
||||
serverinfo->pszForestDirectoryPartition = talloc_asprintf(mem_ctx,
|
||||
"DC=ForestDnsZones,%s",
|
||||
ldb_dn_get_linearized(forest_dn));
|
||||
/* IP addresses on which the DNS server listens for DNS requests */
|
||||
serverinfo->aipListenAddrs = fill_dns_addr_array(mem_ctx, lp_ctx, true);
|
||||
|
||||
load_interface_list(mem_ctx, lp_ctx, &ifaces);
|
||||
num_interfaces = iface_list_count(ifaces);
|
||||
|
||||
serverinfo->aipServerAddrs = talloc_zero(mem_ctx, struct IP4_ARRAY);
|
||||
|
||||
if (serverinfo->aipServerAddrs) {
|
||||
serverinfo->aipServerAddrs->AddrCount = num_interfaces;
|
||||
if (num_interfaces > 0) {
|
||||
serverinfo->aipServerAddrs->AddrArray = talloc_zero_array(mem_ctx,
|
||||
unsigned int,
|
||||
num_interfaces);
|
||||
if (serverinfo->aipServerAddrs->AddrArray) {
|
||||
for (i=0; i<num_interfaces; i++) {
|
||||
serverinfo->aipServerAddrs->AddrArray[i] = inet_addr(iface_list_n_ip(ifaces, i));
|
||||
}
|
||||
} else {
|
||||
serverinfo->aipServerAddrs->AddrCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
talloc_free(ifaces);
|
||||
|
||||
/* Assume listen addresses are same as server addresses */
|
||||
serverinfo->aipListenAddrs = serverinfo->aipServerAddrs;
|
||||
/* All IP addresses available on the server
|
||||
* Not implemented!
|
||||
* Use same as listen addresses
|
||||
*/
|
||||
serverinfo->aipServerAddrs = serverinfo->aipListenAddrs;
|
||||
|
||||
serverinfo->aipForwarders = NULL;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user