mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
import of dnsmasq-2.48.tar.gz
This commit is contained in:
@@ -130,7 +130,7 @@ int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)())
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(HAVE_BSD_NETWORK)
|
||||
#if defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP)
|
||||
#include <net/bpf.h>
|
||||
|
||||
void init_bpf(void)
|
||||
@@ -175,7 +175,7 @@ void send_via_bpf(struct dhcp_packet *mess, size_t len,
|
||||
/* Only know how to do ethernet on *BSD */
|
||||
if (mess->htype != ARPHRD_ETHER || mess->hlen != ETHER_ADDR_LEN)
|
||||
{
|
||||
my_syslog(LOG_WARNING, _("DHCP request for unsupported hardware type (%d) received on %s"),
|
||||
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP request for unsupported hardware type (%d) received on %s"),
|
||||
mess->htype, ifr->ifr_name);
|
||||
return;
|
||||
}
|
||||
|
||||
146
src/cache.c
146
src/cache.c
@@ -17,7 +17,10 @@
|
||||
#include "dnsmasq.h"
|
||||
|
||||
static struct crec *cache_head = NULL, *cache_tail = NULL, **hash_table = NULL;
|
||||
static struct crec *dhcp_spare = NULL, *new_chain = NULL;
|
||||
#ifdef HAVE_DHCP
|
||||
static struct crec *dhcp_spare = NULL;
|
||||
#endif
|
||||
static struct crec *new_chain = NULL;
|
||||
static int cache_inserted = 0, cache_live_freed = 0, insert_error;
|
||||
static union bigname *big_free = NULL;
|
||||
static int bignames_left, hash_size;
|
||||
@@ -859,10 +862,11 @@ static int read_hostsfile(char *filename, int index, int cache_size)
|
||||
return name_count;
|
||||
}
|
||||
|
||||
void cache_reload(struct hostsfile *addn_hosts)
|
||||
void cache_reload(void)
|
||||
{
|
||||
struct crec *cache, **up, *tmp;
|
||||
int i, total_size = daemon->cachesize;
|
||||
struct hostsfile *ah;
|
||||
|
||||
cache_inserted = cache_live_freed = 0;
|
||||
|
||||
@@ -889,7 +893,7 @@ void cache_reload(struct hostsfile *addn_hosts)
|
||||
up = &cache->hash_next;
|
||||
}
|
||||
|
||||
if ((daemon->options & OPT_NO_HOSTS) && !addn_hosts)
|
||||
if ((daemon->options & OPT_NO_HOSTS) && !daemon->addn_hosts)
|
||||
{
|
||||
if (daemon->cachesize > 0)
|
||||
my_syslog(LOG_INFO, _("cleared cache"));
|
||||
@@ -898,13 +902,116 @@ void cache_reload(struct hostsfile *addn_hosts)
|
||||
|
||||
if (!(daemon->options & OPT_NO_HOSTS))
|
||||
total_size = read_hostsfile(HOSTSFILE, 0, total_size);
|
||||
while (addn_hosts)
|
||||
|
||||
for (i = 0, ah = daemon->addn_hosts; ah; ah = ah->next)
|
||||
{
|
||||
total_size = read_hostsfile(addn_hosts->fname, addn_hosts->index, total_size);
|
||||
addn_hosts = addn_hosts->next;
|
||||
}
|
||||
if (i <= ah->index)
|
||||
i = ah->index + 1;
|
||||
|
||||
if (ah->flags & AH_DIR)
|
||||
ah->flags |= AH_INACTIVE;
|
||||
else
|
||||
ah->flags &= ~AH_INACTIVE;
|
||||
}
|
||||
|
||||
for (ah = daemon->addn_hosts; ah; ah = ah->next)
|
||||
if (!(ah->flags & AH_INACTIVE))
|
||||
{
|
||||
struct stat buf;
|
||||
if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode))
|
||||
{
|
||||
DIR *dir_stream;
|
||||
struct dirent *ent;
|
||||
|
||||
/* don't read this as a file */
|
||||
ah->flags |= AH_INACTIVE;
|
||||
|
||||
if (!(dir_stream = opendir(ah->fname)))
|
||||
my_syslog(LOG_ERR, _("cannot access directory %s: %s"),
|
||||
ah->fname, strerror(errno));
|
||||
else
|
||||
{
|
||||
while ((ent = readdir(dir_stream)))
|
||||
{
|
||||
size_t lendir = strlen(ah->fname);
|
||||
size_t lenfile = strlen(ent->d_name);
|
||||
struct hostsfile *ah1;
|
||||
char *path;
|
||||
|
||||
/* ignore emacs backups and dotfiles */
|
||||
if (lenfile == 0 ||
|
||||
ent->d_name[lenfile - 1] == '~' ||
|
||||
(ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
|
||||
ent->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
/* see if we have an existing record.
|
||||
dir is ah->fname
|
||||
file is ent->d_name
|
||||
path to match is ah1->fname */
|
||||
|
||||
for (ah1 = daemon->addn_hosts; ah1; ah1 = ah1->next)
|
||||
{
|
||||
if (lendir < strlen(ah1->fname) &&
|
||||
strstr(ah1->fname, ah->fname) == ah1->fname &&
|
||||
ah1->fname[lendir] == '/' &&
|
||||
strcmp(ah1->fname + lendir + 1, ent->d_name) == 0)
|
||||
{
|
||||
ah1->flags &= ~AH_INACTIVE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* make new record */
|
||||
if (!ah1)
|
||||
{
|
||||
if (!(ah1 = whine_malloc(sizeof(struct hostsfile))))
|
||||
continue;
|
||||
|
||||
if (!(path = whine_malloc(lendir + lenfile + 2)))
|
||||
{
|
||||
free(ah1);
|
||||
continue;
|
||||
}
|
||||
|
||||
strcpy(path, ah->fname);
|
||||
strcat(path, "/");
|
||||
strcat(path, ent->d_name);
|
||||
ah1->fname = path;
|
||||
ah1->index = i++;
|
||||
ah1->flags = AH_DIR;
|
||||
ah1->next = daemon->addn_hosts;
|
||||
daemon->addn_hosts = ah1;
|
||||
}
|
||||
|
||||
/* inactivate record if not regular file */
|
||||
if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && !S_ISREG(buf.st_mode))
|
||||
ah1->flags |= AH_INACTIVE;
|
||||
|
||||
}
|
||||
closedir(dir_stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (ah = daemon->addn_hosts; ah; ah = ah->next)
|
||||
if (!(ah->flags & AH_INACTIVE))
|
||||
total_size = read_hostsfile(ah->fname, ah->index, total_size);
|
||||
}
|
||||
|
||||
char *get_domain(struct in_addr addr)
|
||||
{
|
||||
struct cond_domain *c;
|
||||
|
||||
for (c = daemon->cond_domain; c; c = c->next)
|
||||
if (ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
|
||||
ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
|
||||
return c->domain;
|
||||
|
||||
return daemon->domain_suffix;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
void cache_unhash_dhcp(void)
|
||||
{
|
||||
struct crec *cache, **up;
|
||||
@@ -942,7 +1049,7 @@ void cache_add_dhcp_entry(char *host_name,
|
||||
_("not giving name %s to the DHCP lease of %s because "
|
||||
"the name exists in %s with address %s"),
|
||||
host_name, inet_ntoa(*host_address),
|
||||
record_source(daemon->addn_hosts, crec->uid), daemon->namebuff);
|
||||
record_source(crec->uid), daemon->namebuff);
|
||||
return;
|
||||
}
|
||||
else
|
||||
@@ -1009,6 +1116,7 @@ void cache_add_dhcp_entry(char *host_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void dump_cache(time_t now)
|
||||
@@ -1099,20 +1207,18 @@ void dump_cache(time_t now)
|
||||
}
|
||||
}
|
||||
|
||||
char *record_source(struct hostsfile *addn_hosts, int index)
|
||||
char *record_source(int index)
|
||||
{
|
||||
char *source = HOSTSFILE;
|
||||
while (addn_hosts)
|
||||
{
|
||||
if (addn_hosts->index == index)
|
||||
{
|
||||
source = addn_hosts->fname;
|
||||
break;
|
||||
}
|
||||
addn_hosts = addn_hosts->next;
|
||||
}
|
||||
struct hostsfile *ah;
|
||||
|
||||
return source;
|
||||
if (index == 0)
|
||||
return HOSTSFILE;
|
||||
|
||||
for (ah = daemon->addn_hosts; ah; ah = ah->next)
|
||||
if (ah->index == index)
|
||||
return ah->fname;
|
||||
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
void querystr(char *str, unsigned short type)
|
||||
|
||||
51
src/config.h
51
src/config.h
@@ -14,7 +14,7 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define VERSION "2.47"
|
||||
#define VERSION "2.48"
|
||||
|
||||
#define FTABSIZ 150 /* max number of outstanding requests (default) */
|
||||
#define MAX_PROCS 20 /* max no children for TCP requests */
|
||||
@@ -106,9 +106,6 @@ HAVE_BSD_NETWORK
|
||||
HAVE_SOLARIS_NETWORK
|
||||
define exactly one of these to alter interaction with kernel networking.
|
||||
|
||||
HAVE_SOLARIS_PRIVS
|
||||
define for Solaris > 10 which can split privileges.
|
||||
|
||||
HAVE_BROKEN_RTC
|
||||
define this on embedded systems which don't have an RTC
|
||||
which keeps time over reboots. Causes dnsmasq to use uptime
|
||||
@@ -126,6 +123,9 @@ HAVE_BROKEN_RTC
|
||||
HAVE_TFTP
|
||||
define this to get dnsmasq's built-in TFTP server.
|
||||
|
||||
HAVE_DHCP
|
||||
define this to get dnsmasq's DHCP server.
|
||||
|
||||
HAVE_GETOPT_LONG
|
||||
define this if you have GNU libc or GNU getopt.
|
||||
|
||||
@@ -141,11 +141,6 @@ HAVE_DBUS
|
||||
define some methods to allow (re)configuration of the upstream DNS
|
||||
servers via DBus.
|
||||
|
||||
HAVE_BSD_BRIDGE
|
||||
Define this to enable the --bridge-interface option, useful on some
|
||||
BSD systems.
|
||||
|
||||
|
||||
NOTES:
|
||||
For Linux you should define
|
||||
HAVE_LINUX_NETWORK
|
||||
@@ -165,6 +160,7 @@ NOTES:
|
||||
*/
|
||||
|
||||
/* platform independent options- uncomment to enable */
|
||||
#define HAVE_DHCP
|
||||
#define HAVE_TFTP
|
||||
/* #define HAVE_BROKEN_RTC */
|
||||
/* #define HAVE_DBUS */
|
||||
@@ -174,6 +170,11 @@ NOTES:
|
||||
#undef HAVE_TFTP
|
||||
#endif
|
||||
|
||||
/* Allow DHCP to be disabled with COPTS=-DNO_DHCP */
|
||||
#ifdef NO_DHCP
|
||||
#undef HAVE_DHCP
|
||||
#endif
|
||||
|
||||
/* platform dependent options. */
|
||||
|
||||
/* Must preceed __linux__ since uClinux defines __linux__ too. */
|
||||
@@ -211,13 +212,6 @@ NOTES:
|
||||
#define HAVE_GETOPT_LONG
|
||||
#undef HAVE_ARC4RANDOM
|
||||
#undef HAVE_SOCKADDR_SA_LEN
|
||||
/* glibc < 2.2 has broken Sockaddr_in6 so we have to use our own. */
|
||||
/* glibc < 2.2 doesn't define in_addr_t */
|
||||
#if defined(__GLIBC__) && (__GLIBC__ == 2) && \
|
||||
defined(__GLIBC_MINOR__) && (__GLIBC_MINOR__ < 2)
|
||||
typedef unsigned long in_addr_t;
|
||||
# define HAVE_BROKEN_SOCKADDR_IN6
|
||||
#endif
|
||||
|
||||
#elif defined(__FreeBSD__) || \
|
||||
defined(__OpenBSD__) || \
|
||||
@@ -232,7 +226,6 @@ typedef unsigned long in_addr_t;
|
||||
# define HAVE_ARC4RANDOM
|
||||
#endif
|
||||
#define HAVE_SOCKADDR_SA_LEN
|
||||
#define HAVE_BSD_BRIDGE
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
#define HAVE_BSD_NETWORK
|
||||
@@ -247,34 +240,16 @@ typedef unsigned long in_addr_t;
|
||||
#define HAVE_GETOPT_LONG
|
||||
#undef HAVE_ARC4RANDOM
|
||||
#define HAVE_SOCKADDR_SA_LEN
|
||||
#define HAVE_BSD_BRIDGE
|
||||
|
||||
#elif defined(__sun) || defined(__sun__)
|
||||
#define HAVE_SOLARIS_NETWORK
|
||||
/* only Solaris 10 does split privs. */
|
||||
#if (SUNOS_VER >= 10)
|
||||
# define HAVE_SOLARIS_PRIVS
|
||||
# define HAVE_GETOPT_LONG
|
||||
#endif
|
||||
/* some CMSG stuff missing on early solaris */
|
||||
#ifndef OSSH_ALIGNBYTES
|
||||
# define OSSH_ALIGNBYTES (sizeof(int) - 1)
|
||||
#endif
|
||||
#ifndef __CMSG_ALIGN
|
||||
# define __CMSG_ALIGN(p) (((u_int)(p) + OSSH_ALIGNBYTES) &~ OSSH_ALIGNBYTES)
|
||||
#endif
|
||||
#ifndef CMSG_LEN
|
||||
# define CMSG_LEN(len) (__CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
|
||||
#endif
|
||||
#ifndef CMSG_SPACE
|
||||
# define CMSG_SPACE(len) (__CMSG_ALIGN(sizeof(struct cmsghdr)) + __CMSG_ALIGN(len))
|
||||
#endif
|
||||
#define HAVE_GETOPT_LONG
|
||||
#undef HAVE_ARC4RANDOM
|
||||
#undef HAVE_SOCKADDR_SA_LEN
|
||||
|
||||
#define _XPG4_2
|
||||
#define __EXTENSIONS__
|
||||
#define ETHER_ADDR_LEN 6
|
||||
#define ETHER_ADDR_LEN 6
|
||||
|
||||
#endif
|
||||
|
||||
/* Decide if we're going to support IPv6 */
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
|
||||
#define DBUS_API_SUBJECT_TO_CHANGE
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
const char* introspection_xml =
|
||||
@@ -345,11 +344,7 @@ void set_dbus_listeners(int *maxfdp,
|
||||
if (dbus_watch_get_enabled(w->watch))
|
||||
{
|
||||
unsigned int flags = dbus_watch_get_flags(w->watch);
|
||||
#if (DBUS_MINOR > 0)
|
||||
int fd = dbus_watch_get_unix_fd(w->watch);
|
||||
#else
|
||||
int fd = dbus_watch_get_fd(w->watch);
|
||||
#endif
|
||||
|
||||
bump_maxfd(fd, maxfdp);
|
||||
|
||||
@@ -372,11 +367,7 @@ void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)
|
||||
if (dbus_watch_get_enabled(w->watch))
|
||||
{
|
||||
unsigned int flags = 0;
|
||||
#if (DBUS_MINOR > 0)
|
||||
int fd = dbus_watch_get_unix_fd(w->watch);
|
||||
#else
|
||||
int fd = dbus_watch_get_fd(w->watch);
|
||||
#endif
|
||||
|
||||
if (FD_ISSET(fd, rset))
|
||||
flags |= DBUS_WATCH_READABLE;
|
||||
|
||||
158
src/dhcp.c
158
src/dhcp.c
@@ -16,6 +16,8 @@
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
|
||||
struct iface_param {
|
||||
struct in_addr relay, primary;
|
||||
struct dhcp_context *current;
|
||||
@@ -35,7 +37,7 @@ void dhcp_init(void)
|
||||
#endif
|
||||
|
||||
if (fd == -1)
|
||||
die (_("cannot create DHCP socket : %s"), NULL, EC_BADNET);
|
||||
die (_("cannot create DHCP socket: %s"), NULL, EC_BADNET);
|
||||
|
||||
if (!fix_fd(fd) ||
|
||||
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
|
||||
@@ -43,7 +45,7 @@ void dhcp_init(void)
|
||||
#endif
|
||||
#if defined(HAVE_LINUX_NETWORK)
|
||||
setsockopt(fd, SOL_IP, IP_PKTINFO, &oneopt, sizeof(oneopt)) == -1 ||
|
||||
#elif defined(IP_RECVIF)
|
||||
#else
|
||||
setsockopt(fd, IPPROTO_IP, IP_RECVIF, &oneopt, sizeof(oneopt)) == -1 ||
|
||||
#endif
|
||||
setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &oneopt, sizeof(oneopt)) == -1)
|
||||
@@ -51,12 +53,7 @@ void dhcp_init(void)
|
||||
|
||||
/* When bind-interfaces is set, there might be more than one dnmsasq
|
||||
instance binding port 67. That's OK if they serve different networks.
|
||||
Need to set REUSEADDR to make this posible, or REUSEPORT on *BSD.
|
||||
OpenBSD <= 4.0 screws up IP_RECVIF when SO_REUSEPORT is set, but
|
||||
OpenBSD <= 3.9 doesn't have IP_RECVIF anyway, so we just have to elide
|
||||
this for OpenBSD 4.0, if you want more than one instance on oBSD4.0, tough. */
|
||||
|
||||
#ifndef OpenBSD4_0
|
||||
Need to set REUSEADDR to make this posible, or REUSEPORT on *BSD. */
|
||||
if (daemon->options & OPT_NOWILD)
|
||||
{
|
||||
#ifdef SO_REUSEPORT
|
||||
@@ -67,7 +64,6 @@ void dhcp_init(void)
|
||||
if (rc == -1)
|
||||
die(_("failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"), NULL, EC_BADNET);
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
saddr.sin_family = AF_INET;
|
||||
@@ -124,7 +120,7 @@ void dhcp_packet(time_t now)
|
||||
char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
|
||||
#elif defined(HAVE_SOLARIS_NETWORK)
|
||||
char control[CMSG_SPACE(sizeof(unsigned int))];
|
||||
#elif defined(IP_RECVIF)
|
||||
#elif defined(HAVE_BSD_NETWORK)
|
||||
char control[CMSG_SPACE(sizeof(struct sockaddr_dl))];
|
||||
#endif
|
||||
} control_u;
|
||||
@@ -136,13 +132,30 @@ void dhcp_packet(time_t now)
|
||||
msg.msg_iov = &daemon->dhcp_packet;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
do
|
||||
while (1)
|
||||
{
|
||||
msg.msg_flags = 0;
|
||||
while ((sz = recvmsg(daemon->dhcpfd, &msg, MSG_PEEK)) == -1 && errno == EINTR);
|
||||
while ((sz = recvmsg(daemon->dhcpfd, &msg, MSG_PEEK | MSG_TRUNC)) == -1 && errno == EINTR);
|
||||
|
||||
if (sz == -1)
|
||||
return;
|
||||
|
||||
if (!(msg.msg_flags & MSG_TRUNC))
|
||||
break;
|
||||
|
||||
/* Very new Linux kernels return the actual size needed,
|
||||
older ones always return truncated size */
|
||||
if ((size_t)sz == daemon->dhcp_packet.iov_len)
|
||||
{
|
||||
if (!expand_buf(&daemon->dhcp_packet, sz + 100))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
expand_buf(&daemon->dhcp_packet, sz);
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (sz != -1 && (msg.msg_flags & MSG_TRUNC) &&
|
||||
expand_buf(&daemon->dhcp_packet, daemon->dhcp_packet.iov_len + 100));
|
||||
|
||||
/* expand_buf may have moved buffer */
|
||||
mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
|
||||
@@ -154,7 +167,7 @@ void dhcp_packet(time_t now)
|
||||
|
||||
while ((sz = recvmsg(daemon->dhcpfd, &msg, 0)) == -1 && errno == EINTR);
|
||||
|
||||
if (sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options)))
|
||||
if ((msg.msg_flags & MSG_TRUNC) || sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options)))
|
||||
return;
|
||||
|
||||
#if defined (HAVE_LINUX_NETWORK)
|
||||
@@ -166,41 +179,31 @@ void dhcp_packet(time_t now)
|
||||
if (((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_addr.s_addr != INADDR_BROADCAST)
|
||||
unicast_dest = 1;
|
||||
}
|
||||
|
||||
if (!(ifr.ifr_ifindex = iface_index) ||
|
||||
ioctl(daemon->dhcpfd, SIOCGIFNAME, &ifr) == -1)
|
||||
return;
|
||||
|
||||
#elif defined(IP_RECVIF)
|
||||
|
||||
#elif defined(HAVE_BSD_NETWORK)
|
||||
if (msg.msg_controllen >= sizeof(struct cmsghdr))
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
|
||||
#ifdef HAVE_SOLARIS_NETWORK
|
||||
iface_index = *((unsigned int *)CMSG_DATA(cmptr));
|
||||
#else
|
||||
iface_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
|
||||
#endif
|
||||
|
||||
if (!iface_index || !if_indextoname(iface_index, ifr.ifr_name))
|
||||
return;
|
||||
|
||||
|
||||
#elif defined(HAVE_SOLARIS_NETWORK)
|
||||
if (msg.msg_controllen >= sizeof(struct cmsghdr))
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
|
||||
iface_index = *((unsigned int *)CMSG_DATA(cmptr));
|
||||
|
||||
#endif
|
||||
|
||||
if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
|
||||
return;
|
||||
|
||||
#ifdef MSG_BCAST
|
||||
/* OpenBSD tells us when a packet was broadcast */
|
||||
if (!(msg.msg_flags & MSG_BCAST))
|
||||
unicast_dest = 1;
|
||||
#endif
|
||||
|
||||
#else
|
||||
/* fallback for systems without IP_RECVIF - allow only one interface
|
||||
and assume packets arrive from it - yuk. */
|
||||
{
|
||||
struct iname *name;
|
||||
for (name = daemon->if_names; name->isloop; name = name->next);
|
||||
strcpy(ifr.ifr_name, name->name);
|
||||
iface_index = if_nametoindex(name->name);
|
||||
}
|
||||
#endif
|
||||
|
||||
ifr.ifr_addr.sa_family = AF_INET;
|
||||
if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) != -1 )
|
||||
{
|
||||
@@ -208,7 +211,7 @@ void dhcp_packet(time_t now)
|
||||
iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
|
||||
}
|
||||
|
||||
if (!iface_check(AF_INET, (struct all_addr *)addrp, &ifr, &iface_index))
|
||||
if (!iface_check(AF_INET, (struct all_addr *)addrp, ifr.ifr_name, &iface_index))
|
||||
return;
|
||||
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
@@ -218,9 +221,9 @@ void dhcp_packet(time_t now)
|
||||
/* interface may have been changed by alias in iface_check */
|
||||
if (!addrp)
|
||||
{
|
||||
if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) != -1)
|
||||
if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) == -1)
|
||||
{
|
||||
my_syslog(LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
|
||||
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
|
||||
return;
|
||||
}
|
||||
else
|
||||
@@ -319,7 +322,7 @@ void dhcp_packet(time_t now)
|
||||
dest.sin_addr.s_addr = INADDR_BROADCAST;
|
||||
dest.sin_port = htons(daemon->dhcp_client_port);
|
||||
/* note that we don't specify the interface here: that's done by the
|
||||
IP_XMIT_IF sockopt lower down. */
|
||||
IP_BOUND_IF sockopt lower down. */
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -345,12 +348,7 @@ void dhcp_packet(time_t now)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SOLARIS_NETWORK
|
||||
/* OpenSolaris eliminates IP_XMIT_IF */
|
||||
# ifdef IP_XMIT_IF
|
||||
setsockopt(daemon->dhcpfd, IPPROTO_IP, IP_XMIT_IF, &iface_index, sizeof(iface_index));
|
||||
# else
|
||||
setsockopt(daemon->dhcpfd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
|
||||
# endif
|
||||
#endif
|
||||
|
||||
while(sendmsg(daemon->dhcpfd, &msg, 0) == -1 && retry_send());
|
||||
@@ -384,7 +382,7 @@ static int complete_context(struct in_addr local, int if_index,
|
||||
{
|
||||
strcpy(daemon->dhcp_buff, inet_ntoa(context->start));
|
||||
strcpy(daemon->dhcp_buff2, inet_ntoa(context->end));
|
||||
my_syslog(LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
|
||||
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
|
||||
daemon->dhcp_buff, daemon->dhcp_buff2, inet_ntoa(netmask));
|
||||
}
|
||||
context->netmask = netmask;
|
||||
@@ -474,9 +472,9 @@ struct dhcp_context *narrow_context(struct dhcp_context *context,
|
||||
if (!(tmp = address_available(context, taddr, netids)))
|
||||
{
|
||||
for (tmp = context; tmp; tmp = tmp->current)
|
||||
if (is_same_net(taddr, tmp->start, tmp->netmask) &&
|
||||
(tmp->flags & CONTEXT_STATIC))
|
||||
break;
|
||||
if (is_same_net(taddr, tmp->start, tmp->netmask) &&
|
||||
(tmp->flags & CONTEXT_STATIC))
|
||||
break;
|
||||
|
||||
if (!tmp)
|
||||
for (tmp = context; tmp; tmp = tmp->current)
|
||||
@@ -667,7 +665,8 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||
unsigned char *hwaddr, int hw_len,
|
||||
int hw_type, char *hostname)
|
||||
{
|
||||
struct dhcp_config *config;
|
||||
int count, new;
|
||||
struct dhcp_config *config, *candidate;
|
||||
struct hwaddr_config *conf_addr;
|
||||
|
||||
if (clid)
|
||||
@@ -699,17 +698,21 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||
hostname_isequal(config->hostname, hostname) &&
|
||||
is_addr_in_context(context, config))
|
||||
return config;
|
||||
|
||||
for (config = configs; config; config = config->next)
|
||||
for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
|
||||
if (conf_addr->wildcard_mask != 0 &&
|
||||
conf_addr->hwaddr_len == hw_len &&
|
||||
(conf_addr->hwaddr_type == hw_type || conf_addr->hwaddr_type == 0) &&
|
||||
is_addr_in_context(context, config) &&
|
||||
memcmp_masked(conf_addr->hwaddr, hwaddr, hw_len, conf_addr->wildcard_mask))
|
||||
return config;
|
||||
|
||||
return NULL;
|
||||
|
||||
/* use match with fewest wildcast octets */
|
||||
for (candidate = NULL, count = 0, config = configs; config; config = config->next)
|
||||
if (is_addr_in_context(context, config))
|
||||
for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
|
||||
if (conf_addr->wildcard_mask != 0 &&
|
||||
conf_addr->hwaddr_len == hw_len &&
|
||||
(conf_addr->hwaddr_type == hw_type || conf_addr->hwaddr_type == 0) &&
|
||||
(new = memcmp_masked(conf_addr->hwaddr, hwaddr, hw_len, conf_addr->wildcard_mask)) > count)
|
||||
{
|
||||
count = new;
|
||||
candidate = config;
|
||||
}
|
||||
|
||||
return candidate;
|
||||
}
|
||||
|
||||
void dhcp_read_ethers(void)
|
||||
@@ -728,7 +731,7 @@ void dhcp_read_ethers(void)
|
||||
|
||||
if (!f)
|
||||
{
|
||||
my_syslog(LOG_ERR, _("failed to read %s:%s"), ETHERSFILE, strerror(errno));
|
||||
my_syslog(MS_DHCP | LOG_ERR, _("failed to read %s: %s"), ETHERSFILE, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -764,7 +767,7 @@ void dhcp_read_ethers(void)
|
||||
*ip = 0;
|
||||
if (!*ip || parse_hex(buff, hwaddr, ETHER_ADDR_LEN, NULL, NULL) != ETHER_ADDR_LEN)
|
||||
{
|
||||
my_syslog(LOG_ERR, _("bad line at %s line %d"), ETHERSFILE, lineno);
|
||||
my_syslog(MS_DHCP | LOG_ERR, _("bad line at %s line %d"), ETHERSFILE, lineno);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -777,7 +780,7 @@ void dhcp_read_ethers(void)
|
||||
{
|
||||
if ((addr.s_addr = inet_addr(ip)) == (in_addr_t)-1)
|
||||
{
|
||||
my_syslog(LOG_ERR, _("bad address at %s line %d"), ETHERSFILE, lineno);
|
||||
my_syslog(MS_DHCP | LOG_ERR, _("bad address at %s line %d"), ETHERSFILE, lineno);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -791,7 +794,7 @@ void dhcp_read_ethers(void)
|
||||
{
|
||||
if (!canonicalise(ip))
|
||||
{
|
||||
my_syslog(LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno);
|
||||
my_syslog(MS_DHCP | LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -857,7 +860,7 @@ void dhcp_read_ethers(void)
|
||||
|
||||
fclose(f);
|
||||
|
||||
my_syslog(LOG_INFO, _("read %s - %d addresses"), ETHERSFILE, count);
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("read %s - %d addresses"), ETHERSFILE, count);
|
||||
}
|
||||
|
||||
void check_dhcp_hosts(int fatal)
|
||||
@@ -882,7 +885,7 @@ void check_dhcp_hosts(int fatal)
|
||||
die(_("duplicate IP address %s in dhcp-config directive."),
|
||||
inet_ntoa(cp->addr), EC_BADCONF);
|
||||
else
|
||||
my_syslog(LOG_ERR, _("duplicate IP address %s in %s."),
|
||||
my_syslog(MS_DHCP | LOG_ERR, _("duplicate IP address %s in %s."),
|
||||
inet_ntoa(cp->addr), daemon->dhcp_hosts_file);
|
||||
configs->flags &= ~CONFIG_ADDR;
|
||||
}
|
||||
@@ -925,12 +928,12 @@ void dhcp_update_configs(struct dhcp_config *configs)
|
||||
crec = cache_find_by_name(crec, config->hostname, 0, F_IPV4);
|
||||
if (!crec)
|
||||
continue; /* should be never */
|
||||
my_syslog(LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"),
|
||||
my_syslog(MS_DHCP | LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"),
|
||||
config->hostname, inet_ntoa(crec->addr.addr.addr.addr4));
|
||||
}
|
||||
|
||||
if (config_find_by_address(configs, crec->addr.addr.addr.addr4))
|
||||
my_syslog(LOG_WARNING, _("duplicate IP address %s (%s) in dhcp-config directive"),
|
||||
my_syslog(MS_DHCP | LOG_WARNING, _("duplicate IP address %s (%s) in dhcp-config directive"),
|
||||
inet_ntoa(crec->addr.addr.addr.addr4), config->hostname);
|
||||
else
|
||||
{
|
||||
@@ -982,14 +985,5 @@ char *strip_hostname(char *hostname)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *get_domain(struct in_addr addr)
|
||||
{
|
||||
struct cond_domain *c;
|
||||
#endif
|
||||
|
||||
for (c = daemon->cond_domain; c; c = c->next)
|
||||
if (ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
|
||||
ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
|
||||
return c->domain;
|
||||
|
||||
return daemon->domain_suffix;
|
||||
}
|
||||
|
||||
@@ -33,9 +33,6 @@ static char *compile_opts =
|
||||
#ifdef NO_FORK
|
||||
"no-MMU "
|
||||
#endif
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
"BSD-bridge "
|
||||
#endif
|
||||
#ifndef HAVE_DBUS
|
||||
"no-"
|
||||
#endif
|
||||
@@ -44,6 +41,10 @@ static char *compile_opts =
|
||||
"no-"
|
||||
#endif
|
||||
"I18N "
|
||||
#ifndef HAVE_DHCP
|
||||
"no-"
|
||||
#endif
|
||||
"DHCP "
|
||||
#ifndef HAVE_TFTP
|
||||
"no-"
|
||||
#endif
|
||||
@@ -67,9 +68,11 @@ int main (int argc, char **argv)
|
||||
struct iname *if_tmp;
|
||||
int piperead, pipefd[2], err_pipe[2];
|
||||
struct passwd *ent_pw = NULL;
|
||||
#ifdef HAVE_DHCP
|
||||
uid_t script_uid = 0;
|
||||
gid_t script_gid = 0;
|
||||
struct group *gp= NULL;
|
||||
#endif
|
||||
struct group *gp = NULL;
|
||||
long i, max_fd = sysconf(_SC_OPEN_MAX);
|
||||
char *baduser = NULL;
|
||||
int log_err;
|
||||
@@ -108,11 +111,13 @@ int main (int argc, char **argv)
|
||||
daemon->edns_pktsz : DNSMASQ_PACKETSZ;
|
||||
daemon->packet = safe_malloc(daemon->packet_buff_sz);
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
if (!daemon->lease_file)
|
||||
{
|
||||
if (daemon->dhcp)
|
||||
daemon->lease_file = LEASEFILE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Close any file descriptors we inherited apart from std{in|out|err} */
|
||||
for (i = 0; i < max_fd; i++)
|
||||
@@ -145,23 +150,16 @@ int main (int argc, char **argv)
|
||||
|
||||
now = dnsmasq_time();
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
if (daemon->dhcp)
|
||||
{
|
||||
#if !defined(HAVE_LINUX_NETWORK) && !defined(IP_RECVIF)
|
||||
int c;
|
||||
struct iname *tmp;
|
||||
for (c = 0, tmp = daemon->if_names; tmp; tmp = tmp->next)
|
||||
if (!tmp->isloop)
|
||||
c++;
|
||||
if (c != 1)
|
||||
die(_("must set exactly one interface on broken systems without IP_RECVIF"), NULL, EC_BADCONF);
|
||||
#endif
|
||||
/* Note that order matters here, we must call lease_init before
|
||||
creating any file descriptors which shouldn't be leaked
|
||||
to the lease-script init process. */
|
||||
lease_init(now);
|
||||
dhcp_init();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!enumerate_interfaces())
|
||||
die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
|
||||
@@ -204,6 +202,7 @@ int main (int argc, char **argv)
|
||||
if (daemon->port != 0)
|
||||
pre_allocate_sfds();
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
/* Note getpwnam returns static storage */
|
||||
if (daemon->dhcp && daemon->lease_change_command && daemon->scriptuser)
|
||||
{
|
||||
@@ -215,6 +214,7 @@ int main (int argc, char **argv)
|
||||
else
|
||||
baduser = daemon->scriptuser;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
|
||||
baduser = daemon->username;
|
||||
@@ -290,8 +290,9 @@ int main (int argc, char **argv)
|
||||
When startup is complete we close this and the process terminates. */
|
||||
safe_pipe(err_pipe, 0);
|
||||
|
||||
if ((pid = fork()) == -1 )
|
||||
die(_("cannot fork into background: %s"), NULL, EC_MISC);
|
||||
if ((pid = fork()) == -1)
|
||||
/* fd == -1 since we've not forked, never returns. */
|
||||
send_event(-1, EVENT_FORK_ERR, errno);
|
||||
|
||||
if (pid != 0)
|
||||
{
|
||||
@@ -312,9 +313,11 @@ int main (int argc, char **argv)
|
||||
/* NO calls to die() from here on. */
|
||||
|
||||
setsid();
|
||||
pid = fork();
|
||||
|
||||
if (pid != 0 && pid != -1)
|
||||
|
||||
if ((pid = fork()) == -1)
|
||||
send_event(err_pipe[1], EVENT_FORK_ERR, errno);
|
||||
|
||||
if (pid != 0)
|
||||
_exit(0);
|
||||
}
|
||||
#endif
|
||||
@@ -349,7 +352,7 @@ int main (int argc, char **argv)
|
||||
|
||||
/* if we are to run scripts, we need to fork a helper before dropping root. */
|
||||
daemon->helperfd = -1;
|
||||
#ifndef NO_FORK
|
||||
#if defined(HAVE_DHCP) && !defined(NO_FORK)
|
||||
if (daemon->dhcp && daemon->lease_change_command)
|
||||
daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
|
||||
#endif
|
||||
@@ -380,7 +383,7 @@ int main (int argc, char **argv)
|
||||
if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1) == -1)
|
||||
bad_capabilities = errno;
|
||||
|
||||
#elif defined(HAVE_SOLARIS_PRIVS)
|
||||
#elif defined(HAVE_SOLARIS_NETWORK)
|
||||
/* http://developers.sun.com/solaris/articles/program_privileges.html */
|
||||
priv_set_t *priv_set;
|
||||
|
||||
@@ -400,9 +403,6 @@ int main (int argc, char **argv)
|
||||
if (priv_set)
|
||||
priv_freeset(priv_set);
|
||||
|
||||
#elif defined(HAVE_SOLARIS_NETWORK)
|
||||
|
||||
bad_capabilities = ENOTSUP;
|
||||
#endif
|
||||
|
||||
if (bad_capabilities != 0)
|
||||
@@ -482,6 +482,7 @@ int main (int argc, char **argv)
|
||||
if (daemon->max_logs != 0)
|
||||
my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
if (daemon->dhcp)
|
||||
{
|
||||
struct dhcp_context *dhcp_tmp;
|
||||
@@ -490,13 +491,16 @@ int main (int argc, char **argv)
|
||||
{
|
||||
prettyprint_time(daemon->dhcp_buff2, dhcp_tmp->lease_time);
|
||||
strcpy(daemon->dhcp_buff, inet_ntoa(dhcp_tmp->start));
|
||||
my_syslog(LOG_INFO,
|
||||
my_syslog(MS_DHCP | LOG_INFO,
|
||||
(dhcp_tmp->flags & CONTEXT_STATIC) ?
|
||||
_("DHCP, static leases only on %.0s%s, lease time %s") :
|
||||
(dhcp_tmp->flags & CONTEXT_PROXY) ?
|
||||
_("DHCP, proxy on subnet %.0s%s%.0s") :
|
||||
_("DHCP, IP range %s -- %s, lease time %s"),
|
||||
daemon->dhcp_buff, inet_ntoa(dhcp_tmp->end), daemon->dhcp_buff2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
if (daemon->options & OPT_TFTP)
|
||||
@@ -506,7 +510,7 @@ int main (int argc, char **argv)
|
||||
max_fd = FD_SETSIZE;
|
||||
#endif
|
||||
|
||||
my_syslog(LOG_INFO, "TFTP %s%s %s",
|
||||
my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s",
|
||||
daemon->tftp_prefix ? _("root is ") : _("enabled"),
|
||||
daemon->tftp_prefix ? daemon->tftp_prefix: "",
|
||||
daemon->options & OPT_TFTP_SECURE ? _("secure mode") : "");
|
||||
@@ -534,7 +538,7 @@ int main (int argc, char **argv)
|
||||
if (daemon->tftp_max > max_fd)
|
||||
{
|
||||
daemon->tftp_max = max_fd;
|
||||
my_syslog(LOG_WARNING,
|
||||
my_syslog(MS_TFTP | LOG_WARNING,
|
||||
_("restricting maximum simultaneous TFTP transfers to %d"),
|
||||
daemon->tftp_max);
|
||||
}
|
||||
@@ -582,11 +586,13 @@ int main (int argc, char **argv)
|
||||
set_dbus_listeners(&maxfd, &rset, &wset, &eset);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
if (daemon->dhcp)
|
||||
{
|
||||
FD_SET(daemon->dhcpfd, &rset);
|
||||
bump_maxfd(daemon->dhcpfd, &maxfd);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
FD_SET(daemon->netlinkfd, &rset);
|
||||
@@ -596,7 +602,8 @@ int main (int argc, char **argv)
|
||||
FD_SET(piperead, &rset);
|
||||
bump_maxfd(piperead, &maxfd);
|
||||
|
||||
#ifndef NO_FORK
|
||||
#ifdef HAVE_DHCP
|
||||
# ifdef NO_FORK
|
||||
while (helper_buf_empty() && do_script_run(now));
|
||||
|
||||
if (!helper_buf_empty())
|
||||
@@ -604,11 +611,12 @@ int main (int argc, char **argv)
|
||||
FD_SET(daemon->helperfd, &wset);
|
||||
bump_maxfd(daemon->helperfd, &maxfd);
|
||||
}
|
||||
#else
|
||||
# else
|
||||
/* need this for other side-effects */
|
||||
while (do_script_run(now));
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* must do this just before select(), when we know no
|
||||
more calls to my_syslog() can occur */
|
||||
set_log_writer(&wset, &maxfd);
|
||||
@@ -662,12 +670,14 @@ int main (int argc, char **argv)
|
||||
check_tftp_listeners(&rset, now);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
if (daemon->dhcp && FD_ISSET(daemon->dhcpfd, &rset))
|
||||
dhcp_packet(now);
|
||||
|
||||
#ifndef NO_FORK
|
||||
# ifndef NO_FORK
|
||||
if (daemon->helperfd != -1 && FD_ISSET(daemon->helperfd, &wset))
|
||||
helper_write();
|
||||
# endif
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -737,6 +747,9 @@ static void fatal_event(struct event_desc *ev)
|
||||
{
|
||||
case EVENT_DIE:
|
||||
exit(0);
|
||||
|
||||
case EVENT_FORK_ERR:
|
||||
die(_("cannot fork into background: %s"), NULL, EC_MISC);
|
||||
|
||||
case EVENT_PIPE_ERR:
|
||||
die(_("failed to create helper: %s"), NULL, EC_MISC);
|
||||
@@ -777,7 +790,9 @@ static void async_event(int pipe, time_t now)
|
||||
reload_servers(daemon->resolv_files->name);
|
||||
check_servers();
|
||||
}
|
||||
#ifdef HAVE_DHCP
|
||||
rerun_scripts();
|
||||
#endif
|
||||
break;
|
||||
|
||||
case EVENT_DUMP:
|
||||
@@ -786,11 +801,13 @@ static void async_event(int pipe, time_t now)
|
||||
break;
|
||||
|
||||
case EVENT_ALARM:
|
||||
#ifdef HAVE_DHCP
|
||||
if (daemon->dhcp)
|
||||
{
|
||||
lease_prune(NULL, now);
|
||||
lease_update_file(now);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case EVENT_CHILD:
|
||||
@@ -840,7 +857,7 @@ static void async_event(int pipe, time_t now)
|
||||
if (daemon->tcp_pids[i] != 0)
|
||||
kill(daemon->tcp_pids[i], SIGALRM);
|
||||
|
||||
#ifndef NO_FORK
|
||||
#if defined(HAVE_DHCP) && !defined(NO_FORK)
|
||||
/* handle pending lease transitions */
|
||||
if (daemon->helperfd != -1)
|
||||
{
|
||||
@@ -904,7 +921,7 @@ static void poll_resolv()
|
||||
warned = 0;
|
||||
check_servers();
|
||||
if (daemon->options & OPT_RELOAD)
|
||||
cache_reload(daemon->addn_hosts);
|
||||
cache_reload();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -921,8 +938,9 @@ static void poll_resolv()
|
||||
void clear_cache_and_reload(time_t now)
|
||||
{
|
||||
if (daemon->port != 0)
|
||||
cache_reload(daemon->addn_hosts);
|
||||
cache_reload();
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
if (daemon->dhcp)
|
||||
{
|
||||
if (daemon->options & OPT_ETHERS)
|
||||
@@ -934,6 +952,7 @@ void clear_cache_and_reload(time_t now)
|
||||
lease_update_file(now);
|
||||
lease_update_dns();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
|
||||
@@ -1135,7 +1154,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
int make_icmp_sock(void)
|
||||
{
|
||||
int fd;
|
||||
@@ -1258,5 +1277,6 @@ int icmp_ping(struct in_addr addr)
|
||||
|
||||
return gotreply;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ extern int capget(cap_user_header_t header, cap_user_data_t data);
|
||||
#define LINUX_CAPABILITY_VERSION_3 0x20080522
|
||||
|
||||
#include <sys/prctl.h>
|
||||
#elif defined(HAVE_SOLARIS_PRIVS)
|
||||
#elif defined(HAVE_SOLARIS_NETWORK)
|
||||
#include <priv.h>
|
||||
#endif
|
||||
|
||||
@@ -135,6 +135,7 @@ struct event_desc {
|
||||
#define EVENT_GROUP_ERR 15
|
||||
#define EVENT_DIE 16
|
||||
#define EVENT_LOG_ERR 17
|
||||
#define EVENT_FORK_ERR 18
|
||||
|
||||
/* Exit codes. */
|
||||
#define EC_GOOD 0
|
||||
@@ -185,6 +186,11 @@ struct event_desc {
|
||||
#define OPT_NO_OVERRIDE (1u<<30)
|
||||
#define OPT_NO_REBIND (1u<<31)
|
||||
|
||||
/* 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. */
|
||||
#define MS_TFTP LOG_USER
|
||||
#define MS_DHCP LOG_DAEMON
|
||||
|
||||
struct all_addr {
|
||||
union {
|
||||
struct in_addr addr4;
|
||||
@@ -287,19 +293,7 @@ struct crec {
|
||||
union mysockaddr {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in in;
|
||||
#ifdef HAVE_BROKEN_SOCKADDR_IN6
|
||||
/* early versions of glibc don't include sin6_scope_id in sockaddr_in6
|
||||
but latest kernels _require_ it to be set. The choice is to have
|
||||
dnsmasq fail to compile on back-level libc or fail to run
|
||||
on latest kernels with IPv6. Or to do this: sorry that it's so gross. */
|
||||
struct my_sockaddr_in6 {
|
||||
sa_family_t sin6_family; /* AF_INET6 */
|
||||
uint16_t sin6_port; /* transport layer port # */
|
||||
uint32_t sin6_flowinfo; /* IPv6 traffic class & flow info */
|
||||
struct in6_addr sin6_addr; /* IPv6 address */
|
||||
uint32_t sin6_scope_id; /* set of interfaces for a scope */
|
||||
} in6;
|
||||
#elif defined(HAVE_IPV6)
|
||||
#if defined(HAVE_IPV6)
|
||||
struct sockaddr_in6 in6;
|
||||
#endif
|
||||
};
|
||||
@@ -368,8 +362,11 @@ struct resolvc {
|
||||
};
|
||||
|
||||
/* adn-hosts parms from command-line */
|
||||
#define AH_DIR 1
|
||||
#define AH_INACTIVE 2
|
||||
struct hostsfile {
|
||||
struct hostsfile *next;
|
||||
int flags;
|
||||
char *fname;
|
||||
int index; /* matches to cache entries for logging */
|
||||
};
|
||||
@@ -484,6 +481,7 @@ struct dhcp_opt {
|
||||
#define DHOPT_MATCH 128
|
||||
#define DHOPT_VENDOR 256
|
||||
#define DHOPT_HEX 512
|
||||
#define DHOPT_VENDOR_MATCH 1024
|
||||
|
||||
struct dhcp_boot {
|
||||
char *file, *sname;
|
||||
@@ -492,6 +490,14 @@ struct dhcp_boot {
|
||||
struct dhcp_boot *next;
|
||||
};
|
||||
|
||||
struct pxe_service {
|
||||
unsigned short CSA, type;
|
||||
char *menu, *basename;
|
||||
struct in_addr server;
|
||||
struct dhcp_netid *netid;
|
||||
struct pxe_service *next;
|
||||
};
|
||||
|
||||
#define MATCH_VENDOR 1
|
||||
#define MATCH_USER 2
|
||||
#define MATCH_CIRCUIT 3
|
||||
@@ -514,12 +520,10 @@ struct dhcp_mac {
|
||||
struct dhcp_mac *next;
|
||||
};
|
||||
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
struct dhcp_bridge {
|
||||
char iface[IF_NAMESIZE];
|
||||
struct dhcp_bridge *alias, *next;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct cond_domain {
|
||||
char *domain;
|
||||
@@ -540,6 +544,7 @@ struct dhcp_context {
|
||||
#define CONTEXT_STATIC 1
|
||||
#define CONTEXT_NETMASK 2
|
||||
#define CONTEXT_BRDCAST 4
|
||||
#define CONTEXT_PROXY 8
|
||||
|
||||
|
||||
typedef unsigned char u8;
|
||||
@@ -620,6 +625,7 @@ extern struct daemon {
|
||||
struct dhcp_vendor *dhcp_vendors;
|
||||
struct dhcp_mac *dhcp_macs;
|
||||
struct dhcp_boot *boot_config;
|
||||
struct pxe_service *pxe_services;
|
||||
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *force_broadcast, *bootp_dynamic;
|
||||
char *dhcp_hosts_file, *dhcp_opts_file;
|
||||
int dhcp_max, tftp_max;
|
||||
@@ -643,23 +649,21 @@ extern struct daemon {
|
||||
struct server *srv_save; /* Used for resend on DoD */
|
||||
size_t packet_len; /* " " */
|
||||
struct randfd *rfd_save; /* " " */
|
||||
pid_t tcp_pids[MAX_PROCS];
|
||||
pid_t tcp_pids[MAX_PROCS];
|
||||
struct randfd randomsocks[RANDOM_SOCKS];
|
||||
|
||||
/* DHCP state */
|
||||
int dhcpfd, helperfd;
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
#if defined(HAVE_LINUX_NETWORK)
|
||||
int netlinkfd;
|
||||
#else
|
||||
#elif defined(HAVE_BSD_NETWORK)
|
||||
int dhcp_raw_fd, dhcp_icmp_fd;
|
||||
#endif
|
||||
struct iovec dhcp_packet;
|
||||
char *dhcp_buff, *dhcp_buff2;
|
||||
struct ping_result *ping_results;
|
||||
FILE *lease_stream;
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
struct dhcp_bridge *bridges;
|
||||
#endif
|
||||
|
||||
/* DBus stuff */
|
||||
/* void * here to avoid depending on dbus headers outside dbus.c */
|
||||
@@ -676,7 +680,7 @@ pid_t tcp_pids[MAX_PROCS];
|
||||
/* cache.c */
|
||||
void cache_init(void);
|
||||
void log_query(unsigned short flags, char *name, struct all_addr *addr, char *arg);
|
||||
char *record_source(struct hostsfile *addn_hosts, int index);
|
||||
char *record_source(int index);
|
||||
void querystr(char *str, unsigned short type);
|
||||
struct crec *cache_find_by_addr(struct crec *crecp,
|
||||
struct all_addr *addr, time_t now,
|
||||
@@ -687,11 +691,12 @@ void cache_end_insert(void);
|
||||
void cache_start_insert(void);
|
||||
struct crec *cache_insert(char *name, struct all_addr *addr,
|
||||
time_t now, unsigned long ttl, unsigned short flags);
|
||||
void cache_reload(struct hostsfile *addn_hosts);
|
||||
void cache_reload(void);
|
||||
void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t ttd);
|
||||
void cache_unhash_dhcp(void);
|
||||
void dump_cache(time_t now);
|
||||
char *cache_get_name(struct crec *crecp);
|
||||
char *get_domain(struct in_addr addr);
|
||||
|
||||
/* rfc1035.c */
|
||||
unsigned short extract_request(HEADER *header, size_t qlen,
|
||||
@@ -748,7 +753,7 @@ void flush_log(void);
|
||||
|
||||
/* option.c */
|
||||
void read_opts (int argc, char **argv, char *compile_opts);
|
||||
char *option_string(unsigned char opt);
|
||||
char *option_string(unsigned char opt, int *is_ip, int *is_name);
|
||||
void reread_dhcp(void);
|
||||
|
||||
/* forward.c */
|
||||
@@ -760,6 +765,7 @@ void server_gone(struct server *server);
|
||||
struct frec *get_new_frec(time_t now, int *wait);
|
||||
|
||||
/* network.c */
|
||||
int indextoname(int fd, int index, char *name);
|
||||
int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp);
|
||||
int random_sock(int family);
|
||||
void pre_allocate_sfds(void);
|
||||
@@ -768,15 +774,14 @@ void check_servers(void);
|
||||
int enumerate_interfaces();
|
||||
struct listener *create_wildcard_listeners(void);
|
||||
struct listener *create_bound_listeners(void);
|
||||
int iface_check(int family, struct all_addr *addr,
|
||||
struct ifreq *ifr, int *indexp);
|
||||
int iface_check(int family, struct all_addr *addr, char *name, int *indexp);
|
||||
int fix_fd(int fd);
|
||||
struct in_addr get_ifaddr(char *intr);
|
||||
|
||||
/* dhcp.c */
|
||||
#ifdef HAVE_DHCP
|
||||
void dhcp_init(void);
|
||||
void dhcp_packet(time_t now);
|
||||
char *get_domain(struct in_addr addr);
|
||||
struct dhcp_context *address_available(struct dhcp_context *context,
|
||||
struct in_addr addr,
|
||||
struct dhcp_netid *netids);
|
||||
@@ -799,8 +804,10 @@ struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct i
|
||||
char *strip_hostname(char *hostname);
|
||||
char *host_from_dns(struct in_addr addr);
|
||||
char *get_domain(struct in_addr addr);
|
||||
#endif
|
||||
|
||||
/* lease.c */
|
||||
#ifdef HAVE_DHCP
|
||||
void lease_update_file(time_t now);
|
||||
void lease_update_dns();
|
||||
void lease_init(time_t now);
|
||||
@@ -817,16 +824,21 @@ void lease_prune(struct dhcp_lease *target, time_t now);
|
||||
void lease_update_from_configs(void);
|
||||
int do_script_run(time_t now);
|
||||
void rerun_scripts(void);
|
||||
#endif
|
||||
|
||||
/* 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);
|
||||
unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
|
||||
int clid_len, unsigned char *clid, int *len_out);
|
||||
#endif
|
||||
|
||||
/* dnsmasq.c */
|
||||
#ifdef HAVE_DHCP
|
||||
int make_icmp_sock(void);
|
||||
int icmp_ping(struct in_addr addr);
|
||||
#endif
|
||||
void send_event(int fd, int event, int data);
|
||||
void clear_cache_and_reload(time_t now);
|
||||
|
||||
@@ -855,7 +867,7 @@ void emit_dbus_signal(int action, char *mac, char *hostname, char *addr);
|
||||
#endif
|
||||
|
||||
/* helper.c */
|
||||
#ifndef NO_FORK
|
||||
#if defined(HAVE_DHCP) && !defined(NO_FORK)
|
||||
int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd);
|
||||
void helper_write(void);
|
||||
void queue_script(int action, struct dhcp_lease *lease,
|
||||
|
||||
@@ -667,19 +667,8 @@ void receive_query(struct listener *listen, time_t now)
|
||||
|
||||
/* enforce available interface configuration */
|
||||
|
||||
if (if_index == 0)
|
||||
return;
|
||||
|
||||
#ifdef SIOCGIFNAME
|
||||
ifr.ifr_ifindex = if_index;
|
||||
if (ioctl(listen->fd, SIOCGIFNAME, &ifr) == -1)
|
||||
return;
|
||||
#else
|
||||
if (!if_indextoname(if_index, ifr.ifr_name))
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (!iface_check(listen->family, &dst_addr, &ifr, &if_index))
|
||||
if (!indextoname(listen->fd, if_index, ifr.ifr_name) ||
|
||||
!iface_check(listen->family, &dst_addr, ifr.ifr_name, &if_index))
|
||||
return;
|
||||
|
||||
if (listen->family == AF_INET &&
|
||||
|
||||
26
src/helper.c
26
src/helper.c
@@ -28,7 +28,7 @@
|
||||
main process.
|
||||
*/
|
||||
|
||||
#ifndef NO_FORK
|
||||
#if defined(HAVE_DHCP) && !defined(NO_FORK)
|
||||
|
||||
static void my_setenv(const char *name, const char *value, int *error);
|
||||
|
||||
@@ -276,28 +276,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
|
||||
static void my_setenv(const char *name, const char *value, int *error)
|
||||
{
|
||||
if (*error == 0)
|
||||
{
|
||||
#if defined(HAVE_SOLARIS_NETWORK) && !defined(HAVE_SOLARIS_PRIVS)
|
||||
/* old Solaris is missing setenv..... */
|
||||
char *p;
|
||||
|
||||
if (!(p = malloc(strlen(name) + strlen(value) + 2)))
|
||||
*error = ENOMEM;
|
||||
else
|
||||
{
|
||||
strcpy(p, name);
|
||||
strcat(p, "=");
|
||||
strcat(p, value);
|
||||
|
||||
if (putenv(p) != 0)
|
||||
*error = errno;
|
||||
}
|
||||
#else
|
||||
if (setenv(name, value, 1) != 0)
|
||||
*error = errno;
|
||||
#endif
|
||||
}
|
||||
if (*error == 0 && setenv(name, value, 1) != 0)
|
||||
*error = errno;
|
||||
}
|
||||
|
||||
/* pack up lease data into a buffer */
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
|
||||
static struct dhcp_lease *leases = NULL, *old_leases = NULL;
|
||||
static int dns_dirty, file_dirty, leases_left;
|
||||
|
||||
@@ -57,7 +59,7 @@ void lease_init(time_t now)
|
||||
if (!leasestream)
|
||||
die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE);
|
||||
|
||||
/* a+ mode lease pointer at end. */
|
||||
/* a+ mode leaves pointer at end. */
|
||||
rewind(leasestream);
|
||||
}
|
||||
|
||||
@@ -235,7 +237,7 @@ void lease_update_file(time_t now)
|
||||
if (next_event == 0 || difftime(next_event, LEASE_RETRY + now) > 0.0)
|
||||
next_event = LEASE_RETRY + now;
|
||||
|
||||
my_syslog(LOG_ERR, _("failed to write %s: %s (retry in %us)"),
|
||||
my_syslog(MS_DHCP | LOG_ERR, _("failed to write %s: %s (retry in %us)"),
|
||||
daemon->lease_file, strerror(err),
|
||||
(unsigned int)difftime(next_event, now));
|
||||
}
|
||||
@@ -607,6 +609,8 @@ int do_script_run(time_t now)
|
||||
|
||||
return 0; /* nothing to do */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
19
src/log.c
19
src/log.c
@@ -248,6 +248,10 @@ static void log_write(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* priority is one of LOG_DEBUG, LOG_INFO, LOG_NOTICE, etc. See sys/syslog.h.
|
||||
OR'd to priority can be MS_TFTP, MS_DHCP, ... to be able to do log separation between
|
||||
DNS, DHCP and TFTP services.
|
||||
*/
|
||||
void my_syslog(int priority, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
@@ -256,10 +260,18 @@ void my_syslog(int priority, const char *format, ...)
|
||||
char *p;
|
||||
size_t len;
|
||||
pid_t pid = getpid();
|
||||
char *func = "";
|
||||
|
||||
if ((LOG_FACMASK & priority) == MS_TFTP)
|
||||
func = "-tftp";
|
||||
else if ((LOG_FACMASK & priority) == MS_DHCP)
|
||||
func = "-dhcp";
|
||||
|
||||
priority = LOG_PRI(priority);
|
||||
|
||||
if (log_stderr)
|
||||
{
|
||||
fprintf(stderr, "dnsmasq: ");
|
||||
fprintf(stderr, "dnsmasq%s: ", func);
|
||||
va_start(ap, format);
|
||||
vfprintf(stderr, format, ap);
|
||||
va_end(ap);
|
||||
@@ -305,8 +317,9 @@ void my_syslog(int priority, const char *format, ...)
|
||||
p = entry->payload;
|
||||
if (!log_to_file)
|
||||
p += sprintf(p, "<%d>", priority | log_fac);
|
||||
|
||||
p += sprintf(p, "%.15s dnsmasq[%d]: ", ctime(&time_now) + 4, (int)pid);
|
||||
|
||||
p += sprintf(p, "%.15s dnsmasq%s[%d]: ", ctime(&time_now) + 4, func, (int)pid);
|
||||
|
||||
len = p - entry->payload;
|
||||
va_start(ap, format);
|
||||
len += vsnprintf(p, MAX_MESSAGE - len, format, ap) + 1; /* include zero-terminator */
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#endif
|
||||
|
||||
static struct iovec iov;
|
||||
static u32 netlink_pid;
|
||||
|
||||
static void nl_err(struct nlmsghdr *h);
|
||||
static void nl_routechange(struct nlmsghdr *h);
|
||||
@@ -38,6 +39,7 @@ static void nl_routechange(struct nlmsghdr *h);
|
||||
void netlink_init(void)
|
||||
{
|
||||
struct sockaddr_nl addr;
|
||||
socklen_t slen = sizeof(addr);
|
||||
|
||||
addr.nl_family = AF_NETLINK;
|
||||
addr.nl_pad = 0;
|
||||
@@ -59,48 +61,63 @@ void netlink_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (daemon->netlinkfd == -1)
|
||||
if (daemon->netlinkfd == -1 ||
|
||||
getsockname(daemon->netlinkfd, (struct sockaddr *)&addr, &slen) == 1)
|
||||
die(_("cannot create netlink socket: %s"), NULL, EC_MISC);
|
||||
|
||||
/* save pid assigned by bind() and retrieved by getsockname() */
|
||||
netlink_pid = addr.nl_pid;
|
||||
|
||||
iov.iov_len = 200;
|
||||
iov.iov_len = 100;
|
||||
iov.iov_base = safe_malloc(iov.iov_len);
|
||||
}
|
||||
|
||||
static ssize_t netlink_recv(void)
|
||||
{
|
||||
struct msghdr msg;
|
||||
struct sockaddr_nl nladdr;
|
||||
ssize_t rc;
|
||||
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_name = &nladdr;
|
||||
msg.msg_namelen = sizeof(nladdr);
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_flags = 0;
|
||||
while ((rc = recvmsg(daemon->netlinkfd, &msg, MSG_PEEK)) == -1 && errno == EINTR);
|
||||
|
||||
/* 2.2.x doesn't suport MSG_PEEK at all, returning EOPNOTSUPP, so we just grab a
|
||||
big buffer and pray in that case. */
|
||||
if (rc == -1 && errno == EOPNOTSUPP)
|
||||
while ((rc = recvmsg(daemon->netlinkfd, &msg, MSG_PEEK | MSG_TRUNC)) == -1 && errno == EINTR);
|
||||
|
||||
/* make buffer big enough */
|
||||
if (rc != -1 && (msg.msg_flags & MSG_TRUNC))
|
||||
{
|
||||
if (!expand_buf(&iov, 2000))
|
||||
return -1;
|
||||
break;
|
||||
/* Very new Linux kernels return the actual size needed, older ones always return truncated size */
|
||||
if ((size_t)rc == iov.iov_len)
|
||||
{
|
||||
if (expand_buf(&iov, rc + 100))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
expand_buf(&iov, rc);
|
||||
}
|
||||
|
||||
if (rc == -1 || !(msg.msg_flags & MSG_TRUNC))
|
||||
break;
|
||||
|
||||
if (!expand_buf(&iov, iov.iov_len + 100))
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* finally, read it for real */
|
||||
while ((rc = recvmsg(daemon->netlinkfd, &msg, 0)) == -1 && errno == EINTR);
|
||||
/* read it for real */
|
||||
msg.msg_flags = 0;
|
||||
while ((rc = recvmsg(daemon->netlinkfd, &msg, 0)) == -1 && errno == EINTR);
|
||||
|
||||
/* Make sure this is from the kernel */
|
||||
if (rc == -1 || nladdr.nl_pid == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* discard stuff which is truncated at this point (expand_buf() may fail) */
|
||||
if (msg.msg_flags & MSG_TRUNC)
|
||||
{
|
||||
rc = -1;
|
||||
errno = ENOMEM;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -141,13 +158,20 @@ int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)())
|
||||
while (1)
|
||||
{
|
||||
if ((len = netlink_recv()) == -1)
|
||||
return 0;
|
||||
|
||||
{
|
||||
if (errno == ENOBUFS)
|
||||
{
|
||||
sleep(1);
|
||||
goto again;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
|
||||
if (h->nlmsg_type == NLMSG_ERROR)
|
||||
nl_err(h);
|
||||
else if (h->nlmsg_seq != seq)
|
||||
if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid)
|
||||
nl_routechange(h); /* May be multicast arriving async */
|
||||
else if (h->nlmsg_type == NLMSG_ERROR)
|
||||
nl_err(h);
|
||||
else if (h->nlmsg_type == NLMSG_DONE)
|
||||
{
|
||||
#ifdef HAVE_IPV6
|
||||
@@ -208,10 +232,17 @@ int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void netlink_multicast(void)
|
||||
{
|
||||
ssize_t len;
|
||||
struct nlmsghdr *h;
|
||||
int flags;
|
||||
|
||||
/* don't risk blocking reading netlink messages here. */
|
||||
if ((flags = fcntl(daemon->netlinkfd, F_GETFL)) == -1 ||
|
||||
fcntl(daemon->netlinkfd, F_SETFL, flags | O_NONBLOCK) == -1)
|
||||
return;
|
||||
|
||||
if ((len = netlink_recv()) != -1)
|
||||
{
|
||||
@@ -221,11 +252,15 @@ void netlink_multicast(void)
|
||||
else
|
||||
nl_routechange(h);
|
||||
}
|
||||
|
||||
/* restore non-blocking status */
|
||||
fcntl(daemon->netlinkfd, F_SETFL, flags);
|
||||
}
|
||||
|
||||
static void nl_err(struct nlmsghdr *h)
|
||||
{
|
||||
struct nlmsgerr *err = NLMSG_DATA(h);
|
||||
|
||||
if (err->error != 0)
|
||||
my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error)));
|
||||
}
|
||||
@@ -234,10 +269,10 @@ static void nl_err(struct nlmsghdr *h)
|
||||
If this happens and we still have a DNS packet in the buffer, we re-send it.
|
||||
This helps on DoD links, where frequently the packet which triggers dialling is
|
||||
a DNS query, which then gets lost. By re-sending, we can avoid the lookup
|
||||
failing. */
|
||||
failing. Note that we only accept these messages from the kernel (pid == 0) */
|
||||
static void nl_routechange(struct nlmsghdr *h)
|
||||
{
|
||||
if (h->nlmsg_type == RTM_NEWROUTE)
|
||||
if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE)
|
||||
{
|
||||
struct rtmsg *rtm = NLMSG_DATA(h);
|
||||
int fd;
|
||||
|
||||
@@ -16,8 +16,37 @@
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
int iface_check(int family, struct all_addr *addr,
|
||||
struct ifreq *ifr, int *indexp)
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
|
||||
int indextoname(int fd, int index, char *name)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
||||
if (index == 0)
|
||||
return 0;
|
||||
|
||||
ifr.ifr_ifindex = index;
|
||||
if (ioctl(fd, SIOCGIFNAME, &ifr) == -1)
|
||||
return 0;
|
||||
|
||||
strncpy(name, ifr.ifr_name, IF_NAMESIZE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int indextoname(int fd, int index, char *name)
|
||||
{
|
||||
if (index == 0 || !if_indextoname(index, name))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int iface_check(int family, struct all_addr *addr, char *name, int *indexp)
|
||||
{
|
||||
struct iname *tmp;
|
||||
int ret = 1;
|
||||
@@ -27,7 +56,6 @@ int iface_check(int family, struct all_addr *addr,
|
||||
|
||||
if (indexp)
|
||||
{
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
/* One form of bridging on BSD has the property that packets
|
||||
can be recieved on bridge interfaces which do not have an IP address.
|
||||
We allow these to be treated as aliases of another interface which does have
|
||||
@@ -36,26 +64,25 @@ int iface_check(int family, struct all_addr *addr,
|
||||
for (bridge = daemon->bridges; bridge; bridge = bridge->next)
|
||||
{
|
||||
for (alias = bridge->alias; alias; alias = alias->next)
|
||||
if (strncmp(ifr->ifr_name, alias->iface, IF_NAMESIZE) == 0)
|
||||
if (strncmp(name, alias->iface, IF_NAMESIZE) == 0)
|
||||
{
|
||||
int newindex;
|
||||
|
||||
if (!(newindex = if_nametoindex(bridge->iface)))
|
||||
{
|
||||
my_syslog(LOG_WARNING, _("unknown interface %s in bridge-interface"), ifr->ifr_name);
|
||||
my_syslog(LOG_WARNING, _("unknown interface %s in bridge-interface"), name);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*indexp = newindex;
|
||||
strncpy(ifr->ifr_name, bridge->iface, IF_NAMESIZE);
|
||||
strncpy(name, bridge->iface, IF_NAMESIZE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (alias)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (daemon->if_names || (addr && daemon->if_addrs))
|
||||
@@ -63,7 +90,7 @@ int iface_check(int family, struct all_addr *addr,
|
||||
ret = 0;
|
||||
|
||||
for (tmp = daemon->if_names; tmp; tmp = tmp->next)
|
||||
if (tmp->name && (strcmp(tmp->name, ifr->ifr_name) == 0))
|
||||
if (tmp->name && (strcmp(tmp->name, name) == 0))
|
||||
ret = tmp->used = 1;
|
||||
|
||||
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
|
||||
@@ -82,7 +109,7 @@ int iface_check(int family, struct all_addr *addr,
|
||||
}
|
||||
|
||||
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && (strcmp(tmp->name, ifr->ifr_name) == 0))
|
||||
if (tmp->name && (strcmp(tmp->name, name) == 0))
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
@@ -103,16 +130,8 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
||||
if (sockaddr_isequal(&iface->addr, addr))
|
||||
return 1;
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
ifr.ifr_ifindex = if_index;
|
||||
#endif
|
||||
|
||||
if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1 ||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
ioctl(fd, SIOCGIFNAME, &ifr) == -1 ||
|
||||
#else
|
||||
!if_indextoname(if_index, ifr.ifr_name) ||
|
||||
#endif
|
||||
!indextoname(fd, if_index, ifr.ifr_name) ||
|
||||
ioctl(fd, SIOCGIFFLAGS, &ifr) == -1)
|
||||
{
|
||||
if (fd != -1)
|
||||
@@ -150,7 +169,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
||||
}
|
||||
|
||||
if (addr->sa.sa_family == AF_INET &&
|
||||
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, &ifr, NULL))
|
||||
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name, NULL))
|
||||
return 1;
|
||||
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
@@ -159,7 +178,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
if (addr->sa.sa_family == AF_INET6 &&
|
||||
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, &ifr, NULL))
|
||||
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name, NULL))
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
@@ -217,7 +236,6 @@ static int iface_allowed_v4(struct in_addr local, int if_index,
|
||||
return iface_allowed((struct irec **)vparam, if_index, &addr, netmask);
|
||||
}
|
||||
|
||||
|
||||
int enumerate_interfaces(void)
|
||||
{
|
||||
#ifdef HAVE_IPV6
|
||||
@@ -529,7 +547,7 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
|
||||
|
||||
#if defined(SO_BINDTODEVICE)
|
||||
if (intname[0] != 0 &&
|
||||
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, sizeof(intname)) == -1)
|
||||
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, strlen(intname)) == -1)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
|
||||
456
src/option.c
456
src/option.c
@@ -19,6 +19,10 @@
|
||||
#include "dnsmasq.h"
|
||||
#include <setjmp.h>
|
||||
|
||||
static volatile int mem_recover = 0;
|
||||
static jmp_buf mem_jmp;
|
||||
static void one_file(char *file, int nest, int hard_opt);
|
||||
|
||||
/* Solaris headers don't have facility names. */
|
||||
#ifdef HAVE_SOLARIS_NETWORK
|
||||
static const struct {
|
||||
@@ -34,10 +38,7 @@ static const struct {
|
||||
{ "lpr", LOG_LPR },
|
||||
{ "news", LOG_NEWS },
|
||||
{ "uucp", LOG_UUCP },
|
||||
#ifdef LOG_AUDIT
|
||||
/* Not Solaris < 10 */
|
||||
{ "audit", LOG_AUDIT },
|
||||
#endif
|
||||
{ "cron", LOG_CRON },
|
||||
{ "local0", LOG_LOCAL0 },
|
||||
{ "local1", LOG_LOCAL1 },
|
||||
@@ -98,6 +99,9 @@ struct myoption {
|
||||
#define LOPT_MINPORT 288
|
||||
#define LOPT_DHCP_FQDN 289
|
||||
#define LOPT_CNAME 290
|
||||
#define LOPT_PXE_PROMT 291
|
||||
#define LOPT_PXE_SERV 292
|
||||
#define LOPT_TEST 293
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
static const struct option opts[] =
|
||||
@@ -105,105 +109,106 @@ static const struct option opts[] =
|
||||
static const struct myoption opts[] =
|
||||
#endif
|
||||
{
|
||||
{"version", 0, 0, 'v'},
|
||||
{"no-hosts", 0, 0, 'h'},
|
||||
{"no-poll", 0, 0, 'n'},
|
||||
{"help", 0, 0, 'w'},
|
||||
{"no-daemon", 0, 0, 'd'},
|
||||
{"log-queries", 0, 0, 'q'},
|
||||
{"user", 2, 0, 'u'},
|
||||
{"group", 2, 0, 'g'},
|
||||
{"resolv-file", 2, 0, 'r'},
|
||||
{"mx-host", 1, 0, 'm'},
|
||||
{"mx-target", 1, 0, 't'},
|
||||
{"cache-size", 2, 0, 'c'},
|
||||
{"port", 1, 0, 'p'},
|
||||
{"dhcp-leasefile", 2, 0, 'l'},
|
||||
{"dhcp-lease", 1, 0, 'l' },
|
||||
{"dhcp-host", 1, 0, 'G'},
|
||||
{"dhcp-range", 1, 0, 'F'},
|
||||
{"dhcp-option", 1, 0, 'O'},
|
||||
{"dhcp-boot", 1, 0, 'M'},
|
||||
{"domain", 1, 0, 's'},
|
||||
{"domain-suffix", 1, 0, 's'},
|
||||
{"interface", 1, 0, 'i'},
|
||||
{"listen-address", 1, 0, 'a'},
|
||||
{"bogus-priv", 0, 0, 'b'},
|
||||
{"bogus-nxdomain", 1, 0, 'B'},
|
||||
{"selfmx", 0, 0, 'e'},
|
||||
{"filterwin2k", 0, 0, 'f'},
|
||||
{"pid-file", 2, 0, 'x'},
|
||||
{"strict-order", 0, 0, 'o'},
|
||||
{"server", 1, 0, 'S'},
|
||||
{"local", 1, 0, LOPT_LOCAL },
|
||||
{"address", 1, 0, 'A' },
|
||||
{"conf-file", 2, 0, 'C'},
|
||||
{"no-resolv", 0, 0, 'R'},
|
||||
{"expand-hosts", 0, 0, 'E'},
|
||||
{"localmx", 0, 0, 'L'},
|
||||
{"local-ttl", 1, 0, 'T'},
|
||||
{"no-negcache", 0, 0, 'N'},
|
||||
{"addn-hosts", 1, 0, 'H'},
|
||||
{"query-port", 1, 0, 'Q'},
|
||||
{"except-interface", 1, 0, 'I'},
|
||||
{"no-dhcp-interface", 1, 0, '2'},
|
||||
{"domain-needed", 0, 0, 'D'},
|
||||
{"dhcp-lease-max", 1, 0, 'X' },
|
||||
{"bind-interfaces", 0, 0, 'z'},
|
||||
{"read-ethers", 0, 0, 'Z' },
|
||||
{"alias", 1, 0, 'V' },
|
||||
{"dhcp-vendorclass", 1, 0, 'U'},
|
||||
{"dhcp-userclass", 1, 0, 'j'},
|
||||
{"dhcp-ignore", 1, 0, 'J'},
|
||||
{"edns-packet-max", 1, 0, 'P'},
|
||||
{"keep-in-foreground", 0, 0, 'k'},
|
||||
{"dhcp-authoritative", 0, 0, 'K'},
|
||||
{"srv-host", 1, 0, 'W'},
|
||||
{"localise-queries", 0, 0, 'y'},
|
||||
{"txt-record", 1, 0, 'Y'},
|
||||
{"enable-dbus", 0, 0, '1'},
|
||||
{"bootp-dynamic", 2, 0, '3'},
|
||||
{"dhcp-mac", 1, 0, '4'},
|
||||
{"no-ping", 0, 0, '5'},
|
||||
{"dhcp-script", 1, 0, '6'},
|
||||
{"conf-dir", 1, 0, '7'},
|
||||
{"log-facility", 1, 0 ,'8'},
|
||||
{"leasefile-ro", 0, 0, '9'},
|
||||
{"dns-forward-max", 1, 0, '0'},
|
||||
{"clear-on-reload", 0, 0, LOPT_RELOAD },
|
||||
{"dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
|
||||
{"enable-tftp", 0, 0, LOPT_TFTP },
|
||||
{"tftp-secure", 0, 0, LOPT_SECURE },
|
||||
{"tftp-unique-root", 0, 0, LOPT_APREF },
|
||||
{"tftp-root", 1, 0, LOPT_PREFIX },
|
||||
{"tftp-max", 1, 0, LOPT_TFTP_MAX },
|
||||
{"ptr-record", 1, 0, LOPT_PTR },
|
||||
{"naptr-record", 1, 0, LOPT_NAPTR },
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
{"bridge-interface", 1, 0 , LOPT_BRIDGE },
|
||||
#endif
|
||||
{"dhcp-option-force", 1, 0, LOPT_FORCE },
|
||||
{"tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
|
||||
{"log-dhcp", 0, 0, LOPT_LOG_OPTS },
|
||||
{"log-async", 2, 0, LOPT_MAX_LOGS },
|
||||
{"dhcp-circuitid", 1, 0, LOPT_CIRCUIT },
|
||||
{"dhcp-remoteid", 1, 0, LOPT_REMOTE },
|
||||
{"dhcp-subscrid", 1, 0, LOPT_SUBSCR },
|
||||
{"interface-name", 1, 0, LOPT_INTNAME },
|
||||
{"dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
|
||||
{"dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
|
||||
{"dhcp-no-override", 0, 0, LOPT_OVERRIDE },
|
||||
{"tftp-port-range", 1, 0, LOPT_TFTPPORTS },
|
||||
{"stop-dns-rebind", 0, 0, LOPT_REBIND },
|
||||
{"all-servers", 0, 0, LOPT_NOLAST},
|
||||
{"dhcp-match", 1, 0, LOPT_MATCH },
|
||||
{"dhcp-broadcast", 1, 0, LOPT_BROADCAST },
|
||||
{"neg-ttl", 1, 0, LOPT_NEGTTL },
|
||||
{"dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
|
||||
{"dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
|
||||
{"min-port", 1, 0, LOPT_MINPORT },
|
||||
{"dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
|
||||
{"cname", 1, 0, LOPT_CNAME },
|
||||
{ "version", 0, 0, 'v' },
|
||||
{ "no-hosts", 0, 0, 'h' },
|
||||
{ "no-poll", 0, 0, 'n' },
|
||||
{ "help", 0, 0, 'w' },
|
||||
{ "no-daemon", 0, 0, 'd' },
|
||||
{ "log-queries", 0, 0, 'q' },
|
||||
{ "user", 2, 0, 'u' },
|
||||
{ "group", 2, 0, 'g' },
|
||||
{ "resolv-file", 2, 0, 'r' },
|
||||
{ "mx-host", 1, 0, 'm' },
|
||||
{ "mx-target", 1, 0, 't' },
|
||||
{ "cache-size", 2, 0, 'c' },
|
||||
{ "port", 1, 0, 'p' },
|
||||
{ "dhcp-leasefile", 2, 0, 'l' },
|
||||
{ "dhcp-lease", 1, 0, 'l' },
|
||||
{ "dhcp-host", 1, 0, 'G' },
|
||||
{ "dhcp-range", 1, 0, 'F' },
|
||||
{ "dhcp-option", 1, 0, 'O' },
|
||||
{ "dhcp-boot", 1, 0, 'M' },
|
||||
{ "domain", 1, 0, 's' },
|
||||
{ "domain-suffix", 1, 0, 's' },
|
||||
{ "interface", 1, 0, 'i' },
|
||||
{ "listen-address", 1, 0, 'a' },
|
||||
{ "bogus-priv", 0, 0, 'b' },
|
||||
{ "bogus-nxdomain", 1, 0, 'B' },
|
||||
{ "selfmx", 0, 0, 'e' },
|
||||
{ "filterwin2k", 0, 0, 'f' },
|
||||
{ "pid-file", 2, 0, 'x' },
|
||||
{ "strict-order", 0, 0, 'o' },
|
||||
{ "server", 1, 0, 'S' },
|
||||
{ "local", 1, 0, LOPT_LOCAL },
|
||||
{ "address", 1, 0, 'A' },
|
||||
{ "conf-file", 2, 0, 'C' },
|
||||
{ "no-resolv", 0, 0, 'R' },
|
||||
{ "expand-hosts", 0, 0, 'E' },
|
||||
{ "localmx", 0, 0, 'L' },
|
||||
{ "local-ttl", 1, 0, 'T' },
|
||||
{ "no-negcache", 0, 0, 'N' },
|
||||
{ "addn-hosts", 1, 0, 'H' },
|
||||
{ "query-port", 1, 0, 'Q' },
|
||||
{ "except-interface", 1, 0, 'I' },
|
||||
{ "no-dhcp-interface", 1, 0, '2' },
|
||||
{ "domain-needed", 0, 0, 'D' },
|
||||
{ "dhcp-lease-max", 1, 0, 'X' },
|
||||
{ "bind-interfaces", 0, 0, 'z' },
|
||||
{ "read-ethers", 0, 0, 'Z' },
|
||||
{ "alias", 1, 0, 'V' },
|
||||
{ "dhcp-vendorclass", 1, 0, 'U' },
|
||||
{ "dhcp-userclass", 1, 0, 'j' },
|
||||
{ "dhcp-ignore", 1, 0, 'J' },
|
||||
{ "edns-packet-max", 1, 0, 'P' },
|
||||
{ "keep-in-foreground", 0, 0, 'k' },
|
||||
{ "dhcp-authoritative", 0, 0, 'K' },
|
||||
{ "srv-host", 1, 0, 'W' },
|
||||
{ "localise-queries", 0, 0, 'y' },
|
||||
{ "txt-record", 1, 0, 'Y' },
|
||||
{ "enable-dbus", 0, 0, '1' },
|
||||
{ "bootp-dynamic", 2, 0, '3' },
|
||||
{ "dhcp-mac", 1, 0, '4' },
|
||||
{ "no-ping", 0, 0, '5' },
|
||||
{ "dhcp-script", 1, 0, '6' },
|
||||
{ "conf-dir", 1, 0, '7' },
|
||||
{ "log-facility", 1, 0 ,'8' },
|
||||
{ "leasefile-ro", 0, 0, '9' },
|
||||
{ "dns-forward-max", 1, 0, '0' },
|
||||
{ "clear-on-reload", 0, 0, LOPT_RELOAD },
|
||||
{ "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
|
||||
{ "enable-tftp", 0, 0, LOPT_TFTP },
|
||||
{ "tftp-secure", 0, 0, LOPT_SECURE },
|
||||
{ "tftp-unique-root", 0, 0, LOPT_APREF },
|
||||
{ "tftp-root", 1, 0, LOPT_PREFIX },
|
||||
{ "tftp-max", 1, 0, LOPT_TFTP_MAX },
|
||||
{ "ptr-record", 1, 0, LOPT_PTR },
|
||||
{ "naptr-record", 1, 0, LOPT_NAPTR },
|
||||
{ "bridge-interface", 1, 0 , LOPT_BRIDGE },
|
||||
{ "dhcp-option-force", 1, 0, LOPT_FORCE },
|
||||
{ "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
|
||||
{ "log-dhcp", 0, 0, LOPT_LOG_OPTS },
|
||||
{ "log-async", 2, 0, LOPT_MAX_LOGS },
|
||||
{ "dhcp-circuitid", 1, 0, LOPT_CIRCUIT },
|
||||
{ "dhcp-remoteid", 1, 0, LOPT_REMOTE },
|
||||
{ "dhcp-subscrid", 1, 0, LOPT_SUBSCR },
|
||||
{ "interface-name", 1, 0, LOPT_INTNAME },
|
||||
{ "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
|
||||
{ "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
|
||||
{ "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
|
||||
{ "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
|
||||
{ "stop-dns-rebind", 0, 0, LOPT_REBIND },
|
||||
{ "all-servers", 0, 0, LOPT_NOLAST },
|
||||
{ "dhcp-match", 1, 0, LOPT_MATCH },
|
||||
{ "dhcp-broadcast", 1, 0, LOPT_BROADCAST },
|
||||
{ "neg-ttl", 1, 0, LOPT_NEGTTL },
|
||||
{ "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
|
||||
{ "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
|
||||
{ "min-port", 1, 0, LOPT_MINPORT },
|
||||
{ "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
|
||||
{ "cname", 1, 0, LOPT_CNAME },
|
||||
{ "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
|
||||
{ "pxe-service", 1, 0, LOPT_PXE_SERV },
|
||||
{ "test", 0, 0, LOPT_TEST },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
@@ -287,9 +292,7 @@ static struct {
|
||||
{ '2', ARG_DUP, "interface", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
|
||||
{ '3', ARG_DUP, "[=<id>[,<id>]]", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
|
||||
{ '4', ARG_DUP, "<id>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
{ LOPT_BRIDGE, ARG_DUP, "iface,alias,..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
|
||||
#endif
|
||||
{ '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
|
||||
{ '6', ARG_ONE, "path", gettext_noop("Script to run on DHCP lease creation and destruction."), NULL },
|
||||
{ '7', ARG_DUP, "path", gettext_noop("Read configuration from all the files in this directory."), NULL },
|
||||
@@ -317,13 +320,18 @@ static struct {
|
||||
{ LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
|
||||
{ LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
|
||||
{ LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
|
||||
{ LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
|
||||
{ LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
|
||||
{ LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
|
||||
{ 0, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
/* makes options which take a list of addresses */
|
||||
#define OT_ADDR_LIST 255
|
||||
#define OT_ADDR_LIST 0x80
|
||||
/* DHCP-internal options, for logging. not valid in config file */
|
||||
#define OT_INTERNAL 254
|
||||
#define OT_INTERNAL 0x40
|
||||
#define OT_NAME 0x20
|
||||
|
||||
static const struct {
|
||||
char *name;
|
||||
@@ -335,9 +343,9 @@ static const struct {
|
||||
{ "dns-server", 6, OT_ADDR_LIST },
|
||||
{ "log-server", 7, OT_ADDR_LIST },
|
||||
{ "lpr-server", 9, OT_ADDR_LIST },
|
||||
{ "hostname", 12, OT_INTERNAL },
|
||||
{ "hostname", 12, OT_INTERNAL | OT_NAME },
|
||||
{ "boot-file-size", 13, 2 },
|
||||
{ "domain-name", 15, 0 },
|
||||
{ "domain-name", 15, OT_NAME },
|
||||
{ "swap-server", 16, OT_ADDR_LIST },
|
||||
{ "root-path", 17, 0 },
|
||||
{ "extension-path", 18, 0 },
|
||||
@@ -348,7 +356,7 @@ static const struct {
|
||||
{ "default-ttl", 23, 1 },
|
||||
{ "mtu", 26, 2 },
|
||||
{ "all-subnets-local", 27, 1 },
|
||||
{ "broadcast", 28, OT_INTERNAL },
|
||||
{ "broadcast", 28, OT_INTERNAL | OT_ADDR_LIST },
|
||||
{ "router-discovery", 31, 1 },
|
||||
{ "router-solicitation", 32, OT_ADDR_LIST },
|
||||
{ "static-route", 33, OT_ADDR_LIST },
|
||||
@@ -367,11 +375,11 @@ static const struct {
|
||||
{ "netbios-scope", 47, 0 },
|
||||
{ "x-windows-fs", 48, OT_ADDR_LIST },
|
||||
{ "x-windows-dm", 49, OT_ADDR_LIST },
|
||||
{ "requested-address", 50, OT_INTERNAL },
|
||||
{ "requested-address", 50, OT_INTERNAL | OT_ADDR_LIST },
|
||||
{ "lease-time", 51, OT_INTERNAL },
|
||||
{ "option-overload", 52, OT_INTERNAL },
|
||||
{ "message-type", 53, OT_INTERNAL, },
|
||||
{ "server-identifier", 54, OT_INTERNAL },
|
||||
{ "server-identifier", 54, OT_INTERNAL | OT_ADDR_LIST },
|
||||
{ "parameter-request", 55, OT_INTERNAL },
|
||||
{ "message", 56, OT_INTERNAL },
|
||||
{ "max-message-size", 57, OT_INTERNAL },
|
||||
@@ -401,21 +409,25 @@ static const struct {
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static volatile int mem_recover = 0;
|
||||
static jmp_buf mem_jmp;
|
||||
static void one_file(char *file, int nest, int hard_opt);
|
||||
|
||||
char *option_string(unsigned char opt)
|
||||
char *option_string(unsigned char opt, int *is_ip, int *is_name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; opttab[i].name; i++)
|
||||
if (opttab[i].val == opt)
|
||||
return opttab[i].name;
|
||||
{
|
||||
if (is_ip)
|
||||
*is_ip = !!(opttab[i].size & OT_ADDR_LIST);
|
||||
if (is_name)
|
||||
*is_name = !!(opttab[i].size & OT_NAME);
|
||||
return opttab[i].name;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* We hide metacharaters in quoted strings by mapping them into the ASCII control
|
||||
character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
|
||||
following sequence so that they map to themselves: it is therefore possible to call
|
||||
@@ -626,6 +638,7 @@ static void do_usage(void)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
static void display_opts(void)
|
||||
{
|
||||
int i;
|
||||
@@ -760,7 +773,7 @@ static char *parse_dhcp_opt(char *arg, int flags)
|
||||
|
||||
/* We know that some options take addresses */
|
||||
|
||||
if (opt_len == OT_ADDR_LIST)
|
||||
if (opt_len & OT_ADDR_LIST)
|
||||
{
|
||||
is_string = is_dec = is_hex = 0;
|
||||
if (!is_addr || dots == 0)
|
||||
@@ -919,7 +932,7 @@ static char *parse_dhcp_opt(char *arg, int flags)
|
||||
}
|
||||
}
|
||||
|
||||
if (new->len > 255)
|
||||
if ((new->len > 255) || (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))))
|
||||
problem = _("dhcp-option too long");
|
||||
|
||||
if (!problem)
|
||||
@@ -946,6 +959,7 @@ static char *parse_dhcp_opt(char *arg, int flags)
|
||||
return problem;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
{
|
||||
@@ -1013,20 +1027,21 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
|
||||
while ((ent = readdir(dir_stream)))
|
||||
{
|
||||
size_t len;
|
||||
size_t len = strlen(ent->d_name);
|
||||
struct stat buf;
|
||||
|
||||
if ((len = strlen(ent->d_name)) == 0)
|
||||
continue;
|
||||
/* ignore emacs backups and dotfiles */
|
||||
if (ent->d_name[len - 1] == '~' ||
|
||||
if (len == 0 ||
|
||||
ent->d_name[len - 1] == '~' ||
|
||||
(ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
|
||||
ent->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
path = opt_malloc(strlen(directory) + len + 2);
|
||||
strcpy(path, directory);
|
||||
strcat(path, "/");
|
||||
strcat(path, ent->d_name);
|
||||
|
||||
if (stat(path, &buf) == -1)
|
||||
die(_("cannot access %s: %s"), path, EC_FILE);
|
||||
/* only reg files allowed. */
|
||||
@@ -1139,25 +1154,28 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
else
|
||||
daemon->mxtarget = opt_string_alloc(arg);
|
||||
break;
|
||||
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
case 'l': /* --dhcp-leasefile */
|
||||
daemon->lease_file = opt_string_alloc(arg);
|
||||
break;
|
||||
|
||||
case '6': /* --dhcp-script */
|
||||
#ifdef NO_FORK
|
||||
# ifdef NO_FORK
|
||||
problem = _("cannot run scripts under uClinux");
|
||||
#else
|
||||
# else
|
||||
daemon->lease_change_command = opt_string_alloc(arg);
|
||||
#endif
|
||||
# endif
|
||||
break;
|
||||
|
||||
#endif
|
||||
|
||||
case 'H': /* --addn-hosts */
|
||||
{
|
||||
struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
|
||||
static int hosts_index = 1;
|
||||
new->fname = opt_string_alloc(arg);
|
||||
new->index = hosts_index++;
|
||||
new->flags = 0;
|
||||
new->next = daemon->addn_hosts;
|
||||
daemon->addn_hosts = new;
|
||||
break;
|
||||
@@ -1219,9 +1237,11 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
daemon->group_set = 1;
|
||||
break;
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
case LOPT_SCRIPTUSR: /* --scriptuser */
|
||||
daemon->scriptuser = opt_string_alloc(arg);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'i': /* --interface */
|
||||
do {
|
||||
@@ -1520,11 +1540,14 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
case 'X': /* --dhcp-lease-max */
|
||||
if (!atoi_check(arg, &daemon->dhcp_max))
|
||||
option = '?';
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
case LOPT_TFTP_MAX: /* --tftp-max */
|
||||
if (!atoi_check(arg, &daemon->tftp_max))
|
||||
option = '?';
|
||||
@@ -1548,8 +1571,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
}
|
||||
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
case LOPT_BRIDGE: /* --bridge-interface */
|
||||
{
|
||||
struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
|
||||
@@ -1578,8 +1601,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
case 'F': /* --dhcp-range */
|
||||
{
|
||||
int k, leasepos = 2;
|
||||
@@ -1646,6 +1669,11 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
new->end = new->start;
|
||||
new->flags |= CONTEXT_STATIC;
|
||||
}
|
||||
else if (strcmp(a[1], "proxy") == 0)
|
||||
{
|
||||
new->end = new->start;
|
||||
new->flags |= CONTEXT_PROXY;
|
||||
}
|
||||
else if ((new->end.s_addr = inet_addr(a[1])) == (in_addr_t)-1)
|
||||
option = '?';
|
||||
|
||||
@@ -1916,7 +1944,122 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case LOPT_PXE_PROMT: /* --pxe-prompt */
|
||||
{
|
||||
struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
|
||||
int timeout;
|
||||
|
||||
new->netid = NULL;
|
||||
new->opt = 10; /* PXE_MENU_PROMPT */
|
||||
|
||||
while (arg && strstr(arg, "net:") == arg)
|
||||
{
|
||||
struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
|
||||
comma = split(arg);
|
||||
nn->next = new->netid;
|
||||
new->netid = nn;
|
||||
nn->net = opt_string_alloc(arg+4);
|
||||
arg = comma;
|
||||
}
|
||||
|
||||
if (!arg)
|
||||
option = '?';
|
||||
else
|
||||
{
|
||||
comma = split(arg);
|
||||
unhide_metas(arg);
|
||||
new->len = strlen(arg) + 1;
|
||||
new->val = opt_malloc(new->len);
|
||||
memcpy(new->val + 1, arg, new->len - 1);
|
||||
|
||||
new->u.vendor_class = (unsigned char *)"PXEClient";
|
||||
new->flags = DHOPT_VENDOR;
|
||||
|
||||
if (comma && atoi_check(comma, &timeout))
|
||||
*(new->val) = timeout;
|
||||
else
|
||||
*(new->val) = 255;
|
||||
|
||||
new->next = daemon->dhcp_opts;
|
||||
daemon->dhcp_opts = new;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case LOPT_PXE_SERV: /* --pxe-service */
|
||||
{
|
||||
struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
|
||||
char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
|
||||
"IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };
|
||||
static int boottype = 32768;
|
||||
|
||||
new->netid = NULL;
|
||||
new->server.s_addr = 0;
|
||||
|
||||
while (arg && strstr(arg, "net:") == arg)
|
||||
{
|
||||
struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
|
||||
comma = split(arg);
|
||||
nn->next = new->netid;
|
||||
new->netid = nn;
|
||||
nn->net = opt_string_alloc(arg+4);
|
||||
arg = comma;
|
||||
}
|
||||
|
||||
if (arg && (comma = split(arg)))
|
||||
{
|
||||
for (i = 0; CSA[i]; i++)
|
||||
if (strcasecmp(CSA[i], arg) == 0)
|
||||
break;
|
||||
|
||||
if (CSA[i] || atoi_check(arg, &i))
|
||||
{
|
||||
arg = comma;
|
||||
comma = split(arg);
|
||||
|
||||
new->CSA = i;
|
||||
new->menu = opt_string_alloc(arg);
|
||||
|
||||
if (comma)
|
||||
{
|
||||
arg = comma;
|
||||
comma = split(arg);
|
||||
if (atoi_check(arg, &i))
|
||||
{
|
||||
new->type = i;
|
||||
new->basename = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
new->type = boottype++;
|
||||
new->basename = opt_string_alloc(arg);
|
||||
}
|
||||
|
||||
if (comma && (new->server.s_addr = inet_addr(comma)) == (in_addr_t)-1)
|
||||
option = '?';
|
||||
|
||||
/* Order matters */
|
||||
new->next = NULL;
|
||||
if (!daemon->pxe_services)
|
||||
daemon->pxe_services = new;
|
||||
else
|
||||
{
|
||||
struct pxe_service *s;
|
||||
for (s = daemon->pxe_services; s->next; s = s->next);
|
||||
s->next = new;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
option = '?';
|
||||
break;
|
||||
}
|
||||
|
||||
case '4': /* --dhcp-mac */
|
||||
{
|
||||
if (!(comma = split(arg)))
|
||||
@@ -2058,6 +2201,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
new->list = list;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case 'V': /* --alias */
|
||||
{
|
||||
@@ -2311,6 +2455,10 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
new->weight = weight;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return _("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)");
|
||||
|
||||
}
|
||||
|
||||
if (problem)
|
||||
@@ -2328,10 +2476,32 @@ static void one_file(char *file, int nest, int hard_opt)
|
||||
int i, option;
|
||||
FILE *f;
|
||||
char *p, *arg, *start, *buff = daemon->namebuff;
|
||||
static struct fileread {
|
||||
dev_t dev;
|
||||
ino_t ino;
|
||||
struct fileread *next;
|
||||
} *filesread = NULL;
|
||||
struct stat statbuf;
|
||||
|
||||
/* ignore repeated files. */
|
||||
if (hard_opt == 0 && stat(file, &statbuf) == 0)
|
||||
{
|
||||
struct fileread *r;
|
||||
|
||||
for (r = filesread; r; r = r->next)
|
||||
if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino)
|
||||
return;
|
||||
|
||||
r = safe_malloc(sizeof(struct fileread));
|
||||
r->next = filesread;
|
||||
filesread = r;
|
||||
r->dev = statbuf.st_dev;
|
||||
r->ino = statbuf.st_ino;
|
||||
}
|
||||
|
||||
if (nest > 20)
|
||||
die(_("files nested too deep in %s"), file, EC_BADCONF);
|
||||
|
||||
|
||||
if (!(f = fopen(file, "r")))
|
||||
{
|
||||
if (errno == ENOENT && nest == 0)
|
||||
@@ -2476,6 +2646,7 @@ static void one_file(char *file, int nest, int hard_opt)
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
void reread_dhcp(void)
|
||||
{
|
||||
if (daemon->dhcp_hosts_file)
|
||||
@@ -2546,11 +2717,12 @@ void reread_dhcp(void)
|
||||
my_syslog(LOG_INFO, _("read %s"), daemon->dhcp_opts_file);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void read_opts(int argc, char **argv, char *compile_opts)
|
||||
{
|
||||
char *buff = opt_malloc(MAXDNAME);
|
||||
int option, nest = 0;
|
||||
int option, nest = 0, testmode = 0;
|
||||
char *errmess, *arg, *conffile = CONFFILE;
|
||||
|
||||
opterr = 0;
|
||||
@@ -2600,12 +2772,16 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
||||
arg = NULL;
|
||||
|
||||
/* command-line only stuff */
|
||||
if (option == 'w')
|
||||
if (option == LOPT_TEST)
|
||||
testmode = 1;
|
||||
else if (option == 'w')
|
||||
{
|
||||
if (argc == 3 && strcmp(argv[2], "dhcp") == 0)
|
||||
display_opts();
|
||||
else
|
||||
if (argc != 3 || strcmp(argv[2], "dhcp") != 0)
|
||||
do_usage();
|
||||
#ifdef HAVE_DHCP
|
||||
else
|
||||
display_opts();
|
||||
#endif
|
||||
exit(0);
|
||||
}
|
||||
else if (option == 'v')
|
||||
@@ -2752,4 +2928,10 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
||||
}
|
||||
else if (daemon->options & OPT_DHCP_FQDN)
|
||||
die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
|
||||
|
||||
if (testmode)
|
||||
{
|
||||
fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1290,7 +1290,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr,
|
||||
record_source(daemon->addn_hosts, crecp->uid));
|
||||
record_source(crecp->uid));
|
||||
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
crec_ttl(crecp, now), NULL,
|
||||
@@ -1400,7 +1400,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
{
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(crecp->flags, name, NULL, record_source(daemon->addn_hosts, crecp->uid));
|
||||
log_query(crecp->flags, name, NULL, record_source(crecp->uid));
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
crec_ttl(crecp, now), &nameoffset,
|
||||
T_CNAME, C_IN, "d", cache_get_name(crecp->addr.cname.cache)))
|
||||
@@ -1436,7 +1436,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr.addr,
|
||||
record_source(daemon->addn_hosts, crecp->uid));
|
||||
record_source(crecp->uid));
|
||||
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
crec_ttl(crecp, now), NULL, type, C_IN,
|
||||
|
||||
727
src/rfc2131.c
727
src/rfc2131.c
File diff suppressed because it is too large
Load Diff
49
src/tftp.c
49
src/tftp.c
@@ -45,9 +45,7 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
char *filename, *mode, *p, *end, *opt;
|
||||
struct sockaddr_in addr, peer;
|
||||
struct msghdr msg;
|
||||
struct cmsghdr *cmptr;
|
||||
struct iovec iov;
|
||||
struct ifreq ifr;
|
||||
int is_err = 1, if_index = 0;
|
||||
struct iname *tmp;
|
||||
struct tftp_transfer *transfer;
|
||||
@@ -62,7 +60,7 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
|
||||
#elif defined(HAVE_SOLARIS_NETWORK)
|
||||
char control[CMSG_SPACE(sizeof(unsigned int))];
|
||||
#else
|
||||
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
|
||||
char control[CMSG_SPACE(sizeof(struct sockaddr_dl))];
|
||||
#endif
|
||||
} control_u;
|
||||
@@ -88,6 +86,9 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
addr = listen->iface->addr.in;
|
||||
else
|
||||
{
|
||||
char name[IF_NAMESIZE];
|
||||
struct cmsghdr *cmptr;
|
||||
|
||||
addr.sin_addr.s_addr = 0;
|
||||
|
||||
#if defined(HAVE_LINUX_NETWORK)
|
||||
@@ -97,36 +98,32 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
addr.sin_addr = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_spec_dst;
|
||||
if_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
|
||||
}
|
||||
if (!(ifr.ifr_ifindex = if_index) ||
|
||||
ioctl(listen->tftpfd, SIOCGIFNAME, &ifr) == -1)
|
||||
return;
|
||||
|
||||
#elif defined(HAVE_SOLARIS_NETWORK)
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
|
||||
addr.sin_addr = *((struct in_addr *)CMSG_DATA(cmptr));
|
||||
else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
|
||||
if_index = *((unsigned int *)CMSG_DATA(cmptr));
|
||||
|
||||
|
||||
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
|
||||
addr.sin_addr = *((struct in_addr *)CMSG_DATA(cmptr));
|
||||
else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
|
||||
#ifdef HAVE_SOLARIS_NETWORK
|
||||
if_index = *((unsigned int *)CMSG_DATA(cmptr));
|
||||
#else
|
||||
if_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
|
||||
if_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
|
||||
|
||||
#endif
|
||||
|
||||
if (if_index == 0 || !if_indextoname(if_index, ifr.ifr_name))
|
||||
return;
|
||||
|
||||
#endif
|
||||
|
||||
if (addr.sin_addr.s_addr == 0)
|
||||
return;
|
||||
|
||||
if (!iface_check(AF_INET, (struct all_addr *)&addr.sin_addr,
|
||||
&ifr, &if_index))
|
||||
if (!indextoname(listen->tftpfd, if_index, name) ||
|
||||
addr.sin_addr.s_addr == 0 ||
|
||||
!iface_check(AF_INET, (struct all_addr *)&addr.sin_addr, name, &if_index))
|
||||
return;
|
||||
|
||||
/* allowed interfaces are the same as for DHCP */
|
||||
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, name) == 0))
|
||||
return;
|
||||
|
||||
}
|
||||
@@ -172,7 +169,7 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
addr.sin_port = htons(port);
|
||||
continue;
|
||||
}
|
||||
my_syslog(LOG_ERR, _("unable to get free port for TFTP"));
|
||||
my_syslog(MS_TFTP | LOG_ERR, _("unable to get free port for TFTP"));
|
||||
}
|
||||
free_transfer(transfer);
|
||||
return;
|
||||
@@ -268,7 +265,7 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
free_transfer(transfer);
|
||||
else
|
||||
{
|
||||
my_syslog(LOG_INFO, _("TFTP sent %s to %s"), daemon->namebuff, inet_ntoa(peer.sin_addr));
|
||||
my_syslog(MS_TFTP | LOG_INFO, _("TFTP sent %s to %s"), daemon->namebuff, inet_ntoa(peer.sin_addr));
|
||||
transfer->next = daemon->tftp_trans;
|
||||
daemon->tftp_trans = transfer;
|
||||
}
|
||||
@@ -402,7 +399,7 @@ void check_tftp_listeners(fd_set *rset, time_t now)
|
||||
*(q++) = *r;
|
||||
*q = 0;
|
||||
}
|
||||
my_syslog(LOG_ERR, _("TFTP error %d %s received from %s"),
|
||||
my_syslog(MS_TFTP | LOG_ERR, _("TFTP error %d %s received from %s"),
|
||||
(int)ntohs(mess->block), err,
|
||||
inet_ntoa(transfer->peer.sin_addr));
|
||||
|
||||
@@ -433,7 +430,7 @@ void check_tftp_listeners(fd_set *rset, time_t now)
|
||||
/* don't complain about timeout when we're awaiting the last
|
||||
ACK, some clients never send it */
|
||||
if (len != 0)
|
||||
my_syslog(LOG_ERR, _("TFTP failed sending %s to %s"),
|
||||
my_syslog(MS_TFTP | LOG_ERR, _("TFTP failed sending %s to %s"),
|
||||
transfer->file->filename, inet_ntoa(transfer->peer.sin_addr));
|
||||
len = 0;
|
||||
}
|
||||
@@ -493,7 +490,7 @@ static ssize_t tftp_err(int err, char *packet, char *message, char *file)
|
||||
mess->err = htons(err);
|
||||
ret += (snprintf(mess->message, 500, message, file, errstr) + 1);
|
||||
if (err != ERR_FNF)
|
||||
my_syslog(LOG_ERR, "TFTP %s", mess->message);
|
||||
my_syslog(MS_TFTP | LOG_ERR, "TFTP %s", mess->message);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
19
src/util.c
19
src/util.c
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
/* The SURF random number generator was taken from djbdns-1.05, by
|
||||
Daniel J Berstein, which is public domain. */
|
||||
Daniel J Bernstein, which is public domain. */
|
||||
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -344,14 +344,19 @@ int parse_hex(char *in, unsigned char *out, int maxlen,
|
||||
return i;
|
||||
}
|
||||
|
||||
/* return 0 for no match, or (no matched octets) + 1 */
|
||||
int memcmp_masked(unsigned char *a, unsigned char *b, int len, unsigned int mask)
|
||||
{
|
||||
int i;
|
||||
for (i = len - 1; i >= 0; i--, mask = mask >> 1)
|
||||
if (!(mask & 1) && a[i] != b[i])
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
int i, count;
|
||||
for (count = 1, i = len - 1; i >= 0; i--, mask = mask >> 1)
|
||||
if (!(mask & 1))
|
||||
{
|
||||
if (a[i] == b[i])
|
||||
count++;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/* _note_ may copy buffer */
|
||||
|
||||
Reference in New Issue
Block a user