diff options
-rw-r--r-- | CHANGELOG | 18 | ||||
-rwxr-xr-x | contrib/port-forward/dnsmasq-portforward | 10 | ||||
-rw-r--r-- | man/dnsmasq.8 | 35 | ||||
-rw-r--r-- | src/dnsmasq.c | 9 | ||||
-rw-r--r-- | src/dnsmasq.h | 7 | ||||
-rw-r--r-- | src/helper.c | 449 | ||||
-rw-r--r-- | src/tftp.c | 21 |
7 files changed, 355 insertions, 194 deletions
@@ -24,6 +24,24 @@ version 2.61 Add --host-record. Thanks to Rob Zwissler for the suggestion. + Invoke the DHCP script with action "tftp" when a TFTP file + transfer completes. The size of the file, address to which + it was sent and complete pathname are supplied. Note that + version 2.60 introduced some script incompatibilties + associated with DHCPv6, and this is a further change. To + be safe, scripts should ignore unknown actions, and if + not IPv6-aware, should exit if the environment + variable DNSMASQ_IAID is set. The use-case for this is + to track netboot/install. Suggestion from Shantanu + Gadgil. + + Update contrib/port-forward/dnsmasq-portforward to reflect + the above. + + Set the environment variable DNSMASQ_LOG_DHCP when running + the script id --log-dhcp is in effect, so that script can + taylor their logging verbosity. Suggestion from Malte Forkel. + version 2.60 Fix compilation problem in Mac OS X Lion. Thanks to Olaf diff --git a/contrib/port-forward/dnsmasq-portforward b/contrib/port-forward/dnsmasq-portforward index f9bb857..c2c634f 100755 --- a/contrib/port-forward/dnsmasq-portforward +++ b/contrib/port-forward/dnsmasq-portforward @@ -34,11 +34,21 @@ if [ ${DNSMASQ_OLD_HOSTNAME} ] && [ ${action} = old ] ; then hostname=${DNSMASQ_OLD_HOSTNAME} fi +# IPv6 leases are not our concern. no NAT there! +if [ ${DNSMASQ_IAID} ] ; then + exit 0 +fi + # action init is not relevant, and will only be seen when leasefile-ro is set. if [ ${action} = init ] ; then exit 0 fi +# action tftp is not relevant. +if [ ${action} = tftp ] ; then + exit 0 +fi + if [ ${hostname} ]; then ports=$(sed -n -e "/^${hostname}\ .*/ s/^.* //p" ${PORTSFILE}) diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 index 88609f1..9ebfe31 100644 --- a/man/dnsmasq.8 +++ b/man/dnsmasq.8 @@ -1069,7 +1069,8 @@ re-intialised. The enterprise-id is assigned by IANA, and the uid is a string of hex octets unique to a particular device. .TP .B \-6 --dhcp-script=<path> -Whenever a new DHCP lease is created, or an old one destroyed, the +Whenever a new DHCP lease is created, or an old one destroyed, or a +TFTP file transfer completes, the executable specified by this option is run. <path> must be an absolute pathname, no PATH search occurs. The arguments to the process @@ -1119,6 +1120,8 @@ is known. DNSMASQ_TAGS contains all the tags set during the DHCP transaction, separated by spaces. +DNSMASQ_LOG_DHCP is set if --log-dhcp is in effect. + For IPv4 only: DNSMASQ_CLIENT_ID if the host provided a client-id. @@ -1145,6 +1148,8 @@ only supplied for since these data are not held in dnsmasq's lease database. + + All file descriptors are closed except stdin, stdout and stderr which are open to /dev/null (except in debug mode). @@ -1163,6 +1168,17 @@ all existing leases as they are read from the lease file. Expired leases will be called with "del" and others with "old". When dnsmasq receives a HUP signal, the script will be invoked for existing leases with an "old " event. + + +There are two further actions which may appear as the first argument +to the script, "init" and "tftp". More may be added in the future, so +scripts should be written to ignore unknown actions. "init" is +decsribed below in +.B --leasefile-ro +The "tftp" action is invoked when a TFTP file transfer completes: the +arguments are the file size in bytes, the address to which the file +was sent, and the complete pathname of the file. + .TP .B --dhcp-luascript=<path> Specify a script written in Lua, to be run when leases are created, @@ -1176,11 +1192,13 @@ function, and may provide and .B shutdown functions, which are called, without arguments when dnsmasq starts up -and terminates. +and terminates. It may also provide a +.B tftp +function. The .B lease -method receives the information detailed in +function receives the information detailed in .B --dhcp-script. It gets two arguments, firstly the action, which is a string containing, "add", "old" or "del", and secondly a table of tag value @@ -1197,7 +1215,16 @@ for IPv4, and .B client_duid, ip_address and .B hostname -for IPv6. +for IPv6. + +The +.B tftp +function is called in the same way as the lease function, and the +table holds the tags +.B destination_address, +.B file_name +and +.B file_size. .TP .B --dhcp-scriptuser Specify the user as which to run the lease-change script or Lua script. This defaults to root, but can be changed to another user using this flag. diff --git a/src/dnsmasq.c b/src/dnsmasq.c index 531e0b0..efe63d1 100644 --- a/src/dnsmasq.c +++ b/src/dnsmasq.c @@ -721,6 +721,10 @@ int main (int argc, char **argv) # ifdef HAVE_SCRIPT while (helper_buf_empty() && do_script_run(now)); +# ifdef HAVE_TFTP + while (helper_buf_empty() && do_tftp_script_run()); +# endif + if (!helper_buf_empty()) { FD_SET(daemon->helperfd, &wset); @@ -729,6 +733,11 @@ int main (int argc, char **argv) # else /* need this for other side-effects */ while (do_script_run(now)); + +# ifdef HAVE_TFTP + while (do_tftp_script_run()); +# endif + # endif #endif diff --git a/src/dnsmasq.h b/src/dnsmasq.h index 06f1549..f2a6f36 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -458,6 +458,7 @@ struct frec { #define ACTION_OLD_HOSTNAME 2 #define ACTION_OLD 3 #define ACTION_ADD 4 +#define ACTION_TFTP 5 #define LEASE_NEW 1 /* newly created */ #define LEASE_CHANGED 2 /* modified */ @@ -803,7 +804,7 @@ extern struct daemon { #endif /* TFTP stuff */ - struct tftp_transfer *tftp_trans; + struct tftp_transfer *tftp_trans, *tftp_done_trans; /* utility string buffer, hold max sized IP address as string */ char *addrbuff; @@ -1040,6 +1041,9 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd); void helper_write(void); void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t now); +#ifdef HAVE_TFTP +void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer); +#endif int helper_buf_empty(void); #endif @@ -1047,6 +1051,7 @@ int helper_buf_empty(void); #ifdef HAVE_TFTP void tftp_request(struct listener *listen, time_t now); void check_tftp_listeners(fd_set *rset, time_t now); +int do_tftp_script_run(void); #endif /* conntrack.c */ diff --git a/src/helper.c b/src/helper.c index 135111d..5c07f05 100644 --- a/src/helper.c +++ b/src/helper.c @@ -192,18 +192,24 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd) #endif _exit(0); } - + + is6 = !!(data.flags & (LEASE_TA | LEASE_NA)); + if (data.action == ACTION_DEL) action_str = "del"; else if (data.action == ACTION_ADD) action_str = "add"; else if (data.action == ACTION_OLD || data.action == ACTION_OLD_HOSTNAME) action_str = "old"; + else if (data.action == ACTION_TFTP) + { + action_str = "tftp"; + is6 = (data.flags != AF_INET); + } else continue; - is6 = !!(data.flags & (LEASE_TA | LEASE_NA)); - + if (!is6) { /* stringify MAC into dhcp_buff */ @@ -271,13 +277,16 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd) char *dot; hostname = (char *)buf; hostname[data.hostname_len - 1] = 0; - if (!legal_hostname(hostname)) - hostname = NULL; - else if ((dot = strchr(hostname, '.'))) + if (data.action != ACTION_TFTP) { - domain = dot+1; - *dot = 0; - } + if (!legal_hostname(hostname)) + hostname = NULL; + else if ((dot = strchr(hostname, '.'))) + { + domain = dot+1; + *dot = 0; + } + } } extradata = buf + data.hostname_len; @@ -289,116 +298,141 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd) inet_ntop(AF_INET6, &data.hwaddr, daemon->addrbuff, ADDRSTRLEN); #endif + /* file length */ + if (data.action == ACTION_TFTP) + sprintf(daemon->dhcp_buff, "%u", data.hwaddr_len); + #ifdef HAVE_LUASCRIPT if (daemon->luascript) { - lua_getglobal(lua, "lease"); /* function to call */ - lua_pushstring(lua, action_str); /* arg1 - action */ - lua_newtable(lua); /* arg2 - data table */ - - if (is6) + if (data.action == ACTION_TFTP) { - lua_pushstring(lua, daemon->dhcp_buff); - lua_setfield(lua, -2, "client_duid"); - lua_pushstring(lua, daemon->packet); - lua_setfield(lua, -2, "server_duid"); - lua_pushstring(lua, daemon->dhcp_buff3); - lua_setfield(lua, -2, "iaid"); - } - - if (!is6 && data.clid_len != 0) - { - lua_pushstring(lua, daemon->packet); - lua_setfield(lua, -2, "client_id"); + lua_getglobal(lua, "tftp"); + if (lua_type(lua, -1) != LUA_TFUNCTION) + lua_pop(lua, 1); /* tftp function optional */ + else + { + lua_pushstring(lua, action_str); /* arg1 - action */ + lua_newtable(lua); /* arg2 - data table */ + lua_pushstring(lua, daemon->addrbuff); + lua_setfield(lua, -2, "destination_address"); + lua_pushstring(lua, hostname); + lua_setfield(lua, -2, "file_name"); + lua_pushstring(lua, daemon->dhcp_buff); + lua_setfield(lua, -2, "file_size"); + lua_call(lua, 2, 0); /* pass 2 values, expect 0 */ + } } - - if (strlen(data.interface) != 0) + else { - lua_pushstring(lua, data.interface); - lua_setfield(lua, -2, "interface"); - } - + lua_getglobal(lua, "lease"); /* function to call */ + lua_pushstring(lua, action_str); /* arg1 - action */ + lua_newtable(lua); /* arg2 - data table */ + + if (is6) + { + lua_pushstring(lua, daemon->dhcp_buff); + lua_setfield(lua, -2, "client_duid"); + lua_pushstring(lua, daemon->packet); + lua_setfield(lua, -2, "server_duid"); + lua_pushstring(lua, daemon->dhcp_buff3); + lua_setfield(lua, -2, "iaid"); + } + + if (!is6 && data.clid_len != 0) + { + lua_pushstring(lua, daemon->packet); + lua_setfield(lua, -2, "client_id"); + } + + if (strlen(data.interface) != 0) + { + lua_pushstring(lua, data.interface); + lua_setfield(lua, -2, "interface"); + } + #ifdef HAVE_BROKEN_RTC - lua_pushnumber(lua, data.length); - lua_setfield(lua, -2, "lease_length"); + lua_pushnumber(lua, data.length); + lua_setfield(lua, -2, "lease_length"); #else - lua_pushnumber(lua, data.expires); - lua_setfield(lua, -2, "lease_expires"); + lua_pushnumber(lua, data.expires); + lua_setfield(lua, -2, "lease_expires"); #endif - - if (hostname) - { - lua_pushstring(lua, hostname); - lua_setfield(lua, -2, "hostname"); - } - - if (domain) - { - lua_pushstring(lua, domain); - lua_setfield(lua, -2, "domain"); - } - - end = extradata + data.ed_len; - buf = extradata; - - if (!is6) - buf = grab_extradata_lua(buf, end, "vendor_class"); + + if (hostname) + { + lua_pushstring(lua, hostname); + lua_setfield(lua, -2, "hostname"); + } + + if (domain) + { + lua_pushstring(lua, domain); + lua_setfield(lua, -2, "domain"); + } + + end = extradata + data.ed_len; + buf = extradata; + + if (!is6) + buf = grab_extradata_lua(buf, end, "vendor_class"); #ifdef HAVE_DHCP6 - else - for (i = 0; i < data.hwaddr_len; i++) - { - sprintf(daemon->dhcp_buff2, "vendor_class%i", i); - buf = grab_extradata_lua(buf, end, daemon->dhcp_buff2); - } + else + for (i = 0; i < data.hwaddr_len; i++) + { + sprintf(daemon->dhcp_buff2, "vendor_class%i", i); + buf = grab_extradata_lua(buf, end, daemon->dhcp_buff2); + } #endif - - buf = grab_extradata_lua(buf, end, "supplied_hostname"); - - if (!is6) - { - buf = grab_extradata_lua(buf, end, "cpewan_oui"); - buf = grab_extradata_lua(buf, end, "cpewan_serial"); - buf = grab_extradata_lua(buf, end, "cpewan_class"); - } - - buf = grab_extradata_lua(buf, end, "tags"); - - if (is6) - buf = grab_extradata_lua(buf, end, "relay_address"); - else if (data.giaddr.s_addr != 0) - { - lua_pushstring(lua, inet_ntoa(data.giaddr)); - lua_setfield(lua, -2, "relay_address"); - } - - for (i = 0; buf; i++) - { - sprintf(daemon->dhcp_buff2, "user_class%i", i); - buf = grab_extradata_lua(buf, end, daemon->dhcp_buff2); - } - - if (data.action != ACTION_DEL && data.remaining_time != 0) - { - lua_pushnumber(lua, data.remaining_time); - lua_setfield(lua, -2, "time_remaining"); - } - - if (data.action == ACTION_OLD_HOSTNAME && hostname) - { - lua_pushstring(lua, hostname); - lua_setfield(lua, -2, "old_hostname"); - } - - if (!is6) - { - lua_pushstring(lua, daemon->dhcp_buff); - lua_setfield(lua, -2, "mac_address"); + + buf = grab_extradata_lua(buf, end, "supplied_hostname"); + + if (!is6) + { + buf = grab_extradata_lua(buf, end, "cpewan_oui"); + buf = grab_extradata_lua(buf, end, "cpewan_serial"); + buf = grab_extradata_lua(buf, end, "cpewan_class"); + } + + buf = grab_extradata_lua(buf, end, "tags"); + + if (is6) + buf = grab_extradata_lua(buf, end, "relay_address"); + else if (data.giaddr.s_addr != 0) + { + lua_pushstring(lua, inet_ntoa(data.giaddr)); + lua_setfield(lua, -2, "relay_address"); + } + + for (i = 0; buf; i++) + { + sprintf(daemon->dhcp_buff2, "user_class%i", i); + buf = grab_extradata_lua(buf, end, daemon->dhcp_buff2); + } + + if (data.action != ACTION_DEL && data.remaining_time != 0) + { + lua_pushnumber(lua, data.remaining_time); + lua_setfield(lua, -2, "time_remaining"); + } + + if (data.action == ACTION_OLD_HOSTNAME && hostname) + { + lua_pushstring(lua, hostname); + lua_setfield(lua, -2, "old_hostname"); + } + + if (!is6) + { + lua_pushstring(lua, daemon->dhcp_buff); + lua_setfield(lua, -2, "mac_address"); + } + + lua_pushstring(lua, daemon->addrbuff); + lua_setfield(lua, -2, "ip_address"); + + lua_call(lua, 2, 0); /* pass 2 values, expect 0 */ } - - lua_pushstring(lua, daemon->addrbuff); - lua_setfield(lua, -2, "ip_address"); - - lua_call(lua, 2, 0); /* pass 2 values, expect 0 */ } #endif @@ -439,81 +473,87 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd) continue; } - if (is6) + if (data.action != ACTION_TFTP) { - my_setenv("DNSMASQ_IAID", daemon->dhcp_buff3, &err); - my_setenv("DNSMASQ_SERVER_DUID", daemon->packet, &err); - } - - if (!is6 && data.clid_len != 0) - my_setenv("DNSMASQ_CLIENT_ID", daemon->packet, &err); - - if (strlen(data.interface) != 0) - my_setenv("DNSMASQ_INTERFACE", data.interface, &err); - + if (is6) + { + my_setenv("DNSMASQ_IAID", daemon->dhcp_buff3, &err); + my_setenv("DNSMASQ_SERVER_DUID", daemon->packet, &err); + } + + if (!is6 && data.clid_len != 0) + my_setenv("DNSMASQ_CLIENT_ID", daemon->packet, &err); + + if (strlen(data.interface) != 0) + my_setenv("DNSMASQ_INTERFACE", data.interface, &err); + #ifdef HAVE_BROKEN_RTC - my_setenv("DNSMASQ_LEASE_LENGTH", daemon->dhcp_buff2, &err); + my_setenv("DNSMASQ_LEASE_LENGTH", daemon->dhcp_buff2, &err); #else - my_setenv("DNSMASQ_LEASE_EXPIRES", daemon->dhcp_buff2, &err); + my_setenv("DNSMASQ_LEASE_EXPIRES", daemon->dhcp_buff2, &err); #endif - - if (domain) - my_setenv("DNSMASQ_DOMAIN", domain, &err); - - end = extradata + data.ed_len; - buf = extradata; - - if (!is6) - buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS", &err); + + if (domain) + my_setenv("DNSMASQ_DOMAIN", domain, &err); + + end = extradata + data.ed_len; + buf = extradata; + + if (!is6) + buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS", &err); #ifdef HAVE_DHCP6 - else - { - if (data.hwaddr_len != 0) + else { - buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS_ID", &err); - for (i = 0; i < data.hwaddr_len - 1; i++) + if (data.hwaddr_len != 0) { - sprintf(daemon->dhcp_buff2, "DNSMASQ_VENDOR_CLASS%i", i); - buf = grab_extradata(buf, end, daemon->dhcp_buff2, &err); + buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS_ID", &err); + for (i = 0; i < data.hwaddr_len - 1; i++) + { + sprintf(daemon->dhcp_buff2, "DNSMASQ_VENDOR_CLASS%i", i); + buf = grab_extradata(buf, end, daemon->dhcp_buff2, &err); + } } } - } #endif - - buf = grab_extradata(buf, end, "DNSMASQ_SUPPLIED_HOSTNAME", &err); - - if (!is6) - { - buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_OUI", &err); - buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_SERIAL", &err); - buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_CLASS", &err); - } - - buf = grab_extradata(buf, end, "DNSMASQ_TAGS", &err); - - if (is6) - buf = grab_extradata(buf, end, "DNSMASQ_RELAY_ADDRESS", &err); - else if (data.giaddr.s_addr != 0) - my_setenv("DNSMASQ_RELAY_ADDRESS", inet_ntoa(data.giaddr), &err); - - for (i = 0; buf; i++) - { - sprintf(daemon->dhcp_buff2, "DNSMASQ_USER_CLASS%i", i); - buf = grab_extradata(buf, end, daemon->dhcp_buff2, &err); - } - - if (data.action != ACTION_DEL && data.remaining_time != 0) - { - sprintf(daemon->dhcp_buff2, "%u", data.remaining_time); - my_setenv("DNSMASQ_TIME_REMAINING", daemon->dhcp_buff2, &err); - } - - if (data.action == ACTION_OLD_HOSTNAME && hostname) - { - my_setenv("DNSMASQ_OLD_HOSTNAME", hostname, &err); - hostname = NULL; + + buf = grab_extradata(buf, end, "DNSMASQ_SUPPLIED_HOSTNAME", &err); + + if (!is6) + { + buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_OUI", &err); + buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_SERIAL", &err); + buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_CLASS", &err); + } + + buf = grab_extradata(buf, end, "DNSMASQ_TAGS", &err); + + if (is6) + buf = grab_extradata(buf, end, "DNSMASQ_RELAY_ADDRESS", &err); + else if (data.giaddr.s_addr != 0) + my_setenv("DNSMASQ_RELAY_ADDRESS", inet_ntoa(data.giaddr), &err); + + for (i = 0; buf; i++) + { + sprintf(daemon->dhcp_buff2, "DNSMASQ_USER_CLASS%i", i); + buf = grab_extradata(buf, end, daemon->dhcp_buff2, &err); + } + + if (data.action != ACTION_DEL && data.remaining_time != 0) + { + sprintf(daemon->dhcp_buff2, "%u", data.remaining_time); + my_setenv("DNSMASQ_TIME_REMAINING", daemon->dhcp_buff2, &err); + } + + if (data.action == ACTION_OLD_HOSTNAME && hostname) + { + my_setenv("DNSMASQ_OLD_HOSTNAME", hostname, &err); + hostname = NULL; + } } + if (option_bool(OPT_LOG_OPTS)) + my_setenv("DNSMASQ_LOG_DHCP", "1", &err); + /* we need to have the event_fd around if exec fails */ if ((i = fcntl(event_fd, F_GETFD)) != -1) fcntl(event_fd, F_SETFD, i | FD_CLOEXEC); @@ -584,11 +624,29 @@ static unsigned char *grab_extradata_lua(unsigned char *buf, unsigned char *end, } #endif +static void buff_alloc(size_t size) +{ + if (size > buf_size) + { + struct script_data *new; + + /* start with reasonable size, will almost never need extending. */ + if (size < sizeof(struct script_data) + 200) + size = sizeof(struct script_data) + 200; + + if (!(new = whine_malloc(size))) + return; + if (buf) + free(buf); + buf = new; + buf_size = size; + } +} + /* pack up lease data into a buffer */ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t now) { unsigned char *p; - size_t size; unsigned int hostname_len = 0, clid_len = 0, ed_len = 0; int fd = daemon->dhcpfd; @@ -608,23 +666,7 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n if (hostname) hostname_len = strlen(hostname) + 1; - size = sizeof(struct script_data) + clid_len + ed_len + hostname_len; - - if (size > buf_size) - { - struct script_data *new; - - /* start with reasonable size, will almost never need extending. */ - if (size < sizeof(struct script_data) + 200) - size = sizeof(struct script_data) + 200; - - if (!(new = whine_malloc(size))) - return; - if (buf) - free(buf); - buf = new; - buf_size = size; - } + buff_alloc(sizeof(struct script_data) + clid_len + ed_len + hostname_len); buf->action = action; buf->flags = lease->flags; @@ -669,6 +711,37 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n bytes_in_buf = p - (unsigned char *)buf; } +#ifdef HAVE_TFTP +/* This nastily re-uses DHCP-fields for TFTP stuff */ +void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer) +{ + unsigned int filename_len; + + /* no script */ + if (daemon->helperfd == -1) + return; + + filename_len = strlen(filename) + 1; + buff_alloc(sizeof(struct script_data) + filename_len); + memset(buf, 0, sizeof(struct script_data)); + + buf->action = ACTION_TFTP; + buf->hostname_len = filename_len; + buf->hwaddr_len = file_len; + + if ((buf->flags = peer->sa.sa_family) == AF_INET) + buf->addr = peer->in.sin_addr; +#ifdef HAVE_IPV6 + else + memcpy(buf->hwaddr, &peer->in6.sin6_addr, IN6ADDRSZ); +#endif + + memcpy((unsigned char *)(buf+1), filename, filename_len); + + bytes_in_buf = sizeof(struct script_data) + filename_len; +} +#endif + int helper_buf_empty(void) { return bytes_in_buf == 0; @@ -571,7 +571,9 @@ void check_tftp_listeners(fd_set *rset, time_t now) my_syslog(MS_TFTP | LOG_INFO, _("sent %s to %s"), transfer->file->filename, daemon->addrbuff); /* unlink */ *up = tmp; - free_transfer(transfer); + /* put on queue to be sent to script and deleted */ + transfer->next = daemon->tftp_done_trans; + daemon->tftp_done_trans = transfer; continue; } } @@ -709,4 +711,21 @@ static ssize_t get_block(char *packet, struct tftp_transfer *transfer) } } + +int do_tftp_script_run(void) +{ + struct tftp_transfer *transfer; + + if ((transfer = daemon->tftp_done_trans)) + { + daemon->tftp_done_trans = transfer->next; +#ifdef HAVE_SCRIPT + queue_tftp(transfer->file->size, transfer->file->filename, &transfer->peer); +#endif + free_transfer(transfer); + return 1; + } + + return 0; +} #endif |