-/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#define COPYRIGHT "Copyright (C) 2000-2009 Simon Kelley"
+#define COPYRIGHT "Copyright (c) 2000-2011 Simon Kelley"
#ifndef NO_LARGEFILE
/* Ensure we can use files >2GB (log files may grow this big) */
# define _FILE_OFFSET_BITS 64
#endif
-/* Get linux C library versions. */
-#ifdef __linux__
-# define _GNU_SOURCE
+/* Get linux C library versions and define _GNU_SOURCE for kFreeBSD. */
+#if defined(__linux__) || defined(__GLIBC__)
+# ifndef __ANDROID__
+# define _GNU_SOURCE
+# endif
# include <features.h>
#endif
+/* Need these defined early */
+#if defined(__sun) || defined(__sun__)
+# define _XPG4_2
+# define __EXTENSIONS__
+#endif
+
/* get these before config.h for IPv6 stuff... */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
-#ifdef __APPLE__
-# include <nameser.h>
-# include <arpa/nameser_compat.h>
-#else
-# include <arpa/nameser.h>
-#endif
-
/* and this. */
#include <getopt.h>
#include "config.h"
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+
+#include "dns_protocol.h"
+#include "dhcp_protocol.h"
+
#define gettext_noop(S) (S)
#ifndef LOCALEDIR
# define _(S) (S)
#include <sys/stat.h>
#include <sys/ioctl.h>
#if defined(HAVE_SOLARIS_NETWORK)
-#include <sys/sockio.h>
+# include <sys/sockio.h>
#endif
#include <sys/select.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <limits.h>
#include <net/if.h>
+#if defined(HAVE_SOLARIS_NETWORK) && !defined(ifr_mtu)
+/* Some solaris net/if./h omit this. */
+# define ifr_mtu ifr_ifru.ifru_metric
+#endif
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>
#include <stdarg.h>
-#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun__) || defined (__sun)
+#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun__) || defined (__sun) || defined (__ANDROID__)
# include <netinet/if_ether.h>
#else
# include <net/ethernet.h>
*/
#define DNSMASQ_PACKETSZ PACKETSZ+MAXDNAME+RRFIXEDSZ
-#define OPT_BOGUSPRIV (1u<<0)
-#define OPT_FILTER (1u<<1)
-#define OPT_LOG (1u<<2)
-#define OPT_SELFMX (1u<<3)
-#define OPT_NO_HOSTS (1u<<4)
-#define OPT_NO_POLL (1u<<5)
-#define OPT_DEBUG (1u<<6)
-#define OPT_ORDER (1u<<7)
-#define OPT_NO_RESOLV (1u<<8)
-#define OPT_EXPAND (1u<<9)
-#define OPT_LOCALMX (1u<<10)
-#define OPT_NO_NEG (1u<<11)
-#define OPT_NODOTS_LOCAL (1u<<12)
-#define OPT_NOWILD (1u<<13)
-#define OPT_ETHERS (1u<<14)
-#define OPT_RESOLV_DOMAIN (1u<<15)
-#define OPT_NO_FORK (1u<<16)
-#define OPT_AUTHORITATIVE (1u<<17)
-#define OPT_LOCALISE (1u<<18)
-#define OPT_DBUS (1u<<19)
-#define OPT_DHCP_FQDN (1u<<20)
-#define OPT_NO_PING (1u<<21)
-#define OPT_LEASE_RO (1u<<22)
-#define OPT_ALL_SERVERS (1u<<23)
-#define OPT_RELOAD (1u<<24)
-#define OPT_TFTP (1u<<25)
-#define OPT_TFTP_SECURE (1u<<26)
-#define OPT_TFTP_NOBLOCK (1u<<27)
-#define OPT_LOG_OPTS (1u<<28)
-#define OPT_TFTP_APREF (1u<<29)
-#define OPT_NO_OVERRIDE (1u<<30)
-#define OPT_NO_REBIND (1u<<31)
+/* Trust the compiler dead-code eliminator.... */
+#define option_bool(x) (((x) < 32) ? daemon->options & (1u << (x)) : daemon->options2 & (1u << ((x) - 32)))
+
+#define OPT_BOGUSPRIV 0
+#define OPT_FILTER 1
+#define OPT_LOG 2
+#define OPT_SELFMX 3
+#define OPT_NO_HOSTS 4
+#define OPT_NO_POLL 5
+#define OPT_DEBUG 6
+#define OPT_ORDER 7
+#define OPT_NO_RESOLV 8
+#define OPT_EXPAND 9
+#define OPT_LOCALMX 10
+#define OPT_NO_NEG 11
+#define OPT_NODOTS_LOCAL 12
+#define OPT_NOWILD 13
+#define OPT_ETHERS 14
+#define OPT_RESOLV_DOMAIN 15
+#define OPT_NO_FORK 16
+#define OPT_AUTHORITATIVE 17
+#define OPT_LOCALISE 18
+#define OPT_DBUS 19
+#define OPT_DHCP_FQDN 20
+#define OPT_NO_PING 21
+#define OPT_LEASE_RO 22
+#define OPT_ALL_SERVERS 23
+#define OPT_RELOAD 24
+#define OPT_LOCAL_REBIND 25
+#define OPT_TFTP_SECURE 26
+#define OPT_TFTP_NOBLOCK 27
+#define OPT_LOG_OPTS 28
+#define OPT_TFTP_APREF 29
+#define OPT_NO_OVERRIDE 30
+#define OPT_NO_REBIND 31
+#define OPT_ADD_MAC 32
+#define OPT_DNSSEC 33
+#define OPT_LAST 34
/* extra flags for my_syslog, we use a couple of facilities since they are known
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
};
struct txt_record {
- char *name, *txt;
+ char *name;
+ unsigned char *txt;
unsigned short class, len;
struct txt_record *next;
};
} name;
};
-#define F_IMMORTAL 1
-#define F_CONFIG 2
-#define F_REVERSE 4
-#define F_FORWARD 8
-#define F_DHCP 16
-#define F_NEG 32
-#define F_HOSTS 64
-#define F_IPV4 128
-#define F_IPV6 256
-#define F_BIGNAME 512
-#define F_UPSTREAM 1024
-#define F_SERVER 2048
-#define F_NXDOMAIN 4096
-#define F_QUERY 8192
-#define F_CNAME 16384
-#define F_NOERR 32768
+#define F_IMMORTAL (1u<<0)
+#define F_NAMEP (1u<<1)
+#define F_REVERSE (1u<<2)
+#define F_FORWARD (1u<<3)
+#define F_DHCP (1u<<4)
+#define F_NEG (1u<<5)
+#define F_HOSTS (1u<<6)
+#define F_IPV4 (1u<<7)
+#define F_IPV6 (1u<<8)
+#define F_BIGNAME (1u<<9)
+#define F_NXDOMAIN (1u<<10)
+#define F_CNAME (1u<<11)
+#define F_NOERR (1u<<12)
+#define F_CONFIG (1u<<13)
+/* below here are only valid as args to log_query: cache
+ entries are limited to 16 bits */
+#define F_UPSTREAM (1u<<16)
+#define F_RRNAME (1u<<17)
+#define F_SERVER (1u<<18)
+#define F_QUERY (1u<<19)
+#define F_NSRR (1u<<20)
+
/* struct sockaddr is not large enough to hold any address,
and specifically not big enough to hold an IPv6 address.
#define SERV_MARK 256 /* for mark-and-delete */
#define SERV_TYPE (SERV_HAS_DOMAIN | SERV_FOR_NODOTS)
#define SERV_COUNTED 512 /* workspace for log code */
+#define SERV_USE_RESOLV 1024 /* forward this domain in the normal way */
+#define SERV_NO_REBIND 2048 /* inhibit dns-rebind protection */
struct serverfd {
int fd;
struct irec {
union mysockaddr addr;
struct in_addr netmask; /* only valid for IPv4 */
- int dhcp_ok, mtu;
+ int tftp_ok, mtu;
+ char *name;
struct irec *next;
};
char *name;
};
-/* adn-hosts parms from command-line */
+/* adn-hosts parms from command-line (also dhcp-hostsfile and dhcp-optsfile */
#define AH_DIR 1
#define AH_INACTIVE 2
struct hostsfile {
int index; /* matches to cache entries for logging */
};
+#define FREC_NOREBIND 1
+#define FREC_CHECKING_DISABLED 2
+
struct frec {
union mysockaddr source;
struct all_addr dest;
#endif
unsigned int iface;
unsigned short orig_id, new_id;
- int fd, forwardall;
+ int fd, forwardall, flags;
unsigned int crc;
time_t time;
struct frec *next;
#define ACTION_OLD 3
#define ACTION_ADD 4
-#define DHCP_CHADDR_MAX 16
-
struct dhcp_lease {
int clid_len; /* length of client identifier */
unsigned char *clid; /* clientid */
int hwaddr_len, hwaddr_type;
unsigned char hwaddr[DHCP_CHADDR_MAX];
struct in_addr addr, override, giaddr;
- unsigned char *vendorclass, *userclass, *supplied_hostname;
- unsigned int vendorclass_len, userclass_len, supplied_hostname_len;
+ unsigned char *extradata;
+ unsigned int extradata_len, extradata_size;
int last_interface;
struct dhcp_lease *next;
};
struct dhcp_netid_list *next;
};
+struct tag_if {
+ struct dhcp_netid_list *set;
+ struct dhcp_netid *tag;
+ struct tag_if *next;
+};
+
struct hwaddr_config {
int hwaddr_len, hwaddr_type;
unsigned char hwaddr[DHCP_CHADDR_MAX];
int clid_len; /* length of client identifier */
unsigned char *clid; /* clientid */
char *hostname, *domain;
- struct dhcp_netid netid;
+ struct dhcp_netid_list *netid;
struct in_addr addr;
time_t decline_time;
unsigned int lease_time;
#define CONFIG_TIME 8
#define CONFIG_NAME 16
#define CONFIG_ADDR 32
-#define CONFIG_NETID 64
#define CONFIG_NOCLID 128
#define CONFIG_FROM_ETHERS 256 /* entry created by /etc/ethers */
#define CONFIG_ADDR_HOSTS 512 /* address added by from /etc/hosts */
#define DHOPT_VENDOR 256
#define DHOPT_HEX 512
#define DHOPT_VENDOR_MATCH 1024
+#define DHOPT_RFC3925 2048
struct dhcp_boot {
char *file, *sname;
struct in_addr local, router;
struct in_addr start, end; /* range of available addresses */
int flags;
+ char *interface;
struct dhcp_netid netid, *filter;
struct dhcp_context *next, *current;
};
#define CONTEXT_BRDCAST 4
#define CONTEXT_PROXY 8
-
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned int u32;
-
-
-struct dhcp_packet {
- u8 op, htype, hlen, hops;
- u32 xid;
- u16 secs, flags;
- struct in_addr ciaddr, yiaddr, siaddr, giaddr;
- u8 chaddr[DHCP_CHADDR_MAX], sname[64], file[128];
- u8 options[312];
-};
-
struct ping_result {
struct in_addr addr;
time_t time;
int backoff;
unsigned int block, blocksize, expansion;
off_t offset;
- struct sockaddr_in peer;
+ union mysockaddr peer;
char opt_blocksize, opt_transize, netascii, carrylf;
struct tftp_file *file;
struct tftp_transfer *next;
};
+struct addr_list {
+ struct in_addr addr;
+ struct addr_list *next;
+};
+
+struct interface_list {
+ char *interface;
+ struct interface_list *next;
+};
+
+struct tftp_prefix {
+ char *interface;
+ char *prefix;
+ struct tftp_prefix *next;
+};
+
+
extern struct daemon {
/* datastuctures representing the command-line and
config file arguments. All set (including defaults)
in option.c */
- unsigned int options;
+ unsigned int options, options2;
struct resolvc default_resolv, *resolv_files;
time_t last_resolv;
struct mx_srv_record *mxnames;
int max_logs; /* queue limit */
int cachesize, ftabsize;
int port, query_port, min_port;
- unsigned long local_ttl, neg_ttl;
+ unsigned long local_ttl, neg_ttl, max_ttl;
struct hostsfile *addn_hosts;
struct dhcp_context *dhcp;
struct dhcp_config *dhcp_conf;
struct dhcp_mac *dhcp_macs;
struct dhcp_boot *boot_config;
struct pxe_service *pxe_services;
+ struct tag_if *tag_if;
+ struct addr_list *override_relays;
+ int override;
int enable_pxe;
- struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *force_broadcast, *bootp_dynamic;
- char *dhcp_hosts_file, *dhcp_opts_file;
+ struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names;
+ struct dhcp_netid_list *force_broadcast, *bootp_dynamic;
+ struct hostsfile *dhcp_hosts_file, *dhcp_opts_file;
int dhcp_max, tftp_max;
int dhcp_server_port, dhcp_client_port;
int start_tftp_port, end_tftp_port;
struct doctor *doctors;
unsigned short edns_pktsz;
char *tftp_prefix;
+ struct tftp_prefix *if_prefix; /* per-interface TFTP prefixes */
+ struct interface_list *tftp_interfaces; /* interfaces for limited TFTP service */
+ int tftp_unlimited;
/* globally used stuff for DNS */
char *packet; /* packet buffer */
struct randfd *rfd_save; /* " " */
pid_t tcp_pids[MAX_PROCS];
struct randfd randomsocks[RANDOM_SOCKS];
+ int v6pktinfo;
/* DHCP state */
- int dhcpfd, helperfd;
+ int dhcpfd, helperfd, pxefd;
#if defined(HAVE_LINUX_NETWORK)
int netlinkfd;
#elif defined(HAVE_BSD_NETWORK)
int dhcp_raw_fd, dhcp_icmp_fd;
#endif
struct iovec dhcp_packet;
- char *dhcp_buff, *dhcp_buff2;
+ char *dhcp_buff, *dhcp_buff2, *dhcp_buff3;
struct ping_result *ping_results;
FILE *lease_stream;
struct dhcp_bridge *bridges;
/* cache.c */
void cache_init(void);
-void log_query(unsigned short 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);
void querystr(char *str, unsigned short type);
struct crec *cache_find_by_addr(struct crec *crecp,
char *get_domain(struct in_addr addr);
/* rfc1035.c */
-unsigned short extract_request(HEADER *header, size_t qlen,
+unsigned int extract_request(struct dns_header *header, size_t qlen,
char *name, unsigned short *typep);
-size_t setup_reply(HEADER *header, size_t qlen,
- struct all_addr *addrp, unsigned short flags,
+size_t setup_reply(struct dns_header *header, size_t qlen,
+ struct all_addr *addrp, unsigned int flags,
unsigned long local_ttl);
-int extract_addresses(HEADER *header, size_t qlen, char *namebuff, time_t now);
-size_t answer_request(HEADER *header, char *limit, size_t qlen,
+int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff,
+ time_t now, int is_sign, int checkrebind, int checking_disabled);
+size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
struct in_addr local_addr, struct in_addr local_netmask, time_t now);
-int check_for_bogus_wildcard(HEADER *header, size_t qlen, char *name,
+int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
struct bogus_addr *addr, time_t now);
-unsigned char *find_pseudoheader(HEADER *header, size_t plen,
+unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
size_t *len, unsigned char **p, int *is_sign);
int check_for_local_domain(char *name, time_t now);
-unsigned int questions_crc(HEADER *header, size_t plen, char *buff);
-size_t resize_packet(HEADER *header, size_t plen,
+unsigned int questions_crc(struct dns_header *header, size_t plen, char *buff);
+size_t resize_packet(struct dns_header *header, size_t plen,
unsigned char *pheader, size_t hlen);
+size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3);
/* util.c */
void rand_init(void);
void read_opts (int argc, char **argv, char *compile_opts);
char *option_string(unsigned char opt, int *is_ip, int *is_name);
void reread_dhcp(void);
+void set_option_bool(unsigned int opt);
+struct hostsfile *expand_filelist(struct hostsfile *list);
/* forward.c */
void reply_query(int fd, int family, time_t now);
/* dhcp.c */
#ifdef HAVE_DHCP
void dhcp_init(void);
-void dhcp_packet(time_t now);
+void dhcp_packet(time_t now, int pxe_fd);
struct dhcp_context *address_available(struct dhcp_context *context,
struct in_addr addr,
struct dhcp_netid *netids);
struct dhcp_context *narrow_context(struct dhcp_context *context,
struct in_addr taddr,
struct dhcp_netid *netids);
-int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int negonly);int address_allocate(struct dhcp_context *context,
+int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int negonly);
+int address_allocate(struct dhcp_context *context,
struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
struct dhcp_netid *netids, time_t now);
+struct dhcp_netid *run_tag_if(struct dhcp_netid *input);
int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type);
struct dhcp_config *find_config(struct dhcp_config *configs,
struct dhcp_context *context,
/* rfc2131.c */
#ifdef HAVE_DHCP
size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
- size_t sz, time_t now, int unicast_dest, int *is_inform);
+ size_t sz, time_t now, int unicast_dest, int *is_inform, int pxe_fd);
unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
int clid_len, unsigned char *clid, int *len_out);
#endif
#endif
void send_event(int fd, int event, int data);
void clear_cache_and_reload(time_t now);
+void poll_resolv(int force, int do_reload, time_t now);
/* netlink.c */
#ifdef HAVE_LINUX_NETWORK
#endif
/* bpf.c or netlink.c */
-int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)());
+int iface_enumerate(int family, void *parm, int (callback)());
/* dbus.c */
#ifdef HAVE_DBUS
char *dbus_init(void);
void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset);
void set_dbus_listeners(int *maxfdp, fd_set *rset, fd_set *wset, fd_set *eset);
+# ifdef HAVE_DHCP
void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
+# endif
#endif
/* helper.c */