diff options
author | Erik Kline <ek@google.com> | 2017-05-24 09:46:37 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-05-24 09:46:37 +0000 |
commit | a21366fc0529c748068fdd4bfcab48723e2a5f99 (patch) | |
tree | 393316bed9b71d2cf78d8b69cc68021cc2a82d20 | |
parent | 337e7e3a369dd09e37ddf2df37d4fb03f92db49f (diff) | |
parent | d37f567618c3f5266d82b971a505f5a214a03f34 (diff) | |
download | dnsmasq-oreo-dr1-dev.tar.gz |
Merge "Remove some unused TFTP and DBUS support" am: 00d11a4477 am: c660bc5375 am: 71fa6b0bfboreo-dr1-dev
am: d37f567618
Change-Id: I960366fcca40f86e05929cffa853294dec18a1e7
-rwxr-xr-x | dbus/DBus-interface | 131 | ||||
-rwxr-xr-x | dbus/dnsmasq.conf | 14 | ||||
-rw-r--r-- | src/Android.mk | 6 | ||||
-rwxr-xr-x | src/config.h | 21 | ||||
-rwxr-xr-x | src/dbus.c | 436 | ||||
-rwxr-xr-x | src/dnsmasq.c | 147 | ||||
-rwxr-xr-x | src/dnsmasq.h | 50 | ||||
-rwxr-xr-x | src/lease.c | 14 | ||||
-rwxr-xr-x | src/network.c | 60 | ||||
-rwxr-xr-x | src/option.c | 34 | ||||
-rwxr-xr-x | src/tftp.c | 600 |
11 files changed, 15 insertions, 1498 deletions
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 @@ LOCAL_PATH := $(call my-dir) ######################### 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 @@ HAVE_BROKEN_RTC 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_ARC4RANDOM 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 @@ NOTES: /* 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 @@ static char *compile_opts = #ifdef NO_FORK "no-MMU " #endif -#ifndef HAVE_DBUS -"no-" -#endif -"DBus " #ifndef LOCALEDIR "no-" #endif @@ -46,12 +42,9 @@ static char *compile_opts = #endif "DHCP " #if defined(HAVE_DHCP) && !defined(HAVE_SCRIPT) -"no-scripts " -#endif -#ifndef HAVE_TFTP -"no-" +"no-scripts" #endif -"TFTP"; +""; @@ -145,11 +138,6 @@ int main (int argc, char **argv) } #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 @@ int main (int argc, char **argv) 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 @@ int main (int argc, char **argv) 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 @@ int main (int argc, char **argv) } #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 @@ int main (int argc, char **argv) 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 @@ int main (int argc, char **argv) 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 @@ int main (int argc, char **argv) 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 @@ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp) 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 @@ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp) 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 @@ static void check_dns_listeners(fd_set *set, time_t now) { 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 @@ int icmp_ping(struct in_addr addr) /* 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 @@ int icmp_ping(struct in_addr addr) 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 irec { }; 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 { 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 @@ extern struct daemon { 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 @@ extern struct daemon { 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 @@ void send_via_bpf(struct dhcp_packet *mess, size_t len, /* 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 @@ void queue_script(int action, struct dhcp_lease *lease, 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 @@ int do_script_run(time_t now) { 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 @@ int do_script_run(time_t now) #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 @@ int do_script_run(time_t now) 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 @@ static int create_ipv6_listener(struct listener **link, int port) 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 @@ struct listener *create_wildcard_listeners(void) 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 @@ struct listener *create_wildcard_listeners(void) } } #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 @@ void create_bound_listener(struct listener **listeners, struct irec *iface) 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 @@ void create_bound_listener(struct listener **listeners, struct irec *iface) 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 @@ int delete_listener(struct listener **l) 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 @@ struct listener *create_bound_listeners(void) 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 @@ struct listener *create_bound_listeners(void) 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 @@ static void do_usage(void) { '*', EDNS_PKTSZ }, { '&', MAXLEASES }, { '!', FTABSIZ }, - { '#', TFTP_MAX_CONNECTIONS }, { '\0', 0 } }; @@ -1585,33 +1584,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest) 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 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest) { 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 @@ void read_opts(int argc, char **argv, char *compile_opts) 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 |