Commit 36bec089 authored by Simon Kelley's avatar Simon Kelley

Merge branch 'auth'

parents 29d28dda 45dd1fec
...@@ -65,7 +65,7 @@ version = -DVERSION='\"`$(top)/bld/get-version $(top)`\"' ...@@ -65,7 +65,7 @@ version = -DVERSION='\"`$(top)/bld/get-version $(top)`\"'
objs = cache.o rfc1035.o util.o option.o forward.o network.o \ objs = cache.o rfc1035.o util.o option.o forward.o network.o \
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \ dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \ helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
dhcp-common.o outpacket.o radv.o slaac.o dhcp-common.o outpacket.o radv.o slaac.o auth.o
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \ hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
dns-protocol.h radv-protocol.h dns-protocol.h radv-protocol.h
......
...@@ -8,7 +8,7 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \ ...@@ -8,7 +8,7 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
netlink.c network.c option.c rfc1035.c \ netlink.c network.c option.c rfc1035.c \
rfc2131.c tftp.c util.c conntrack.c \ rfc2131.c tftp.c util.c conntrack.c \
dhcp6.c rfc3315.c dhcp-common.c outpacket.c \ dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
radv.c slaac.c radv.c slaac.c auth.c
LOCAL_MODULE := dnsmasq LOCAL_MODULE := dnsmasq
......
This diff is collapsed.
...@@ -1248,14 +1248,14 @@ char *record_source(int index) ...@@ -1248,14 +1248,14 @@ char *record_source(int index)
return "<unknown>"; return "<unknown>";
} }
void querystr(char *str, unsigned short type) void querystr(char *desc, char *str, unsigned short type)
{ {
unsigned int i; unsigned int i;
sprintf(str, "query[type=%d]", type); sprintf(str, "%s[type=%d]", desc, type);
for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++) for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
if (typestr[i].type == type) if (typestr[i].type == type)
sprintf(str,"query[%s]", typestr[i].name); sprintf(str,"%s[%s]", desc, typestr[i].name);
} }
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg) void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
...@@ -1316,6 +1316,8 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg) ...@@ -1316,6 +1316,8 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
source = arg; source = arg;
else if (flags & F_UPSTREAM) else if (flags & F_UPSTREAM)
source = "reply"; source = "reply";
else if (flags & F_AUTH)
source = "auth";
else if (flags & F_SERVER) else if (flags & F_SERVER)
{ {
source = "forwarded"; source = "forwarded";
......
...@@ -42,6 +42,10 @@ ...@@ -42,6 +42,10 @@
#define EDNS0_OPTION_MAC 5 /* dyndns.org temporary assignment */ #define EDNS0_OPTION_MAC 5 /* dyndns.org temporary assignment */
#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq" /* Default - may be overridden by config */ #define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq" /* Default - may be overridden by config */
#define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq" #define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq"
#define AUTH_TTL 600 /* default TTL for auth DNS */
#define SOA_REFRESH 1200 /* SOA refresh default */
#define SOA_RETRY 180 /* SOA retry default */
#define SOA_EXPIRY 1209600 /* SOA expiry default */
/* compile-time options: uncomment below to enable or do eg. /* compile-time options: uncomment below to enable or do eg.
make COPTS=-DHAVE_BROKEN_RTC make COPTS=-DHAVE_BROKEN_RTC
......
...@@ -366,7 +366,7 @@ static int join_multicast_worker(struct in6_addr *local, int prefix, ...@@ -366,7 +366,7 @@ static int join_multicast_worker(struct in6_addr *local, int prefix,
close(fd); close(fd);
/* Are we doing DHCP on this interface? */ /* Are we doing DHCP on this interface? */
if (!iface_check(AF_INET6, (struct all_addr *)local, ifrn_name)) if (!iface_check(AF_INET6, (struct all_addr *)local, ifrn_name, NULL))
return 1; return 1;
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next) for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
......
...@@ -262,7 +262,7 @@ void dhcp_packet(time_t now, int pxe_fd) ...@@ -262,7 +262,7 @@ void dhcp_packet(time_t now, int pxe_fd)
parm.current = NULL; parm.current = NULL;
parm.ind = iface_index; parm.ind = iface_index;
if (!iface_check(AF_INET, (struct all_addr *)&iface_addr, ifr.ifr_name)) if (!iface_check(AF_INET, (struct all_addr *)&iface_addr, ifr.ifr_name, NULL))
{ {
/* If we failed to match the primary address of the interface, see if we've got a --listen-address /* If we failed to match the primary address of the interface, see if we've got a --listen-address
for a secondary */ for a secondary */
......
...@@ -84,6 +84,7 @@ int main (int argc, char **argv) ...@@ -84,6 +84,7 @@ int main (int argc, char **argv)
daemon->addrbuff = safe_malloc(ADDRSTRLEN); daemon->addrbuff = safe_malloc(ADDRSTRLEN);
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
if (!daemon->lease_file) if (!daemon->lease_file)
{ {
...@@ -151,6 +152,14 @@ int main (int argc, char **argv) ...@@ -151,6 +152,14 @@ int main (int argc, char **argv)
now = dnsmasq_time(); now = dnsmasq_time();
/* Create a serial at startup is not configured. */
if (daemon->authinterface && daemon->soa_sn == 0)
#ifdef HAVE_BROKEN_RTC
die(_("zone serial must be configured in --auth-soa"));
#else
daemon->soa_sn = now;
#endif
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
if (daemon->dhcp || daemon->dhcp6) if (daemon->dhcp || daemon->dhcp6)
{ {
...@@ -1440,11 +1449,18 @@ static void check_dns_listeners(fd_set *set, time_t now) ...@@ -1440,11 +1449,18 @@ static void check_dns_listeners(fd_set *set, time_t now)
struct server *s; struct server *s;
int flags; int flags;
struct in_addr netmask; struct in_addr netmask;
int auth_dns;
if (iface) if (iface)
{
netmask = iface->netmask; netmask = iface->netmask;
auth_dns = iface->dns_auth;
}
else else
{
netmask.s_addr = 0; netmask.s_addr = 0;
auth_dns = 0;
}
#ifndef NO_FORK #ifndef NO_FORK
/* Arrange for SIGALARM after CHILD_LIFETIME seconds to /* Arrange for SIGALARM after CHILD_LIFETIME seconds to
...@@ -1463,7 +1479,7 @@ static void check_dns_listeners(fd_set *set, time_t now) ...@@ -1463,7 +1479,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
if ((flags = fcntl(confd, F_GETFL, 0)) != -1) if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
fcntl(confd, F_SETFL, flags & ~O_NONBLOCK); fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
buff = tcp_request(confd, now, &tcp_addr, netmask); buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
shutdown(confd, SHUT_RDWR); shutdown(confd, SHUT_RDWR);
close(confd); close(confd);
......
...@@ -278,6 +278,20 @@ struct cname { ...@@ -278,6 +278,20 @@ struct cname {
struct cname *next; struct cname *next;
}; };
struct auth_zone {
char *domain;
struct subnet {
int is6, prefixlen;
struct in_addr addr4;
#ifdef HAVE_IPV6
struct in6_addr addr6;
#endif
struct subnet *next;
} *subnet;
struct auth_zone *next;
};
struct host_record { struct host_record {
struct name_list { struct name_list {
char *name; char *name;
...@@ -357,6 +371,8 @@ struct crec { ...@@ -357,6 +371,8 @@ struct crec {
#define F_SERVER (1u<<18) #define F_SERVER (1u<<18)
#define F_QUERY (1u<<19) #define F_QUERY (1u<<19)
#define F_NOERR (1u<<20) #define F_NOERR (1u<<20)
#define F_AUTH (1u<<21)
/* composites */ /* composites */
#define F_TYPE (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS) /* Only one may be set */ #define F_TYPE (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS) /* Only one may be set */
...@@ -412,7 +428,7 @@ struct server { ...@@ -412,7 +428,7 @@ struct server {
struct irec { struct irec {
union mysockaddr addr; union mysockaddr addr;
struct in_addr netmask; /* only valid for IPv4 */ struct in_addr netmask; /* only valid for IPv4 */
int tftp_ok, dhcp_ok, mtu, done, dad; int tftp_ok, dhcp_ok, mtu, done, dad, dns_auth;
char *name; char *name;
struct irec *next; struct irec *next;
}; };
...@@ -733,11 +749,13 @@ extern struct daemon { ...@@ -733,11 +749,13 @@ extern struct daemon {
struct ptr_record *ptr; struct ptr_record *ptr;
struct host_record *host_records, *host_records_tail; struct host_record *host_records, *host_records_tail;
struct cname *cnames; struct cname *cnames;
struct auth_zone *auth_zones;
struct interface_name *int_names; struct interface_name *int_names;
char *mxtarget; char *mxtarget;
char *lease_file; char *lease_file;
char *username, *groupname, *scriptuser; char *username, *groupname, *scriptuser;
char *luascript; char *luascript;
char *authserver, *authinterface, *hostmaster;
int group_set, osport; int group_set, osport;
char *domain_suffix; char *domain_suffix;
struct cond_domain *cond_domain; struct cond_domain *cond_domain;
...@@ -751,7 +769,7 @@ extern struct daemon { ...@@ -751,7 +769,7 @@ extern struct daemon {
int max_logs; /* queue limit */ int max_logs; /* queue limit */
int cachesize, ftabsize; int cachesize, ftabsize;
int port, query_port, min_port; int port, query_port, min_port;
unsigned long local_ttl, neg_ttl, max_ttl, max_cache_ttl; unsigned long local_ttl, neg_ttl, max_ttl, max_cache_ttl, auth_ttl;
struct hostsfile *addn_hosts; struct hostsfile *addn_hosts;
struct dhcp_context *dhcp, *dhcp6, *ra_contexts; struct dhcp_context *dhcp, *dhcp6, *ra_contexts;
struct dhcp_config *dhcp_conf; struct dhcp_config *dhcp_conf;
...@@ -778,6 +796,7 @@ extern struct daemon { ...@@ -778,6 +796,7 @@ extern struct daemon {
unsigned int duid_enterprise, duid_config_len; unsigned int duid_enterprise, duid_config_len;
unsigned char *duid_config; unsigned char *duid_config;
char *dbus_name; char *dbus_name;
unsigned long soa_sn, soa_refresh, soa_retry, soa_expiry;
/* globally used stuff for DNS */ /* globally used stuff for DNS */
char *packet; /* packet buffer */ char *packet; /* packet buffer */
...@@ -835,7 +854,7 @@ extern struct daemon { ...@@ -835,7 +854,7 @@ extern struct daemon {
void cache_init(void); void cache_init(void);
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg); void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg);
char *record_source(int index); char *record_source(int index);
void querystr(char *str, unsigned short type); void querystr(char *desc, char *str, unsigned short type);
struct crec *cache_find_by_addr(struct crec *crecp, struct crec *cache_find_by_addr(struct crec *crecp,
struct all_addr *addr, time_t now, struct all_addr *addr, time_t now,
unsigned short prot); unsigned short prot);
...@@ -879,6 +898,16 @@ unsigned int questions_crc(struct dns_header *header, size_t plen, char *buff); ...@@ -879,6 +898,16 @@ unsigned int questions_crc(struct dns_header *header, size_t plen, char *buff);
size_t resize_packet(struct dns_header *header, size_t plen, size_t resize_packet(struct dns_header *header, size_t plen,
unsigned char *pheader, size_t hlen); unsigned char *pheader, size_t hlen);
size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3); size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3);
int add_resource_record(struct dns_header *header, char *limit, int *truncp,
unsigned int nameoffset, unsigned char **pp, unsigned long ttl,
unsigned int *offset, unsigned short type, unsigned short class, char *format, ...);
unsigned char *skip_questions(struct dns_header *header, size_t plen);
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
char *name, int isExtract, int extrabytes);
int in_arpa_name_2_addr(char *namein, struct all_addr *addrp);
/* auth.c */
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now);
/* util.c */ /* util.c */
void rand_init(void); void rand_init(void);
...@@ -935,7 +964,7 @@ char *parse_server(char *arg, union mysockaddr *addr, ...@@ -935,7 +964,7 @@ char *parse_server(char *arg, union mysockaddr *addr,
void reply_query(int fd, int family, time_t now); void reply_query(int fd, int family, time_t now);
void receive_query(struct listener *listen, time_t now); void receive_query(struct listener *listen, time_t now);
unsigned char *tcp_request(int confd, time_t now, unsigned char *tcp_request(int confd, time_t now,
union mysockaddr *local_addr, struct in_addr netmask); union mysockaddr *local_addr, struct in_addr netmask, int auth_dns);
void server_gone(struct server *server); void server_gone(struct server *server);
struct frec *get_new_frec(time_t now, int *wait); struct frec *get_new_frec(time_t now, int *wait);
int send_from(int fd, int nowild, char *packet, size_t len, int send_from(int fd, int nowild, char *packet, size_t len,
...@@ -953,7 +982,7 @@ int enumerate_interfaces(); ...@@ -953,7 +982,7 @@ int enumerate_interfaces();
void create_wildcard_listeners(void); void create_wildcard_listeners(void);
void create_bound_listeners(int die); void create_bound_listeners(int die);
int is_dad_listeners(void); int is_dad_listeners(void);
int iface_check(int family, struct all_addr *addr, char *name); int iface_check(int family, struct all_addr *addr, char *name, int *auth_dns);
int fix_fd(int fd); int fix_fd(int fd);
struct in_addr get_ifaddr(char *intr); struct in_addr get_ifaddr(char *intr);
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
......
...@@ -635,6 +635,7 @@ void receive_query(struct listener *listen, time_t now) ...@@ -635,6 +635,7 @@ void receive_query(struct listener *listen, time_t now)
size_t m; size_t m;
ssize_t n; ssize_t n;
int if_index = 0; int if_index = 0;
int auth_dns = 0;
struct iovec iov[1]; struct iovec iov[1];
struct msghdr msg; struct msghdr msg;
struct cmsghdr *cmptr; struct cmsghdr *cmptr;
...@@ -657,15 +658,18 @@ void receive_query(struct listener *listen, time_t now) ...@@ -657,15 +658,18 @@ void receive_query(struct listener *listen, time_t now)
/* packet buffer overwritten */ /* packet buffer overwritten */
daemon->srv_save = NULL; daemon->srv_save = NULL;
if (listen->iface && listen->family == AF_INET && option_bool(OPT_NOWILD)) dst_addr_4.s_addr = 0;
netmask.s_addr = 0;
if (listen->iface && option_bool(OPT_NOWILD))
{
auth_dns = listen->iface->dns_auth;
if (listen->family == AF_INET)
{ {
dst_addr_4 = listen->iface->addr.in.sin_addr; dst_addr_4 = listen->iface->addr.in.sin_addr;
netmask = listen->iface->netmask; netmask = listen->iface->netmask;
} }
else
{
dst_addr_4.s_addr = 0;
netmask.s_addr = 0;
} }
iov[0].iov_base = daemon->packet; iov[0].iov_base = daemon->packet;
...@@ -760,7 +764,7 @@ void receive_query(struct listener *listen, time_t now) ...@@ -760,7 +764,7 @@ void receive_query(struct listener *listen, time_t now)
/* enforce available interface configuration */ /* enforce available interface configuration */
if (!indextoname(listen->fd, if_index, ifr.ifr_name) || if (!indextoname(listen->fd, if_index, ifr.ifr_name) ||
!iface_check(listen->family, &dst_addr, ifr.ifr_name)) !iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
return; return;
if (listen->family == AF_INET && option_bool(OPT_LOCALISE)) if (listen->family == AF_INET && option_bool(OPT_LOCALISE))
...@@ -796,7 +800,7 @@ void receive_query(struct listener *listen, time_t now) ...@@ -796,7 +800,7 @@ void receive_query(struct listener *listen, time_t now)
{ {
char types[20]; char types[20];
querystr(types, type); querystr(auth_dns ? "auth" : "query", types, type);
if (listen->family == AF_INET) if (listen->family == AF_INET)
log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
...@@ -808,8 +812,18 @@ void receive_query(struct listener *listen, time_t now) ...@@ -808,8 +812,18 @@ void receive_query(struct listener *listen, time_t now)
#endif #endif
} }
m = answer_request (header, ((char *) header) + PACKETSZ, (size_t)n, if (auth_dns)
{
m = answer_auth(header, ((char *) header) + PACKETSZ, (size_t)n, now);
if (m >= 1)
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
(char *)header, m, &source_addr, &dst_addr, if_index);
}
else
{
m = answer_request(header, ((char *) header) + PACKETSZ, (size_t)n,
dst_addr_4, netmask, now); dst_addr_4, netmask, now);
if (m >= 1) if (m >= 1)
{ {
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND), send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
...@@ -821,6 +835,7 @@ void receive_query(struct listener *listen, time_t now) ...@@ -821,6 +835,7 @@ void receive_query(struct listener *listen, time_t now)
daemon->queries_forwarded++; daemon->queries_forwarded++;
else else
daemon->local_answer++; daemon->local_answer++;
}
} }
/* The daemon forks before calling this: it should deal with one connection, /* The daemon forks before calling this: it should deal with one connection,
...@@ -828,7 +843,7 @@ void receive_query(struct listener *listen, time_t now) ...@@ -828,7 +843,7 @@ void receive_query(struct listener *listen, time_t now)
about resources for debug mode, when the fork is suppressed: that's about resources for debug mode, when the fork is suppressed: that's
done by the caller. */ done by the caller. */
unsigned char *tcp_request(int confd, time_t now, unsigned char *tcp_request(int confd, time_t now,
union mysockaddr *local_addr, struct in_addr netmask) union mysockaddr *local_addr, struct in_addr netmask, int auth_dns)
{ {
size_t size = 0; size_t size = 0;
int norebind = 0; int norebind = 0;
...@@ -870,7 +885,7 @@ unsigned char *tcp_request(int confd, time_t now, ...@@ -870,7 +885,7 @@ unsigned char *tcp_request(int confd, time_t now,
{ {
char types[20]; char types[20];
querystr(types, qtype); querystr(auth_dns ? "auth" : "query", types, qtype);
if (peer_addr.sa.sa_family == AF_INET) if (peer_addr.sa.sa_family == AF_INET)
log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
...@@ -887,8 +902,12 @@ unsigned char *tcp_request(int confd, time_t now, ...@@ -887,8 +902,12 @@ unsigned char *tcp_request(int confd, time_t now,
else else
dst_addr_4.s_addr = 0; dst_addr_4.s_addr = 0;
if (auth_dns)
m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now);
else
{
/* m > 0 if answered from cache */ /* m > 0 if answered from cache */
m = answer_request(header, ((char *) header) + 65536, (unsigned int)size, m = answer_request(header, ((char *) header) + 65536, (size_t)size,
dst_addr_4, netmask, now); dst_addr_4, netmask, now);
/* Do this by steam now we're not in the select() loop */ /* Do this by steam now we're not in the select() loop */
...@@ -1017,6 +1036,7 @@ unsigned char *tcp_request(int confd, time_t now, ...@@ -1017,6 +1036,7 @@ unsigned char *tcp_request(int confd, time_t now,
if (m == 0) if (m == 0)
m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl); m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
} }
}
check_log_writer(NULL); check_log_writer(NULL);
......
...@@ -107,7 +107,7 @@ int indextoname(int fd, int index, char *name) ...@@ -107,7 +107,7 @@ int indextoname(int fd, int index, char *name)
#endif #endif
int iface_check(int family, struct all_addr *addr, char *name) int iface_check(int family, struct all_addr *addr, char *name, int *auth)
{ {
struct iname *tmp; struct iname *tmp;
int ret = 1; int ret = 1;
...@@ -115,6 +115,17 @@ int iface_check(int family, struct all_addr *addr, char *name) ...@@ -115,6 +115,17 @@ int iface_check(int family, struct all_addr *addr, char *name)
/* Note: have to check all and not bail out early, so that we set the /* Note: have to check all and not bail out early, so that we set the
"used" flags. */ "used" flags. */
if (auth)
{
if (daemon->authinterface && strcmp(daemon->authinterface, name) == 0)
{
*auth = 1;
return 1;
}
else
*auth = 0;
}
if (daemon->if_names || daemon->if_addrs) if (daemon->if_names || daemon->if_addrs)
{ {
ret = 0; ret = 0;
...@@ -153,6 +164,7 @@ static int iface_allowed(struct irec **irecp, int if_index, ...@@ -153,6 +164,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
struct ifreq ifr; struct ifreq ifr;
int tftp_ok = !!option_bool(OPT_TFTP); int tftp_ok = !!option_bool(OPT_TFTP);
int dhcp_ok = 1; int dhcp_ok = 1;
int auth_dns = 0;
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
struct iname *tmp; struct iname *tmp;
#endif #endif
...@@ -210,10 +222,23 @@ static int iface_allowed(struct irec **irecp, int if_index, ...@@ -210,10 +222,23 @@ static int iface_allowed(struct irec **irecp, int if_index,
} }
if (addr->sa.sa_family == AF_INET && if (addr->sa.sa_family == AF_INET &&
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name)) !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name, &auth_dns))
return 1;
#ifdef HAVE_IPV6
if (addr->sa.sa_family == AF_INET6 &&
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name, &auth_dns))
return 1; return 1;
#endif
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
/* No DHCP where we're doing auth DNS. */
if (auth_dns)
{
tftp_ok = 0;
dhcp_ok = 0;
}
else
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next) for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0)) if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
{ {
...@@ -222,13 +247,6 @@ static int iface_allowed(struct irec **irecp, int if_index, ...@@ -222,13 +247,6 @@ static int iface_allowed(struct irec **irecp, int if_index,
} }
#endif #endif
#ifdef HAVE_IPV6
if (addr->sa.sa_family == AF_INET6 &&
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name))
return 1;
#endif
/* add to list */ /* add to list */
if ((iface = whine_malloc(sizeof(struct irec)))) if ((iface = whine_malloc(sizeof(struct irec))))
{ {
...@@ -236,6 +254,7 @@ static int iface_allowed(struct irec **irecp, int if_index, ...@@ -236,6 +254,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
iface->netmask = netmask; iface->netmask = netmask;
iface->tftp_ok = tftp_ok; iface->tftp_ok = tftp_ok;
iface->dhcp_ok = dhcp_ok; iface->dhcp_ok = dhcp_ok;
iface->dns_auth = auth_dns;
iface->mtu = mtu; iface->mtu = mtu;
iface->dad = dad; iface->dad = dad;
iface->done = 0; iface->done = 0;
......
...@@ -121,6 +121,10 @@ struct myoption { ...@@ -121,6 +121,10 @@ struct myoption {
#define LOPT_RR 310 #define LOPT_RR 310
#define LOPT_CLVERBIND 311 #define LOPT_CLVERBIND 311
#define LOPT_MAXCTTL 312 #define LOPT_MAXCTTL 312
#define LOPT_AUTHZONE 313
#define LOPT_AUTHSERV 314
#define LOPT_AUTHTTL 315
#define LOPT_AUTHSOA 316
#ifdef HAVE_GETOPT_LONG #ifdef HAVE_GETOPT_LONG
static const struct option opts[] = static const struct option opts[] =
...@@ -247,6 +251,10 @@ static const struct myoption opts[] = ...@@ -247,6 +251,10 @@ static const struct myoption opts[] =
{ "dhcp-duid", 1, 0, LOPT_DUID }, { "dhcp-duid", 1, 0, LOPT_DUID },
{ "host-record", 1, 0, LOPT_HOST_REC }, { "host-record", 1, 0, LOPT_HOST_REC },
{ "bind-dynamic", 0, 0, LOPT_CLVERBIND }, { "bind-dynamic", 0, 0, LOPT_CLVERBIND },
{ "auth-zone", 1, 0, LOPT_AUTHZONE },
{ "auth-server", 1, 0, LOPT_AUTHSERV },
{ "auth-ttl", 1, 0, LOPT_AUTHTTL },
{ "auth-soa", 1, 0, LOPT_AUTHSOA },
{ NULL, 0, 0, 0 } { NULL, 0, 0, 0 }
}; };
...@@ -378,7 +386,11 @@ static struct { ...@@ -378,7 +386,11 @@ static struct {
{ LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL }, { LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL },
{ LOPT_HOST_REC, ARG_DUP, "<name>,<address>", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL }, { LOPT_HOST_REC, ARG_DUP, "<name>,<address>", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
{ LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL }, { LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },
{ LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in use - check for new interfaces"), NULL}, { LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in use - check for new interfaces"), NULL },
{ LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", gettext_noop("Export local names to global DNS"), NULL },
{ LOPT_AUTHZONE, ARG_DUP, "<domain>,<subnet>[,<subnet>]", gettext_noop("Domain to export to global DNS"), NULL },
{ LOPT_AUTHTTL, ARG_ONE, "<integer>", gettext_noop("Set TTL for authoritative replies"), NULL },
{ LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritive zone information"), NULL },
{ 0, 0, NULL, NULL, NULL } { 0, 0, NULL, NULL, NULL }
}; };
...@@ -1521,6 +1533,99 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma ...@@ -1521,6 +1533,99 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
break; break;
} }
case LOPT_AUTHSERV: /* --auth-server */
if (!(comma = split(arg)))
ret_err(gen_err);
daemon->authserver = opt_string_alloc(arg);
daemon->authinterface = opt_string_alloc(comma);
break;
case LOPT_AUTHZONE: /* --auth-zone */
{
struct auth_zone *new;
comma = split(arg);
if (!comma)
ret_err(gen_err);
new = safe_malloc(sizeof(struct auth_zone));
new->domain = opt_string_alloc(arg);
new->subnet = NULL;
new->next = daemon->auth_zones;
daemon->auth_zones = new;
while ((arg = comma))
{
int prefixlen = 0;
char *prefix;
struct subnet *subnet = safe_malloc(sizeof(struct subnet));
subnet->next = new->subnet;
new->subnet = subnet;
comma = split(arg);
prefix = split_chr(arg, '/');
if (prefix && !atoi_check(prefix, &prefixlen))
ret_err(gen_err);
if (inet_pton(AF_INET, arg, &subnet->addr4))
{
if ((prefixlen & 0x07) != 0 || prefixlen > 24)
ret_err(_("bad prefix"));
subnet->prefixlen = (prefixlen == 0) ? 24 : prefixlen;
subnet->is6 = 0;
}
#ifdef HAVE_IPV6
else if (inet_pton(AF_INET6, arg, &subnet->addr6))
{
subnet->prefixlen = (prefixlen == 0) ? 64 : prefixlen;
subnet->is6 = 1;
}
#endif
else
ret_err(gen_err);
}
break;
}
case LOPT_AUTHSOA: /* --auth-soa */
comma = split(arg);
atoi_check(arg, (int *)&daemon->soa_sn);
if (comma)
{
char *cp;
arg = comma;
comma = split(arg);
daemon->hostmaster = opt_string_alloc(arg);
for (cp = daemon->hostmaster; *cp; cp++)
if (*cp == '@')
*cp = '.';
if (comma)
{
arg = comma;
comma = split(arg);
atoi_check(arg, (int *)&daemon->soa_refresh);
if (comma)
{
arg = comma;
comma = split(arg);
atoi_check(arg, (int *)&daemon->soa_retry);
if (comma)
{
arg = comma;
comma = split(arg);
atoi_check(arg, (int *)&daemon->soa_expiry);
}
}
}
}
break;
case 's': /* --domain */ case 's': /* --domain */
if (strcmp (arg, "#") == 0) if (strcmp (arg, "#") == 0)
set_option_bool(OPT_RESOLV_DOMAIN); set_option_bool(OPT_RESOLV_DOMAIN);
...@@ -1933,6 +2038,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma ...@@ -1933,6 +2038,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
case LOPT_NEGTTL: /* --neg-ttl */ case LOPT_NEGTTL: /* --neg-ttl */
case LOPT_MAXTTL: /* --max-ttl */ case LOPT_MAXTTL: /* --max-ttl */
case LOPT_MAXCTTL: /* --max-cache-ttl */ case LOPT_MAXCTTL: /* --max-cache-ttl */
case LOPT_AUTHTTL: /* --auth-ttl */
{ {
int ttl; int ttl;
if (!atoi_check(arg, &ttl)) if (!atoi_check(arg, &ttl))
...@@ -1943,6 +2049,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma ...@@ -1943,6 +2049,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
daemon->max_ttl = (unsigned long)ttl; daemon->max_ttl = (unsigned long)ttl;
else if (option == LOPT_MAXCTTL) else if (option == LOPT_MAXCTTL)
daemon->max_cache_ttl = (unsigned long)ttl; daemon->max_cache_ttl = (unsigned long)ttl;
else if (option == LOPT_AUTHTTL)
daemon->auth_ttl = (unsigned long)ttl;
else else
daemon->local_ttl = (unsigned long)ttl; daemon->local_ttl = (unsigned long)ttl;
break; break;
...@@ -3613,6 +3721,10 @@ void read_opts(int argc, char **argv, char *compile_opts) ...@@ -3613,6 +3721,10 @@ void read_opts(int argc, char **argv, char *compile_opts)
daemon->tftp_max = TFTP_MAX_CONNECTIONS; daemon->tftp_max = TFTP_MAX_CONNECTIONS;
daemon->edns_pktsz = EDNS_PKTSZ; daemon->edns_pktsz = EDNS_PKTSZ;
daemon->log_fac = -1; daemon->log_fac = -1;
daemon->auth_ttl = AUTH_TTL;
daemon->soa_refresh = SOA_REFRESH;
daemon->soa_retry = SOA_RETRY;
daemon->soa_expiry = SOA_EXPIRY;
add_txt("version.bind", "dnsmasq-" VERSION ); add_txt("version.bind", "dnsmasq-" VERSION );
add_txt("authors.bind", "Simon Kelley"); add_txt("authors.bind", "Simon Kelley");
add_txt("copyright.bind", COPYRIGHT); add_txt("copyright.bind", COPYRIGHT);
...@@ -3721,6 +3833,14 @@ void read_opts(int argc, char **argv, char *compile_opts) ...@@ -3721,6 +3833,14 @@ void read_opts(int argc, char **argv, char *compile_opts)
#endif /* IPv6 */ #endif /* IPv6 */
} }
/* create default, if not specified */
if (daemon->authserver && !daemon->hostmaster)
{
strcpy(buff, "hostmaster.");
strcat(buff, daemon->authserver);
daemon->hostmaster = opt_string_alloc(buff);
}
/* only one of these need be specified: the other defaults to the host-name */ /* only one of these need be specified: the other defaults to the host-name */
if (option_bool(OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget) if (option_bool(OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
{ {
......
...@@ -149,7 +149,7 @@ void icmp6_packet(void) ...@@ -149,7 +149,7 @@ void icmp6_packet(void)
if (!indextoname(daemon->icmp6fd, if_index, interface)) if (!indextoname(daemon->icmp6fd, if_index, interface))
return; return;
if (!iface_check(AF_LOCAL, NULL, interface)) if (!iface_check(AF_LOCAL, NULL, interface, NULL))
return; return;
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next) for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
......
...@@ -16,10 +16,6 @@ ...@@ -16,10 +16,6 @@
#include "dnsmasq.h" #include "dnsmasq.h"
static int add_resource_record(struct dns_header *header, char *limit, int *truncp,
unsigned int nameoffset, unsigned char **pp,
unsigned long ttl, unsigned int *offset, unsigned short type,
unsigned short class, char *format, ...);
#define CHECK_LEN(header, pp, plen, len) \ #define CHECK_LEN(header, pp, plen, len) \
((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen)) ((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen))
...@@ -27,7 +23,7 @@ static int add_resource_record(struct dns_header *header, char *limit, int *trun ...@@ -27,7 +23,7 @@ static int add_resource_record(struct dns_header *header, char *limit, int *trun
#define ADD_RDLEN(header, pp, plen, len) \ #define ADD_RDLEN(header, pp, plen, len) \
(!CHECK_LEN(header, pp, plen, len) ? 0 : (((pp) += (len)), 1)) (!CHECK_LEN(header, pp, plen, len) ? 0 : (((pp) += (len)), 1))
static int extract_name(struct dns_header *header, size_t plen, unsigned char **pp, int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
char *name, int isExtract, int extrabytes) char *name, int isExtract, int extrabytes)
{ {
unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL; unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
...@@ -173,7 +169,7 @@ static int extract_name(struct dns_header *header, size_t plen, unsigned char ** ...@@ -173,7 +169,7 @@ static int extract_name(struct dns_header *header, size_t plen, unsigned char **
/* Max size of input string (for IPv6) is 75 chars.) */ /* Max size of input string (for IPv6) is 75 chars.) */
#define MAXARPANAME 75 #define MAXARPANAME 75
static int in_arpa_name_2_addr(char *namein, struct all_addr *addrp) int in_arpa_name_2_addr(char *namein, struct all_addr *addrp)
{ {
int j; int j;
char name[MAXARPANAME+1], *cp1; char name[MAXARPANAME+1], *cp1;
...@@ -333,7 +329,7 @@ static unsigned char *skip_name(unsigned char *ansp, struct dns_header *header, ...@@ -333,7 +329,7 @@ static unsigned char *skip_name(unsigned char *ansp, struct dns_header *header,
return ansp; return ansp;
} }
static unsigned char *skip_questions(struct dns_header *header, size_t plen) unsigned char *skip_questions(struct dns_header *header, size_t plen)
{ {
int q; int q;
unsigned char *ansp = (unsigned char *)(header+1); unsigned char *ansp = (unsigned char *)(header+1);
...@@ -1189,7 +1185,7 @@ int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name, ...@@ -1189,7 +1185,7 @@ int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
return 0; return 0;
} }
static int add_resource_record(struct dns_header *header, char *limit, int *truncp, unsigned int nameoffset, unsigned char **pp, int add_resource_record(struct dns_header *header, char *limit, int *truncp, unsigned int nameoffset, unsigned char **pp,
unsigned long ttl, unsigned int *offset, unsigned short type, unsigned short class, char *format, ...) unsigned long ttl, unsigned int *offset, unsigned short type, unsigned short class, char *format, ...)
{ {
va_list ap; va_list ap;
...@@ -1202,7 +1198,18 @@ static int add_resource_record(struct dns_header *header, char *limit, int *trun ...@@ -1202,7 +1198,18 @@ static int add_resource_record(struct dns_header *header, char *limit, int *trun
if (truncp && *truncp) if (truncp && *truncp)
return 0; return 0;
va_start(ap, format); /* make ap point to 1st unamed argument */
if (nameoffset != 0)
{
PUTSHORT(nameoffset | 0xc000, p); PUTSHORT(nameoffset | 0xc000, p);
}
else
{
p = do_rfc1035_name(p, va_arg(ap, char *));
*p++ = 0;
}
PUTSHORT(type, p); PUTSHORT(type, p);
PUTSHORT(class, p); PUTSHORT(class, p);
PUTLONG(ttl, p); /* TTL */ PUTLONG(ttl, p); /* TTL */
...@@ -1210,8 +1217,6 @@ static int add_resource_record(struct dns_header *header, char *limit, int *trun ...@@ -1210,8 +1217,6 @@ static int add_resource_record(struct dns_header *header, char *limit, int *trun
sav = p; /* Save pointer to RDLength field */ sav = p; /* Save pointer to RDLength field */
PUTSHORT(0, p); /* Placeholder RDLength */ PUTSHORT(0, p); /* Placeholder RDLength */
va_start(ap, format); /* make ap point to 1st unamed argument */
for (; *format; format++) for (; *format; format++)
switch (*format) switch (*format)
{ {
...@@ -1857,7 +1862,3 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, ...@@ -1857,7 +1862,3 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
return ansp - (unsigned char *)header; return ansp - (unsigned char *)header;
} }
...@@ -193,12 +193,12 @@ void tftp_request(struct listener *listen, time_t now) ...@@ -193,12 +193,12 @@ void tftp_request(struct listener *listen, time_t now)
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
if (listen->family == AF_INET6) if (listen->family == AF_INET6)
{ {
if (!iface_check(AF_INET6, (struct all_addr *)&addr.in6.sin6_addr, name)) if (!iface_check(AF_INET6, (struct all_addr *)&addr.in6.sin6_addr, name, NULL))
return; return;
} }
else else
#endif #endif
if (!iface_check(AF_INET, (struct all_addr *)&addr.in.sin_addr, name)) if (!iface_check(AF_INET, (struct all_addr *)&addr.in.sin_addr, name, NULL))
return; return;
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment