[automerger] Add extra (size_t) cast to avoid compiler warning. am: 1387a89b14 am: bc2ee79a6e am: 53787550a7 am: 95129dbdb6 am: 10d8009592 am: e04fe5b516 am: aca21c9df5 am: db203bf112 am: 14cd06a72d am: 2e47278b09 am: 48d106d6bf am: cd33bb4337 am: d31b8df am: 12c4073fa7
am: 0aab2c5ab8  -s ours

Change-Id: Ia7812dae3e0fd88af7205a8e7130f86384731343
diff --git a/dbus/DBus-interface b/dbus/DBus-interface
deleted file mode 100755
index 8d578ca..0000000
--- a/dbus/DBus-interface
+++ /dev/null
@@ -1,131 +0,0 @@
-DBus support must be enabled at compile-time and run-time. Ensure 
-that src/config.h contains the line
-
-#define HAVE_DBUS.
-
-and that /etc/dnsmasq.conf contains the line
-
-enable-dbus
-
-Because dnsmasq can operate stand-alone from the DBus, and may need to provide
-service before the dbus daemon is available, it will continue to run
-if the DBus connection is not available at startup. The DBus will be polled 
-every 250ms until a connection is established. Start of polling and final
-connection establishment are both logged. When dnsmasq establishes a
-connection to the dbus, it sends the signal "Up". Anything controlling
-the server settings in dnsmasq should re-invoke the SetServers method
-(q.v.) when it sees this signal. This allows dnsmasq to be restarted
-and avoids startup races with the provider of nameserver information.
-
-
-Dnsmasq provides one service on the DBus: uk.org.thekelleys.dnsmasq
-and a single object: /uk/org/thekelleys/dnsmasq
-
-1. METHODS
-----------
-
-Methods are of the form
-
-uk.org.thekelleys.<method>
-
-Available methods are:
-
-GetVersion
-----------
-Returns a string containing the version of dnsmasq running.
-
-ClearCache
-----------
-Returns nothing. Clears the domain name cache and re-reads
-/etc/hosts. The same as sending dnsmasq a HUP signal.
-
-SetServers
-----------
-Returns nothing. Takes a set of arguments representing the new
-upstream DNS servers to be used by dnsmasq. IPv4 addresses are
-represented as a UINT32 (in network byte order) and IPv6 addresses
-are represented as sixteen BYTEs (since there is no UINT128 type).
-Each server address may be followed by one or more STRINGS, which are
-the domains for which the preceding server should be used.
-
-Examples.
-
-UINT32: <address1>
-UNIT32: <address2>
-
-is equivalent to
-
---server=<address1> --server=<address2>
-
-
-UINT32 <address1>
-UINT32 <address2>
-STRING "somedomain.com"
-
-is equivalent to
-
---server=<address1> --server=/somedomain.com/<address2> 
-
-UINT32 <address1>
-UINT32 <address2>
-STRING "somedomain.com"
-UINT32 <address3>
-STRING "anotherdomain.com"
-STRING "thirddomain.com"
-
-is equivalent to
-
---server=<address1> 
---server=/somedomain.com/<address2> 
---server=/anotherdomain.com/thirddomain.com/<address3>
-
-Am IPv4 address of 0.0.0.0 is interpreted as "no address, local only",
-so
-
-UINT32: <0.0.0.0>
-STRING  "local.domain"
-
-is equivalent to
-
---local=/local.domain/
-
-
-Each call to SetServers completely replaces the set of servers
-specified by via the DBus, but it leaves any servers specified via the
-command line or /etc/dnsmasq.conf or /etc/resolv.conf alone.
-
-2. SIGNALS
-----------
-
-If dnsmasq's DHCP server is active, it will send signals over DBUS whenever
-the DHCP lease database changes. Think of these signals as transactions on
-a database with the IP address acting as the primary key.
-
-Signals are of the form:
-
-uk.org.thekelleys.<signal>
-
-and their parameters are:
-
-STRING "192.168.1.115"
-STRING "01:23:45:67:89:ab"
-STRING "hostname.or.fqdn"
-
-
-Available signals are:
-
-DhcpLeaseAdded
----------------
-
-This signal is emitted when a DHCP lease for a given IP address is created.
-
-DhcpLeaseDeleted
-----------------
-
-This signal is emitted when a DHCP lease for a given IP address is deleted.
-
-DhcpLeaseUpdated
-----------------
-
-This signal is emitted when a DHCP lease for a given IP address is updated.
- 
diff --git a/dbus/dnsmasq.conf b/dbus/dnsmasq.conf
deleted file mode 100755
index 82b1c76..0000000
--- a/dbus/dnsmasq.conf
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE busconfig PUBLIC
- "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
-<busconfig>
-	<policy user="root">
-		<allow own="uk.org.thekelleys.dnsmasq"/>
-		<allow send_destination="uk.org.thekelleys.dnsmasq"/>
-	</policy>
-	<policy context="default">
-                <deny own="uk.org.thekelleys.dnsmasq"/>
-                <deny send_destination="uk.org.thekelleys.dnsmasq"/>
-        </policy>
-</busconfig>
-
diff --git a/src/Android.mk b/src/Android.mk
index 8edf9d6..7c729ef 100644
--- a/src/Android.mk
+++ b/src/Android.mk
@@ -3,14 +3,14 @@
 #########################
 
 include $(CLEAR_VARS)
-LOCAL_SRC_FILES :=  bpf.c cache.c dbus.c dhcp.c dnsmasq.c forward.c helper.c lease.c log.c \
-                    netlink.c network.c option.c rfc1035.c rfc2131.c tftp.c util.c
+LOCAL_SRC_FILES :=  bpf.c cache.c dhcp.c dnsmasq.c forward.c helper.c lease.c log.c \
+                    netlink.c network.c option.c rfc1035.c rfc2131.c util.c
 
 LOCAL_MODULE := dnsmasq
 
 LOCAL_C_INCLUDES := external/dnsmasq/src
 
-LOCAL_CFLAGS := -O2 -g -W -Wall -D__ANDROID__ -DIPV6 -DNO_TFTP -DNO_SCRIPT -D_BSD_SOURCE \
+LOCAL_CFLAGS := -O2 -g -W -Wall -D__ANDROID__ -DIPV6 -DNO_SCRIPT -D_BSD_SOURCE \
                 -Wno-unused-variable -Wno-unused-parameter -Werror
 LOCAL_SYSTEM_SHARED_LIBRARIES := libc
 LOCAL_SHARED_LIBRARIES := libcutils liblog
diff --git a/src/config.h b/src/config.h
index e63cbae..9e43696 100755
--- a/src/config.h
+++ b/src/config.h
@@ -68,16 +68,10 @@
 #define DHCP_CLIENT_PORT 68
 #define DHCP_SERVER_ALTPORT 1067
 #define DHCP_CLIENT_ALTPORT 1068
-#define TFTP_PORT 69
-#define TFTP_MAX_CONNECTIONS 50 /* max simultaneous connections */
 #define LOG_MAX 5 /* log-queue length */
 #define RANDFILE "/dev/urandom"
 #define DAD_WAIT 20 /* retry binding IPv6 sockets for this long */
 
-/* DBUS interface specifics */
-#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq"
-#define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq"
-
 /* A small collection of RR-types which are missing on some platforms */
 
 #ifndef T_SIG
@@ -124,9 +118,6 @@
    NOTE: when enabling or disabling this, be sure to delete any old
    leases file, otherwise dnsmasq may get very confused.
 
-HAVE_TFTP
-   define this to get dnsmasq's built-in TFTP server.
-
 HAVE_DHCP
    define this to get dnsmasq's DHCP server.
 
@@ -143,11 +134,6 @@
 HAVE_SOCKADDR_SA_LEN
    define this if struct sockaddr has sa_len field (*BSD) 
 
-HAVE_DBUS
-   Define this if you want to link against libdbus, and have dnsmasq
-   define some methods to allow (re)configuration of the upstream DNS 
-   servers via DBus.
-
 NOTES:
    For Linux you should define 
       HAVE_LINUX_NETWORK
@@ -168,15 +154,8 @@
 
 /* platform independent options- uncomment to enable */
 #define HAVE_DHCP
-#define HAVE_TFTP
 #define HAVE_SCRIPT
 /* #define HAVE_BROKEN_RTC */
-/* #define HAVE_DBUS */
-
-/* Allow TFTP to be disabled with COPTS=-DNO_TFTP */
-#ifdef NO_TFTP
-#undef HAVE_TFTP
-#endif
 
 /* Allow DHCP to be disabled with COPTS=-DNO_DHCP */
 #ifdef NO_DHCP
diff --git a/src/dbus.c b/src/dbus.c
deleted file mode 100755
index 841f924..0000000
--- a/src/dbus.c
+++ /dev/null
@@ -1,436 +0,0 @@
-/* dnsmasq is Copyright (c) 2000-2009 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
-   the Free Software Foundation; version 2 dated June, 1991, or
-   (at your option) version 3 dated 29 June, 2007.
- 
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-     
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "dnsmasq.h"
-
-#ifdef HAVE_DBUS
-
-#include <dbus/dbus.h>
-
-const char* introspection_xml =
-"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
-"\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
-"<node name=\"" DNSMASQ_PATH "\">\n"
-"  <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
-"    <method name=\"Introspect\">\n"
-"      <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
-"    </method>\n"
-"  </interface>\n"
-"  <interface name=\"" DNSMASQ_SERVICE "\">\n"
-"    <method name=\"ClearCache\">\n"
-"    </method>\n"
-"    <method name=\"GetVersion\">\n"
-"      <arg name=\"version\" direction=\"out\" type=\"s\"/>\n"
-"    </method>\n"
-"    <method name=\"SetServers\">\n"
-"      <arg name=\"servers\" direction=\"in\" type=\"av\"/>\n"
-"    </method>\n"
-"    <signal name=\"DhcpLeaseAdded\">\n"
-"      <arg name=\"ipaddr\" type=\"s\"/>\n"
-"      <arg name=\"hwaddr\" type=\"s\"/>\n"
-"      <arg name=\"hostname\" type=\"s\"/>\n"
-"    </signal>\n"
-"    <signal name=\"DhcpLeaseDeleted\">\n"
-"      <arg name=\"ipaddr\" type=\"s\"/>\n"
-"      <arg name=\"hwaddr\" type=\"s\"/>\n"
-"      <arg name=\"hostname\" type=\"s\"/>\n"
-"    </signal>\n"
-"    <signal name=\"DhcpLeaseUpdated\">\n"
-"      <arg name=\"ipaddr\" type=\"s\"/>\n"
-"      <arg name=\"hwaddr\" type=\"s\"/>\n"
-"      <arg name=\"hostname\" type=\"s\"/>\n"
-"    </signal>\n"
-"  </interface>\n"
-"</node>\n";
-
-struct watch {
-  DBusWatch *watch;      
-  struct watch *next;
-};
-
-
-static dbus_bool_t add_watch(DBusWatch *watch, void *data)
-{
-  struct watch *w;
-
-  for (w = daemon->watches; w; w = w->next)
-    if (w->watch == watch)
-      return TRUE;
-
-  if (!(w = whine_malloc(sizeof(struct watch))))
-    return FALSE;
-
-  w->watch = watch;
-  w->next = daemon->watches;
-  daemon->watches = w;
-
-  w = data; /* no warning */
-  return TRUE;
-}
-
-static void remove_watch(DBusWatch *watch, void *data)
-{
-  struct watch **up, *w;  
-  
-  for (up = &(daemon->watches), w = daemon->watches; w; w = w->next)
-    if (w->watch == watch)
-      {
-        *up = w->next;
-        free(w);
-      }
-    else
-      up = &(w->next);
-
-  w = data; /* no warning */
-}
-
-static void dbus_read_servers(DBusMessage *message)
-{
-  struct server *serv, *tmp, **up;
-  DBusMessageIter iter;
-  union  mysockaddr addr, source_addr;
-  char *domain;
-  
-  dbus_message_iter_init(message, &iter);
-  
-  /* mark everything from DBUS */
-  for (serv = daemon->servers; serv; serv = serv->next)
-    if (serv->flags & SERV_FROM_DBUS)
-      serv->flags |= SERV_MARK;
-  
-  while (1)
-    {
-      int skip = 0;
-
-      if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_UINT32)
-	{
-	  u32 a;
-	  
-	  dbus_message_iter_get_basic(&iter, &a);
-	  dbus_message_iter_next (&iter);
-	  
-#ifdef HAVE_SOCKADDR_SA_LEN
-	  source_addr.in.sin_len = addr.in.sin_len = sizeof(struct sockaddr_in);
-#endif
-	  addr.in.sin_addr.s_addr = ntohl(a);
-	  source_addr.in.sin_family = addr.in.sin_family = AF_INET;
-	  addr.in.sin_port = htons(NAMESERVER_PORT);
-	  source_addr.in.sin_addr.s_addr = INADDR_ANY;
-	  source_addr.in.sin_port = htons(daemon->query_port);
-	}
-      else if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_BYTE)
-	{
-	  unsigned char p[sizeof(struct in6_addr)];
-	  unsigned int i;
-
-	  skip = 1;
-
-	  for(i = 0; i < sizeof(struct in6_addr); i++)
-	    {
-	      dbus_message_iter_get_basic(&iter, &p[i]);
-	      dbus_message_iter_next (&iter);
-	      if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BYTE)
-		break;
-	    }
-
-#ifndef HAVE_IPV6
-	  my_syslog(LOG_WARNING, _("attempt to set an IPv6 server address via DBus - no IPv6 support"));
-#else
-	  if (i == sizeof(struct in6_addr)-1)
-	    {
-	      memcpy(&addr.in6.sin6_addr, p, sizeof(struct in6_addr));
-#ifdef HAVE_SOCKADDR_SA_LEN
-              source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(struct sockaddr_in6);
-#endif
-              source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
-              addr.in6.sin6_port = htons(NAMESERVER_PORT);
-              source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
-	      source_addr.in6.sin6_scope_id = addr.in6.sin6_scope_id = 0;
-              source_addr.in6.sin6_addr = in6addr_any;
-              source_addr.in6.sin6_port = htons(daemon->query_port);
-	      skip = 0;
-	    }
-#endif
-	}
-      else
-	/* At the end */
-	break;
-      
-      do {
-	if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING)
-	  {
-	    dbus_message_iter_get_basic(&iter, &domain);
-	    dbus_message_iter_next (&iter);
-	  }
-	else
-	  domain = NULL;
-	
-	if (!skip)
-	  {
-	    /* See if this is already there, and unmark */
-	    for (serv = daemon->servers; serv; serv = serv->next)
-	      if ((serv->flags & SERV_FROM_DBUS) &&
-		  (serv->flags & SERV_MARK))
-		{
-		  if (!(serv->flags & SERV_HAS_DOMAIN) && !domain)
-		    {
-		      serv->flags &= ~SERV_MARK;
-		      break;
-		    }
-		  if ((serv->flags & SERV_HAS_DOMAIN) && 
-		      domain &&
-		      hostname_isequal(domain, serv->domain))
-		    {
-		      serv->flags &= ~SERV_MARK;
-		      break;
-		    }
-		}
-	    
-	    if (!serv && (serv = whine_malloc(sizeof (struct server))))
-	      {
-		/* Not found, create a new one. */
-		memset(serv, 0, sizeof(struct server));
-		
-		if (domain)
-		  serv->domain = whine_malloc(strlen(domain)+1);
-		
-		if (domain && !serv->domain)
-		  {
-		    free(serv);
-		    serv = NULL;
-		  }
-		else
-		  {
-		    serv->next = daemon->servers;
-		    daemon->servers = serv;
-		    serv->flags = SERV_FROM_DBUS;
-		    if (domain)
-		      {
-			strcpy(serv->domain, domain);
-			serv->flags |= SERV_HAS_DOMAIN;
-		      }
-		  }
-	      }
-
-	    if (serv)
-	      {
-		if (source_addr.in.sin_family == AF_INET &&
-		    addr.in.sin_addr.s_addr == 0 &&
-		    serv->domain)
-		  serv->flags |= SERV_NO_ADDR;
-		else
-		  {
-		    serv->flags &= ~SERV_NO_ADDR;
-		    serv->addr = addr;
-		    serv->source_addr = source_addr;
-		  }
-	      }
-	  }
-	} while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING);
-    }
-  
-  /* unlink and free anything still marked. */
-  for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp) 
-    {
-      tmp = serv->next;
-      if (serv->flags & SERV_MARK)
-	{
-	  server_gone(serv);
-	  *up = serv->next;
-	  free(serv);
-	}
-      else 
-	up = &serv->next;
-    }
-
-}
-
-DBusHandlerResult message_handler(DBusConnection *connection, 
-				  DBusMessage *message, 
-				  void *user_data)
-{
-  char *method = (char *)dbus_message_get_member(message);
-   
-  if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
-    {
-      DBusMessage *reply = dbus_message_new_method_return(message);
-
-      dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection_xml, DBUS_TYPE_INVALID);
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-    }
-  else if (strcmp(method, "GetVersion") == 0)
-    {
-      char *v = VERSION;
-      DBusMessage *reply = dbus_message_new_method_return(message);
-      
-      dbus_message_append_args(reply, DBUS_TYPE_STRING, &v, DBUS_TYPE_INVALID);
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-    }
-  else if (strcmp(method, "SetServers") == 0)
-    {
-      my_syslog(LOG_INFO, _("setting upstream servers from DBus"));
-      dbus_read_servers(message);
-      check_servers();
-    }
-  else if (strcmp(method, "ClearCache") == 0)
-    clear_cache_and_reload(dnsmasq_time());
-  else
-    return (DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
-  
-  method = user_data; /* no warning */
-
-  return (DBUS_HANDLER_RESULT_HANDLED);
- 
-}
- 
-
-/* returns NULL or error message, may fail silently if dbus daemon not yet up. */
-char *dbus_init(void)
-{
-  DBusConnection *connection = NULL;
-  DBusObjectPathVTable dnsmasq_vtable = {NULL, &message_handler, NULL, NULL, NULL, NULL };
-  DBusError dbus_error;
-  DBusMessage *message;
-
-  dbus_error_init (&dbus_error);
-  if (!(connection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error)))
-    return NULL;
-    
-  dbus_connection_set_exit_on_disconnect(connection, FALSE);
-  dbus_connection_set_watch_functions(connection, add_watch, remove_watch, 
-				      NULL, NULL, NULL);
-  dbus_error_init (&dbus_error);
-  dbus_bus_request_name (connection, DNSMASQ_SERVICE, 0, &dbus_error);
-  if (dbus_error_is_set (&dbus_error))
-    return (char *)dbus_error.message;
-  
-  if (!dbus_connection_register_object_path(connection,  DNSMASQ_PATH, 
-					    &dnsmasq_vtable, NULL))
-    return _("could not register a DBus message handler");
-  
-  daemon->dbus = connection; 
-  
-  if ((message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, "Up")))
-    {
-      dbus_connection_send(connection, message, NULL);
-      dbus_message_unref(message);
-    }
-
-  return NULL;
-}
- 
-
-void set_dbus_listeners(int *maxfdp,
-			fd_set *rset, fd_set *wset, fd_set *eset)
-{
-  struct watch *w;
-  
-  for (w = daemon->watches; w; w = w->next)
-    if (dbus_watch_get_enabled(w->watch))
-      {
-	unsigned int flags = dbus_watch_get_flags(w->watch);
-	int fd = dbus_watch_get_unix_fd(w->watch);
-	
-	bump_maxfd(fd, maxfdp);
-	
-	if (flags & DBUS_WATCH_READABLE)
-	  FD_SET(fd, rset);
-	
-	if (flags & DBUS_WATCH_WRITABLE)
-	  FD_SET(fd, wset);
-	
-	FD_SET(fd, eset);
-      }
-}
-
-void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)
-{
-  DBusConnection *connection = (DBusConnection *)daemon->dbus;
-  struct watch *w;
-
-  for (w = daemon->watches; w; w = w->next)
-    if (dbus_watch_get_enabled(w->watch))
-      {
-	unsigned int flags = 0;
-	int fd = dbus_watch_get_unix_fd(w->watch);
-	
-	if (FD_ISSET(fd, rset))
-	  flags |= DBUS_WATCH_READABLE;
-	
-	if (FD_ISSET(fd, wset))
-	  flags |= DBUS_WATCH_WRITABLE;
-	
-	if (FD_ISSET(fd, eset))
-	  flags |= DBUS_WATCH_ERROR;
-
-	if (flags != 0)
-	  dbus_watch_handle(w->watch, flags);
-      }
-
-  if (connection)
-    {
-      dbus_connection_ref (connection);
-      while (dbus_connection_dispatch (connection) == DBUS_DISPATCH_DATA_REMAINS);
-      dbus_connection_unref (connection);
-    }
-}
-
-void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname)
-{
-  DBusConnection *connection = (DBusConnection *)daemon->dbus;
-  DBusMessage* message = NULL;
-  DBusMessageIter args;
-  char *action_str, *addr, *mac = daemon->namebuff;
-  unsigned char *p;
-  int i;
-
-  if (!connection)
-    return;
-  
-  if (!hostname)
-    hostname = "";
-  
-  p = extended_hwaddr(lease->hwaddr_type, lease->hwaddr_len,
-		      lease->hwaddr, lease->clid_len, lease->clid, &i);
-  print_mac(mac, p, i);
-  
-  if (action == ACTION_DEL)
-    action_str = "DhcpLeaseDeleted";
-  else if (action == ACTION_ADD)
-    action_str = "DhcpLeaseAdded";
-  else if (action == ACTION_OLD)
-    action_str = "DhcpLeaseUpdated";
-  else
-    return;
-
-  addr = inet_ntoa(lease->addr);
-
-  if (!(message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, action_str)))
-    return;
-  
-  dbus_message_iter_init_append(message, &args);
-
-  if (dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &addr) &&
-      dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &mac) &&
-      dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &hostname))
-    dbus_connection_send(connection, message, NULL);
-  
-  dbus_message_unref(message);
-}
-
-#endif
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index 24e7055..27f8bce 100755
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -33,10 +33,6 @@
 #ifdef NO_FORK
 "no-MMU "
 #endif
-#ifndef HAVE_DBUS
-"no-"
-#endif
-"DBus "
 #ifndef LOCALEDIR
 "no-"
 #endif
@@ -46,12 +42,9 @@
 #endif
 "DHCP "
 #if defined(HAVE_DHCP) && !defined(HAVE_SCRIPT)
-"no-scripts "
+"no-scripts"
 #endif
-#ifndef HAVE_TFTP
-"no-"
-#endif
-"TFTP";
+"";
 
 
 
@@ -145,11 +138,6 @@
     }
 #endif
 
-#ifndef HAVE_TFTP
-  if (daemon->options & OPT_TFTP)
-    die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
-#endif
-
 #ifdef HAVE_SOLARIS_NETWORK
   if (daemon->max_logs != 0)
     die(_("asychronous logging is not available under Solaris"), NULL, EC_BADCONF);
@@ -194,20 +182,7 @@
   
   if (daemon->port != 0)
     cache_init();
-    
-  if (daemon->options & OPT_DBUS)
-#ifdef HAVE_DBUS
-    {
-      char *err;
-      daemon->dbus = NULL;
-      daemon->watches = NULL;
-      if ((err = dbus_init()))
-	die(_("DBus error: %s"), err, EC_MISC);
-    }
-#else
-  die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
-#endif
-  
+ 
   if (daemon->port != 0)
     pre_allocate_sfds();
 
@@ -466,16 +441,6 @@
     my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
   
   my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
-  
-#ifdef HAVE_DBUS
-  if (daemon->options & OPT_DBUS)
-    {
-      if (daemon->dbus)
-	my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
-      else
-	my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
-    }
-#endif
 
   if (log_err != 0)
     my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"), 
@@ -521,49 +486,6 @@
     }
 #endif
 
-#ifdef HAVE_TFTP
-  if (daemon->options & OPT_TFTP)
-    {
-#ifdef FD_SETSIZE
-      if (FD_SETSIZE < (unsigned)max_fd)
-	max_fd = FD_SETSIZE;
-#endif
-
-      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") : "");
-      
-      /* This is a guess, it assumes that for small limits, 
-	 disjoint files might be served, but for large limits, 
-	 a single file will be sent to may clients (the file only needs
-	 one fd). */
-
-      max_fd -= 30; /* use other than TFTP */
-      
-      if (max_fd < 0)
-	max_fd = 5;
-      else if (max_fd < 100)
-	max_fd = max_fd/2;
-      else
-	max_fd = max_fd - 20;
-      
-      /* if we have to use a limited range of ports, 
-	 that will limit the number of transfers */
-      if (daemon->start_tftp_port != 0 &&
-	  daemon->end_tftp_port - daemon->start_tftp_port + 1 < max_fd)
-	max_fd = daemon->end_tftp_port - daemon->start_tftp_port + 1;
-
-      if (daemon->tftp_max > max_fd)
-	{
-	  daemon->tftp_max = max_fd;
-	  my_syslog(MS_TFTP | LOG_WARNING, 
-		    _("restricting maximum simultaneous TFTP transfers to %d"), 
-		    daemon->tftp_max);
-	}
-    }
-#endif
-
   /* finished start-up - release original process */
   if (err_pipe[1] != -1)
     close(err_pipe[1]);
@@ -595,19 +517,6 @@
       set_android_listeners(&rset, &maxfd);
 #endif
 
-      /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
-      if (daemon->tftp_trans ||
-	  ((daemon->options & OPT_DBUS) && !daemon->dbus))
-	{
-	  t.tv_sec = 0;
-	  t.tv_usec = 250000;
-	  tp = &t;
-	}
-
-#ifdef HAVE_DBUS
-      set_dbus_listeners(&maxfd, &rset, &wset, &eset);
-#endif	
-  
 #ifdef HAVE_DHCP
       if (daemon->dhcp)
 	{
@@ -672,19 +581,6 @@
       if (FD_ISSET(daemon->netlinkfd, &rset))
 	netlink_multicast();
 #endif
-      
-#ifdef HAVE_DBUS
-      /* if we didn't create a DBus connection, retry now. */ 
-     if ((daemon->options & OPT_DBUS) && !daemon->dbus)
-	{
-	  char *err;
-	  if ((err = dbus_init()))
-	    my_syslog(LOG_WARNING, _("DBus error: %s"), err);
-	  if (daemon->dbus)
-	    my_syslog(LOG_INFO, _("connected to system DBus"));
-	}
-      check_dbus_listeners(&rset, &wset, &eset);
-#endif
 
 #if defined(__ANDROID__) && !defined(__BRILLO__)
       check_android_listeners(&rset);
@@ -692,10 +588,6 @@
       
       check_dns_listeners(&rset, now);
 
-#ifdef HAVE_TFTP
-      check_tftp_listeners(&rset, now);
-#endif      
-
 #ifdef HAVE_DHCP
       if (daemon->dhcp && FD_ISSET(daemon->dhcpfd, &rset))
 	dhcp_packet(now);
@@ -1039,18 +931,7 @@
   struct serverfd *serverfdp;
   struct listener *listener;
   int wait = 0, i;
-  
-#ifdef HAVE_TFTP
-  int  tftp = 0;
-  struct tftp_transfer *transfer;
-  for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
-    {
-      tftp++;
-      FD_SET(transfer->sockfd, set);
-      bump_maxfd(transfer->sockfd, maxfdp);
-    }
-#endif
-  
+
   /* will we be able to get memory? */
   if (daemon->port != 0)
     get_new_frec(now, &wait);
@@ -1088,15 +969,6 @@
 	      bump_maxfd(listener->tcpfd, maxfdp);
 	      break;
 	    }
-
-#ifdef HAVE_TFTP
-      if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
-	{
-	  FD_SET(listener->tftpfd, set);
-	  bump_maxfd(listener->tftpfd, maxfdp);
-	}
-#endif
-
     }
   
   return wait;
@@ -1122,11 +994,6 @@
     {
       if (listener->fd != -1 && FD_ISSET(listener->fd, set))
 	receive_query(listener, now); 
-      
-#ifdef HAVE_TFTP     
-      if (listener->tftpfd != -1 && FD_ISSET(listener->tftpfd, set))
-	tftp_request(listener, now);
-#endif
 
       if (listener->tcpfd != -1 && FD_ISSET(listener->tcpfd, set))
 	{
@@ -1257,7 +1124,7 @@
   /* Try and get an ICMP echo from a machine. */
 
   /* Note that whilst in the three second wait, we check for 
-     (and service) events on the DNS and TFTP  sockets, (so doing that
+     (and service) events on the DNS sockets, (so doing that
      better not use any resources our caller has in use...)
      but we remain deaf to signals or further DHCP packets. */
 
@@ -1330,10 +1197,6 @@
       check_log_writer(&wset);
       check_dns_listeners(&rset, now);
 
-#ifdef HAVE_TFTP
-      check_tftp_listeners(&rset, now);
-#endif
-
       if (FD_ISSET(fd, &rset) &&
 	  recvfrom(fd, &packet, sizeof(packet), 0,
 		   (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 10b8521..2a78497 100755
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -348,7 +348,7 @@
 };
 
 struct listener {
-  int fd, tcpfd, tftpfd, family;
+  int fd, tcpfd, family;
   struct irec *iface; /* only valid for non-wildcard */
   struct listener *next;
 };
@@ -575,26 +575,6 @@
   struct ping_result *next;
 };
 
-struct tftp_file {
-  int refcount, fd;
-  off_t size;
-  dev_t dev;
-  ino_t inode;
-  char filename[];
-};
-
-struct tftp_transfer {
-  int sockfd;
-  time_t timeout;
-  int backoff;
-  unsigned int block, blocksize, expansion;
-  off_t offset;
-  struct sockaddr_in peer;
-  char opt_blocksize, opt_transize, netascii, carrylf;
-  struct tftp_file *file;
-  struct tftp_transfer *next;
-};
-
 extern struct daemon {
   /* datastuctures representing the command-line and 
      config file arguments. All set (including defaults)
@@ -637,13 +617,11 @@
   int enable_pxe;
   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;
+  int dhcp_max;
   int dhcp_server_port, dhcp_client_port;
-  int start_tftp_port, end_tftp_port; 
   unsigned int min_leasetime;
   struct doctor *doctors;
   unsigned short edns_pktsz;
-  char *tftp_prefix; 
   uint32_t listen_mark;
 
   /* globally used stuff for DNS */
@@ -677,16 +655,6 @@
   FILE *lease_stream;
   struct dhcp_bridge *bridges;
 
-  /* DBus stuff */
-  /* void * here to avoid depending on dbus headers outside dbus.c */
-  void *dbus;
-#ifdef HAVE_DBUS
-  struct watch *watches;
-#endif
-
-  /* TFTP stuff */
-  struct tftp_transfer *tftp_trans;
-
 } *daemon;
 
 /* cache.c */
@@ -875,14 +843,6 @@
 /* bpf.c or netlink.c */
 int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_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);
-void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
-#endif
-
 /* helper.c */
 #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);
@@ -891,9 +851,3 @@
 		  char *hostname, time_t now);
 int helper_buf_empty(void);
 #endif
-
-/* tftp.c */
-#ifdef HAVE_TFTP
-void tftp_request(struct listener *listen, time_t now);
-void check_tftp_listeners(fd_set *rset, time_t now);
-#endif
diff --git a/src/lease.c b/src/lease.c
index c021d15..985bd73 100755
--- a/src/lease.c
+++ b/src/lease.c
@@ -530,13 +530,6 @@
 {
   struct dhcp_lease *lease;
 
-#ifdef HAVE_DBUS
-  /* If we're going to be sending DBus signals, but the connection is not yet up,
-     delay everything until it is. */
-  if ((daemon->options & OPT_DBUS) && !daemon->dbus)
-    return 0;
-#endif
-
   if (old_leases)
     {
       lease = old_leases;
@@ -557,9 +550,6 @@
 #ifdef HAVE_SCRIPT
 	  queue_script(ACTION_DEL, lease, lease->old_hostname, now);
 #endif
-#ifdef HAVE_DBUS
-	  emit_dbus_signal(ACTION_DEL, lease, lease->old_hostname);
-#endif
 	  old_leases = lease->next;
 	  
 	  free(lease->old_hostname); 
@@ -593,10 +583,6 @@
 	queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease, 
 		     lease->fqdn ? lease->fqdn : lease->hostname, now);
 #endif
-#ifdef HAVE_DBUS
-	emit_dbus_signal(lease->new ? ACTION_ADD : ACTION_OLD, lease,
-			 lease->fqdn ? lease->fqdn : lease->hostname);
-#endif
 	lease->new = lease->changed = lease->aux_changed = 0;
 	
 	/* these are used for the "add" call, then junked, since they're not in the database */
diff --git a/src/network.c b/src/network.c
index 1588288..b1a06e4 100755
--- a/src/network.c
+++ b/src/network.c
@@ -320,7 +320,6 @@
   l = safe_malloc(sizeof(struct listener));
   l->fd = fd;
   l->tcpfd = tcpfd;
-  l->tftpfd = -1;
   l->family = AF_INET6;
   l->iface = NULL;
   l->next = NULL;
@@ -335,7 +334,7 @@
   union mysockaddr addr;
   int opt = 1;
   struct listener *l, *l6 = NULL;
-  int tcpfd = -1, fd = -1, tftpfd = -1;
+  int tcpfd = -1, fd = -1;
 
   memset(&addr, 0, sizeof(addr));
   addr.in.sin_family = AF_INET;
@@ -387,31 +386,11 @@
       }
     }
 #endif /* __ANDROID__ */
-  
-#ifdef HAVE_TFTP
-  if (daemon->options & OPT_TFTP)
-    {
-      addr.in.sin_port = htons(TFTP_PORT);
-      if ((tftpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
-	return NULL;
-      
-      if (!fix_fd(tftpfd) ||
-#if defined(HAVE_LINUX_NETWORK) 
-	  setsockopt(tftpfd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1 ||
-#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
-	  setsockopt(tftpfd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
-	  setsockopt(tftpfd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1 ||
-#endif 
-	  bind(tftpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
-	return NULL;
-    }
-#endif
-  
+
   l = safe_malloc(sizeof(struct listener));
   l->family = AF_INET;
   l->fd = fd;
   l->tcpfd = tcpfd;
-  l->tftpfd = tftpfd;
   l->iface = NULL;
   l->next = l6;
 
@@ -442,7 +421,6 @@
   new->family = iface->addr.sa.sa_family;
   new->iface = iface;
   new->next = *listeners;
-  new->tftpfd = -1;
   new->tcpfd = -1;
   new->fd = -1;
   *listeners = new;
@@ -502,20 +480,6 @@
     if (listen(new->tcpfd, 5) == -1)
       die(_("failed to listen on socket: %s"), NULL, EC_BADNET);
   }
-
-#ifdef HAVE_TFTP
-  if ((daemon->options & OPT_TFTP) && iface->addr.sa.sa_family == AF_INET && iface->dhcp_ok)
-  {
-    short save = iface->addr.in.sin_port;
-    iface->addr.in.sin_port = htons(TFTP_PORT);
-    if ((new->tftpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 ||
-        setsockopt(new->tftpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
-        !fix_fd(new->tftpfd) ||
-        bind(new->tftpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
-      die(_("failed to create TFTP socket: %s"), NULL, EC_BADNET);
-    iface->addr.in.sin_port = save;
-  }
-#endif
 }
 
 /**
@@ -559,11 +523,6 @@
     my_syslog(LOG_INFO, _("Closing wildcard listener family=%d"), listener->family);
   }
 
-  if (listener->tftpfd != -1)
-  {
-    close(listener->tftpfd);
-    listener->tftpfd = -1;
-  }
   if (listener->tcpfd != -1)
   {
     close(listener->tcpfd);
@@ -633,7 +592,6 @@
       new->family = iface->addr.sa.sa_family;
       new->iface = iface;
       new->next = listeners;
-      new->tftpfd = -1;
       new->tcpfd = -1;
       new->fd = -1;
       listeners = new;
@@ -686,20 +644,6 @@
 	  if (listen(new->tcpfd, 5) == -1)
 	    die(_("failed to listen on socket: %s"), NULL, EC_BADNET);
 	}
-
-#ifdef HAVE_TFTP
-      if ((daemon->options & OPT_TFTP) && iface->addr.sa.sa_family == AF_INET && iface->dhcp_ok)
-	{
-	  short save = iface->addr.in.sin_port;
-	  iface->addr.in.sin_port = htons(TFTP_PORT);
-	  if ((new->tftpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 ||
-	      setsockopt(new->tftpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
-	      !fix_fd(new->tftpfd) ||
-	      bind(new->tftpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
-	    die(_("failed to create TFTP socket: %s"), NULL, EC_BADNET);
-	  iface->addr.in.sin_port = save;
-	}
-#endif
 #endif /* !__ANDROID */
     }
 
diff --git a/src/option.c b/src/option.c
index 8d5a39e..3b190ab 100755
--- a/src/option.c
+++ b/src/option.c
@@ -611,7 +611,6 @@
     { '*', EDNS_PKTSZ },
     { '&', MAXLEASES },
     { '!', FTABSIZ },
-    { '#', TFTP_MAX_CONNECTIONS },
     { '\0', 0 }
   };
 
@@ -1585,33 +1584,7 @@
 	option = '?';
       break;
 #endif
-      
-#ifdef HAVE_TFTP
-    case LOPT_TFTP_MAX:  /*  --tftp-max */
-      if (!atoi_check(arg, &daemon->tftp_max))
-	option = '?';
-      break;  
 
-    case LOPT_PREFIX: /* --tftp-prefix */
-      daemon->tftp_prefix = opt_string_alloc(arg);
-      break;
-
-    case LOPT_TFTPPORTS: /* --tftp-port-range */
-      if (!(comma = split(arg)) || 
-	  !atoi_check16(arg, &daemon->start_tftp_port) ||
-	  !atoi_check16(comma, &daemon->end_tftp_port))
-	problem = _("bad port range");
-      
-      if (daemon->start_tftp_port > daemon->end_tftp_port)
-	{
-	  int tmp = daemon->start_tftp_port;
-	  daemon->start_tftp_port = daemon->end_tftp_port;
-	  daemon->end_tftp_port = tmp;
-	} 
-      
-      break;
-#endif
-	      
     case LOPT_BRIDGE:   /* --bridge-interface */
       {
 	struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
@@ -2506,17 +2479,17 @@
       {
 	char *endptr;
 	uint32_t mark = strtoul(arg, &endptr, 0);
-my_syslog(LOG_WARNING, "passed-in mark: %s", arg);
+        // my_syslog(LOG_WARNING, "passed-in mark: %s", arg);
 	if (!*endptr)
 	  daemon->listen_mark = mark;
 	else
 	  problem = _("invalid mark");
-my_syslog(LOG_WARNING, "daemon->listen_mark: 0x%x, *endptr=%d", daemon->listen_mark, *endptr);
+        // my_syslog(LOG_WARNING, "daemon->listen_mark: 0x%x, *endptr=%d", daemon->listen_mark, *endptr);
 	break;
       }
 
     default:
-      return _("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)");
+      return _("unsupported option (check that dnsmasq was compiled with DHCP support)");
 
     }
 
@@ -2802,7 +2775,6 @@
   daemon->username = CHUSER;
   daemon->runfile =  RUNFILE;
   daemon->dhcp_max = MAXLEASES;
-  daemon->tftp_max = TFTP_MAX_CONNECTIONS;
   daemon->edns_pktsz = EDNS_PKTSZ;
   daemon->log_fac = -1;
   add_txt("version.bind", "dnsmasq-" VERSION );
diff --git a/src/tftp.c b/src/tftp.c
deleted file mode 100755
index c1ddb19..0000000
--- a/src/tftp.c
+++ /dev/null
@@ -1,600 +0,0 @@
-/* dnsmasq is Copyright (c) 2000-2009 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
-   the Free Software Foundation; version 2 dated June, 1991, or
-   (at your option) version 3 dated 29 June, 2007.
- 
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-     
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "dnsmasq.h"
-
-#ifdef HAVE_TFTP
-
-static struct tftp_file *check_tftp_fileperm(ssize_t *len);
-static void free_transfer(struct tftp_transfer *transfer);
-static ssize_t tftp_err(int err, char *packet, char *mess, char *file);
-static ssize_t tftp_err_oops(char *packet, char *file);
-static ssize_t get_block(char *packet, struct tftp_transfer *transfer);
-static char *next(char **p, char *end);
-
-#define OP_RRQ  1
-#define OP_WRQ  2
-#define OP_DATA 3
-#define OP_ACK  4
-#define OP_ERR  5
-#define OP_OACK 6
-
-#define ERR_NOTDEF 0
-#define ERR_FNF    1
-#define ERR_PERM   2
-#define ERR_FULL   3
-#define ERR_ILL    4
-
-void tftp_request(struct listener *listen, time_t now)
-{
-  ssize_t len;
-  char *packet = daemon->packet;
-  char *filename, *mode, *p, *end, *opt;
-  struct sockaddr_in addr, peer;
-  struct msghdr msg;
-  struct iovec iov;
-  struct ifreq ifr;
-  int is_err = 1, if_index = 0, mtu = 0;
-  struct iname *tmp;
-  struct tftp_transfer *transfer;
-  int port = daemon->start_tftp_port; /* may be zero to use ephemeral port */
-#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
-  int mtuflag = IP_PMTUDISC_DONT;
-#endif
-  
-  union {
-    struct cmsghdr align; /* this ensures alignment */
-#if defined(HAVE_LINUX_NETWORK)
-    char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
-#elif defined(HAVE_SOLARIS_NETWORK)
-    char control[CMSG_SPACE(sizeof(unsigned int))];
-#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
-    char control[CMSG_SPACE(sizeof(struct sockaddr_dl))];
-#endif
-  } control_u; 
-
-  msg.msg_controllen = sizeof(control_u);
-  msg.msg_control = control_u.control;
-  msg.msg_flags = 0;
-  msg.msg_name = &peer;
-  msg.msg_namelen = sizeof(peer);
-  msg.msg_iov = &iov;
-  msg.msg_iovlen = 1;
-
-  iov.iov_base = packet;
-  iov.iov_len = daemon->packet_buff_sz;
-
-  /* we overwrote the buffer... */
-  daemon->srv_save = NULL;
-
-  if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2)
-    return;
-  
-  if (daemon->options & OPT_NOWILD)
-    {
-      addr = listen->iface->addr.in;
-      mtu = listen->iface->mtu;
-    }
-  else
-    {
-      char name[IF_NAMESIZE];
-      struct cmsghdr *cmptr;
-      
-      addr.sin_addr.s_addr = 0;
-      
-#if defined(HAVE_LINUX_NETWORK)
-      for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
-	if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
-	  {
-	    addr.sin_addr = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_spec_dst;
-	    if_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
-	  }
-      
-#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)
-	  if_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
-           
-#endif
-      
-      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, name) == 0))
-	  return;
-     
-      strncpy(name, ifr.ifr_name, IF_NAMESIZE);
-      if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
-	mtu = ifr.ifr_mtu;      
-    }
-  
-  addr.sin_port = htons(port);
-  addr.sin_family = AF_INET;
-#ifdef HAVE_SOCKADDR_SA_LEN
-  addr.sin_len = sizeof(addr);
-#endif
-  
-  if (!(transfer = whine_malloc(sizeof(struct tftp_transfer))))
-    return;
-  
-  if ((transfer->sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
-    {
-      free(transfer);
-      return;
-    }
-  
-  transfer->peer = peer;
-  transfer->timeout = now + 2;
-  transfer->backoff = 1;
-  transfer->block = 1;
-  transfer->blocksize = 512;
-  transfer->offset = 0;
-  transfer->file = NULL;
-  transfer->opt_blocksize = transfer->opt_transize = 0;
-  transfer->netascii = transfer->carrylf = 0;
-
-  /* if we have a nailed-down range, iterate until we find a free one. */
-  while (1)
-    {
-      if (bind(transfer->sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1 ||
-#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
-	  setsockopt(transfer->sockfd, SOL_IP, IP_MTU_DISCOVER, &mtuflag, sizeof(mtuflag)) == -1 ||
-#endif
-	  !fix_fd(transfer->sockfd))
-	{
-	  if (errno == EADDRINUSE && daemon->start_tftp_port != 0)
-	    {
-	      if (++port <= daemon->end_tftp_port)
-		{ 
-		  addr.sin_port = htons(port);
-		  continue;
-		}
-	      my_syslog(MS_TFTP | LOG_ERR, _("unable to get free port for TFTP"));
-	    }
-	  free_transfer(transfer);
-	  return;
-	}
-      break;
-    }
-  
-  p = packet + 2;
-  end = packet + len;
-
-  if (ntohs(*((unsigned short *)packet)) != OP_RRQ ||
-      !(filename = next(&p, end)) ||
-      !(mode = next(&p, end)) ||
-      (strcasecmp(mode, "octet") != 0 && strcasecmp(mode, "netascii") != 0))
-    len = tftp_err(ERR_ILL, packet, _("unsupported request from %s"), inet_ntoa(peer.sin_addr));
-  else
-    {
-      if (strcasecmp(mode, "netascii") == 0)
-	transfer->netascii = 1;
-      
-      while ((opt = next(&p, end)))
-	{
-	  if (strcasecmp(opt, "blksize") == 0)
-	    {
-	      if ((opt = next(&p, end)) &&
-		  !(daemon->options & OPT_TFTP_NOBLOCK))
-		{
-		  transfer->blocksize = atoi(opt);
-		  if (transfer->blocksize < 1)
-		    transfer->blocksize = 1;
-		  if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4)
-		    transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4;
-		  /* 32 bytes for IP, UDP and TFTP headers */
-		  if (mtu != 0 && transfer->blocksize > (unsigned)mtu - 32)
-		    transfer->blocksize = (unsigned)mtu - 32;
-		  transfer->opt_blocksize = 1;
-		  transfer->block = 0;
-		}
-	    }
-	  else if (strcasecmp(opt, "tsize") == 0 && next(&p, end) && !transfer->netascii)
-	    {
-	      transfer->opt_transize = 1;
-	      transfer->block = 0;
-	    }
-	}
-
-      /* cope with backslashes from windows boxen. */
-      while ((p = strchr(filename, '\\')))
-	*p = '/';
-
-      strcpy(daemon->namebuff, "/");
-      if (daemon->tftp_prefix)
-	{
-	  if (daemon->tftp_prefix[0] == '/')
-	    daemon->namebuff[0] = 0;
-	  strncat(daemon->namebuff, daemon->tftp_prefix, (MAXDNAME-1) - strlen(daemon->namebuff));
-	  if (daemon->tftp_prefix[strlen(daemon->tftp_prefix)-1] != '/')
-	    strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
-
-	  if (daemon->options & OPT_TFTP_APREF)
-	    {
-	      size_t oldlen = strlen(daemon->namebuff);
-	      struct stat statbuf;
-	      
-	      strncat(daemon->namebuff, inet_ntoa(peer.sin_addr), (MAXDNAME-1) - strlen(daemon->namebuff));
-	      strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
-	      
-	      /* remove unique-directory if it doesn't exist */
-	      if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode))
-		daemon->namebuff[oldlen] = 0;
-	    }
-		
-	  /* Absolute pathnames OK if they match prefix */
-	  if (filename[0] == '/')
-	    {
-	      if (strstr(filename, daemon->namebuff) == filename)
-		daemon->namebuff[0] = 0;
-	      else
-		filename++;
-	    }
-	}
-      else if (filename[0] == '/')
-	daemon->namebuff[0] = 0;
-      strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
-
-      /* check permissions and open file */
-      if ((transfer->file = check_tftp_fileperm(&len)))
-	{
-	  if ((len = get_block(packet, transfer)) == -1)
-	    len = tftp_err_oops(packet, daemon->namebuff);
-	  else
-	    is_err = 0;
-	}
-    }
-  
-  while (sendto(transfer->sockfd, packet, len, 0, 
-		(struct sockaddr *)&peer, sizeof(peer)) == -1 && errno == EINTR);
-  
-  if (is_err)
-    free_transfer(transfer);
-  else
-    {
-      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;
-    }
-}
- 
-static struct tftp_file *check_tftp_fileperm(ssize_t *len)
-{
-  char *packet = daemon->packet, *namebuff = daemon->namebuff;
-  struct tftp_file *file;
-  struct tftp_transfer *t;
-  uid_t uid = geteuid();
-  struct stat statbuf;
-  int fd = -1;
-
-  /* trick to ban moving out of the subtree */
-  if (daemon->tftp_prefix && strstr(namebuff, "/../"))
-    goto perm;
-  
-  if ((fd = open(namebuff, O_RDONLY)) == -1)
-    {
-      if (errno == ENOENT)
-	{
-	  *len = tftp_err(ERR_FNF, packet, _("file %s not found"), namebuff);
-	  return NULL;
-	}
-      else if (errno == EACCES)
-	goto perm;
-      else
-	goto oops;
-    }
-  
-  /* stat the file descriptor to avoid stat->open races */
-  if (fstat(fd, &statbuf) == -1)
-    goto oops;
-  
-  /* running as root, must be world-readable */
-  if (uid == 0)
-    {
-      if (!(statbuf.st_mode & S_IROTH))
-	goto perm;
-    }
-  /* in secure mode, must be owned by user running dnsmasq */
-  else if ((daemon->options & OPT_TFTP_SECURE) && uid != statbuf.st_uid)
-    goto perm;
-      
-  /* If we're doing many tranfers from the same file, only 
-     open it once this saves lots of file descriptors 
-     when mass-booting a big cluster, for instance. 
-     Be conservative and only share when inode and name match
-     this keeps error messages sane. */
-  for (t = daemon->tftp_trans; t; t = t->next)
-    if (t->file->dev == statbuf.st_dev && 
-	t->file->inode == statbuf.st_ino &&
-	strcmp(t->file->filename, namebuff) == 0)
-      {
-	close(fd);
-	t->file->refcount++;
-	return t->file;
-      }
-  
-  if (!(file = whine_malloc(sizeof(struct tftp_file) + strlen(namebuff) + 1)))
-    {
-      errno = ENOMEM;
-      goto oops;
-    }
-
-  file->fd = fd;
-  file->size = statbuf.st_size;
-  file->dev = statbuf.st_dev;
-  file->inode = statbuf.st_ino;
-  file->refcount = 1;
-  strcpy(file->filename, namebuff);
-  return file;
-  
- perm:
-  errno = EACCES;
-  *len =  tftp_err(ERR_PERM, packet, _("cannot access %s: %s"), namebuff);
-  if (fd != -1)
-    close(fd);
-  return NULL;
-
- oops:
-  *len =  tftp_err_oops(packet, namebuff);
-  if (fd != -1)
-    close(fd);
-  return NULL;
-}
-
-void check_tftp_listeners(fd_set *rset, time_t now)
-{
-  struct tftp_transfer *transfer, *tmp, **up;
-  ssize_t len;
-  
-  struct ack {
-    unsigned short op, block;
-  } *mess = (struct ack *)daemon->packet;
-  
-  /* Check for activity on any existing transfers */
-  for (transfer = daemon->tftp_trans, up = &daemon->tftp_trans; transfer; transfer = tmp)
-    {
-      tmp = transfer->next;
-      
-      if (FD_ISSET(transfer->sockfd, rset))
-	{
-	  /* we overwrote the buffer... */
-	  daemon->srv_save = NULL;
-	  
-	  if ((len = recv(transfer->sockfd, daemon->packet, daemon->packet_buff_sz, 0)) >= (ssize_t)sizeof(struct ack))
-	    {
-	      if (ntohs(mess->op) == OP_ACK && ntohs(mess->block) == (unsigned short)transfer->block) 
-		{
-		  /* Got ack, ensure we take the (re)transmit path */
-		  transfer->timeout = now;
-		  transfer->backoff = 0;
-		  if (transfer->block++ != 0)
-		    transfer->offset += transfer->blocksize - transfer->expansion;
-		}
-	      else if (ntohs(mess->op) == OP_ERR)
-		{
-		  char *p = daemon->packet + sizeof(struct ack);
-		  char *end = daemon->packet + len;
-		  char *err = next(&p, end);
-		  /* Sanitise error message */
-		  if (!err)
-		    err = "";
-		  else
-		    {
-		      char *q, *r;
-		      for (q = r = err; *r; r++)
-			if (isprint((int)*r))
-			  *(q++) = *r;
-		      *q = 0;
-		    }
-		  my_syslog(MS_TFTP | LOG_ERR, _("TFTP error %d %s received from %s"),
-			    (int)ntohs(mess->block), err, 
-			    inet_ntoa(transfer->peer.sin_addr));	
-		  
-		  /* Got err, ensure we take abort */
-		  transfer->timeout = now;
-		  transfer->backoff = 100;
-		}
-	    }
-	}
-      
-      if (difftime(now, transfer->timeout) >= 0.0)
-	{
-	  int endcon = 0;
-
-	  /* timeout, retransmit */
-	  transfer->timeout += 1 + (1<<transfer->backoff);
-	  	  
-	  /* we overwrote the buffer... */
-	  daemon->srv_save = NULL;
-	 
-	  if ((len = get_block(daemon->packet, transfer)) == -1)
-	    {
-	      len = tftp_err_oops(daemon->packet, transfer->file->filename);
-	      endcon = 1;
-	    }
-	  else if (++transfer->backoff > 5)
-	    {
-	      /* don't complain about timeout when we're awaiting the last
-		 ACK, some clients never send it */
-	      if (len != 0)
-		my_syslog(MS_TFTP | LOG_ERR, _("TFTP failed sending %s to %s"), 
-			  transfer->file->filename, inet_ntoa(transfer->peer.sin_addr));
-	      len = 0;
-	    }
-	  
-	  if (len != 0)
-	    while(sendto(transfer->sockfd, daemon->packet, len, 0, 
-			 (struct sockaddr *)&transfer->peer, sizeof(transfer->peer)) == -1 && errno == EINTR);
-	  
-	  if (endcon || len == 0)
-	    {
-	      /* unlink */
-	      *up = tmp;
-	      free_transfer(transfer);
-	      continue;
-	    }
-	}
-
-      up = &transfer->next;
-    }
-}
-
-static void free_transfer(struct tftp_transfer *transfer)
-{
-  close(transfer->sockfd);
-  if (transfer->file && (--transfer->file->refcount) == 0)
-    {
-      close(transfer->file->fd);
-      free(transfer->file);
-    }
-  free(transfer);
-}
-
-static char *next(char **p, char *end)
-{
-  char *ret = *p;
-  size_t len;
-
-  if (*(end-1) != 0 || 
-      *p == end ||
-      (len = strlen(ret)) == 0)
-    return NULL;
-
-  *p += len + 1;
-  return ret;
-}
-
-static ssize_t tftp_err(int err, char *packet, char *message, char *file)
-{
-  struct errmess {
-    unsigned short op, err;
-    char message[];
-  } *mess = (struct errmess *)packet;
-  ssize_t ret = 4;
-  char *errstr = strerror(errno);
- 
-  mess->op = htons(OP_ERR);
-  mess->err = htons(err);
-  ret += (snprintf(mess->message, 500,  message, file, errstr) + 1);
-  my_syslog(MS_TFTP | LOG_ERR, "TFTP %s", mess->message);
-  
-  return  ret;
-}
-
-static ssize_t tftp_err_oops(char *packet, char *file)
-{
-  return tftp_err(ERR_NOTDEF, packet, _("cannot read %s: %s"), file);
-}
-
-/* return -1 for error, zero for done. */
-static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
-{
-  if (transfer->block == 0)
-    {
-      /* send OACK */
-      char *p;
-      struct oackmess {
-	unsigned short op;
-	char data[];
-      } *mess = (struct oackmess *)packet;
-      
-      p = mess->data;
-      mess->op = htons(OP_OACK);
-      if (transfer->opt_blocksize)
-	{
-	  p += (sprintf(p, "blksize") + 1);
-	  p += (sprintf(p, "%d", transfer->blocksize) + 1);
-	}
-      if (transfer->opt_transize)
-	{
-	  p += (sprintf(p,"tsize") + 1);
-	  p += (sprintf(p, "%u", (unsigned int)transfer->file->size) + 1);
-	}
-
-      return p - packet;
-    }
-  else
-    {
-      /* send data packet */
-      struct datamess {
-	unsigned short op, block;
-	unsigned char data[];
-      } *mess = (struct datamess *)packet;
-      
-      size_t size = transfer->file->size - transfer->offset; 
-      
-      if (transfer->offset > transfer->file->size)
-	return 0; /* finished */
-      
-      if (size > transfer->blocksize)
-	size = transfer->blocksize;
-      
-      mess->op = htons(OP_DATA);
-      mess->block = htons((unsigned short)(transfer->block));
-      
-      if (lseek(transfer->file->fd, transfer->offset, SEEK_SET) == (off_t)-1 ||
-	  !read_write(transfer->file->fd, mess->data, size, 1))
-	return -1;
-      
-      transfer->expansion = 0;
-      
-      /* Map '\n' to CR-LF in netascii mode */
-      if (transfer->netascii)
-	{
-	  size_t i;
-	  int newcarrylf;
-
-	  for (i = 0, newcarrylf = 0; i < size; i++)
-	    if (mess->data[i] == '\n' && ( i != 0 || !transfer->carrylf))
-	      {
-		if (size == transfer->blocksize)
-		  {
-		    transfer->expansion++;
-		    if (i == size - 1)
-		      newcarrylf = 1; /* don't expand LF again if it moves to the next block */
-		  }
-		else
-		  size++; /* room in this block */
-	      
-		/* make space and insert CR */
-		memmove(&mess->data[i+1], &mess->data[i], size - (i + 1));
-		mess->data[i] = '\r';
-		
-		i++;
-	      }
-	  transfer->carrylf = newcarrylf;
-	  
-	}
-
-      return size + 4;
-    }
-}
-
-#endif