Hello community, here is the log from the commit of package atftp.3860 for openSUSE:13.2:Update checked in at 2015-07-02 09:35:19 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:13.2:Update/atftp.3860 (Old) and /work/SRC/openSUSE:13.2:Update/.atftp.3860.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "atftp.3860" Changes: -------- New Changes file: --- /dev/null 2015-06-25 09:04:34.320025005 +0200 +++ /work/SRC/openSUSE:13.2:Update/.atftp.3860.new/atftp.changes 2015-07-02 09:35:20.000000000 +0200 @@ -0,0 +1,386 @@ +------------------------------------------------------------------- +Mon Jun 15 13:19:22 UTC 2015 - mpluskal@suse.com + +- Use ATFTPD_BIND_ADDRESSES in init script (boo#921219) +- Move autoreconf back to %buils as it causes issues with quilt + +------------------------------------------------------------------- +Mon Jun 8 07:39:43 UTC 2015 - schwab@suse.de + +- Force gnu89 inline semantics + +------------------------------------------------------------------- +Tue May 26 08:19:21 UTC 2015 - mpluskal@suse.com + +- Move autoreconf to %prep section as it better fits there + +------------------------------------------------------------------- +Sun May 24 21:24:18 UTC 2015 - mpluskal@suse.com + +- Fix atftpd.socket (boo#932161) + +------------------------------------------------------------------- +Wed Mar 18 15:23:17 UTC 2015 - mpluskal@suse.com + +- Do not install service and socket file as executable + * change to 0644 +- Cleanup spec file with spec-cleaner + +------------------------------------------------------------------- +Mon Feb 16 13:06:57 UTC 2015 - p.drouand@gmail.com + +- Add systemd support for openSUSE >= 12.1 + +------------------------------------------------------------------- +Tue Nov 12 20:41:45 UTC 2013 - chris@computersalat.de + +- rebase patches (p0) +- rename atftpd.init.d to atftpd.init +- fix spec + * remove ghost /var/run/atftp (created by init) + +------------------------------------------------------------------- +Thu Feb 7 13:05:52 UTC 2013 - vcizek@suse.com + +- create capabilites provided by both tftp and atftp + (bnc#801481 or bnc#725378) + +------------------------------------------------------------------- +Thu Jan 3 13:28:02 UTC 2013 - vcizek@suse.com + +- change ownership of /srv/tftpboot, because atftpd running as + tftp:tftp can't write to that directory +- create pid directory on service start +- manpage changes: + * substitute /tftpboot with /srv/tftpboot + * default user is now tftp:tftp + * added patches: + atftp-0.7-default_user_man.patch + atftp-0.7-default_dir_man.patch + +------------------------------------------------------------------- +Mon Oct 8 08:49:53 UTC 2012 - vcizek@suse.com + +- use Vladimir Nadvornik's heuristic for packet retransmission + by default (see bnc#774376) + The RFC1350 compliant behaviour stays optional. + (added atftp-0.7-ack_heuristic.patch) +- merged the two sorcerer's apprentice syndrome patches to one + (removed atftp-0.7-prevent-sas.patch) + +------------------------------------------------------------------- +Tue Sep 11 13:01:20 UTC 2012 - vcizek@suse.com + +- added rules for SuSEfirewall2 (bnc#729793) + +------------------------------------------------------------------- +Tue Sep 11 12:47:04 UTC 2012 - vcizek@suse.com + +- use the "su" logrotate directive (bnc#677335) + +------------------------------------------------------------------- +Wed Sep 5 14:10:03 UTC 2012 - vcizek@suse.com + +- prevent the sorcerer's apprentice syndrome situation only when + explicitly specified by the user (bnc#774376) + (added a new command line option --prevent-sas to turn it on) + +------------------------------------------------------------------- +Wed Jan 11 15:27:36 UTC 2012 - vcizek@suse.com + +- fix a race condition where two server threads pick up a single + client, which causes the transported file being overwritten + (bnc#599856) + +------------------------------------------------------------------- +Mon Jan 2 17:28:19 UTC 2012 - vcizek@suse.cz + +- added autoconf as BuildRequires + +------------------------------------------------------------------- +Thu Dec 1 11:20:12 UTC 2011 - coolo@suse.com + +- add automake as buildrequire to avoid implicit dependency + +------------------------------------------------------------------- +Wed Nov 9 15:13:18 UTC 2011 - vcizek@suse.com + +- licence in spdx format + +------------------------------------------------------------------- +Thu Nov 3 16:56:46 UTC 2011 - vcizek@suse.com + +- fixed the "Sorcerer's Apprentice Syndrome" bug + (bnc#727843) + +------------------------------------------------------------------- +Sat Sep 17 13:28:52 UTC 2011 - jengelh@medozas.de + +- Remove redundant tags/sections from specfile +- Use %_smp_mflags for parallel build + +------------------------------------------------------------------- +Tue Sep 6 11:55:01 UTC 2011 - vcizek@suse.com + +- added missing PreReq: pwdutils (bnc#683140) + +------------------------------------------------------------------- +Fri Oct 29 23:18:57 UTC 2010 - chris@computersalat.de + +- cleanup spec + o RPM_BUILD_ROOT vs buildroot +- fix pre + o no check before addding group/user (darix) +- fix files + o provide /srv/tftpboot +- modify sysconfig + o provide defaults (darix) + +------------------------------------------------------------------- +Wed Oct 13 21:28:56 UTC 2010 - chris@computersalat.de + +- modified init/sysconfig file + o set defaults in init file +- added default group/user tftp:tftp (bnc#472282) +- added /srv/tftpboot as default ATFTPD_DIRECTORY (bnc#248008,507011) +- added logrotate script + o --logfile /var/log/atftpd/atftp.log +- added missing README.MCAST, README.PCRE +- some rpmlint stuff + o fixed missing-dependency-to-logrotate + o fixed init non-remote_fs-dependency + o fixed init no-reload-entry + o fixed non-conffile-in-etc + +------------------------------------------------------------------- +Wed Sep 22 06:39:40 UTC 2010 - cristian.rodriguez@opensuse.org + +- add missing pcre-devel to build Requires (bnc#537425) + +------------------------------------------------------------------- +Fri Sep 12 16:27:04 CEST 2008 - mrueckert@suse.de + +- add atftpd-0.7_circumvent_tftp_size_restrictions.patch: + allow block counts higher than 65536 (Fate#303031) +- replace network with remote_fs in the init script dependencies + +------------------------------------------------------------------- +Fri Aug 22 15:14:00 CEST 2008 - ro@suse.de + +- change fillup_and_insserv to fillup_only (not active by default) + +------------------------------------------------------------------- +Thu Apr 3 15:57:09 CEST 2008 - mrueckert@suse.de + +- added atftpd-0.7_unprotected_assignments_crash.patch: (bnc#291884) + under high load atftpd dies as data access wasnt always protected + with a mutex. + +------------------------------------------------------------------- +Thu Jun 21 15:37:53 CEST 2007 - adrian@suse.de + +- fix changelog entry order + +------------------------------------------------------------------- +Mon Jan 22 18:33:44 CET 2007 - mrueckert@suse.de + +- added atftp-0.7_bug-213384_OPT_NUMBER.patch: + "atftpd incorrectly sends OACK (option acknowledge) packets" + (#213384,#80441) + +------------------------------------------------------------------- +Mon Jul 31 16:16:43 CEST 2006 - mrueckert@suse.de + +- added /var/run/atftpd/ (0755,nobody,nogroup): + at ftp can finally create pid files + the default pid file for a single instance will be + /var/run/atftpd/pid ++++ 189 more lines (skipped) ++++ between /dev/null ++++ and /work/SRC/openSUSE:13.2:Update/.atftp.3860.new/atftp.changes New: ---- atftp-0.7-ack_heuristic.patch atftp-0.7-default_dir_man.patch atftp-0.7-default_user_man.patch atftp-0.7-server_receive_race.patch atftp-0.7-sorcerers_apprentice.patch atftp-0.7.dif atftp-0.7.tar.bz2 atftp-0.7_bug-213384_OPT_NUMBER.patch atftp-0.7_compiler_warnings.patch atftp-0.7_sol_ip.patch atftp-0.7_thread_crash.patch atftp-CLK_TCK.diff atftp.changes atftp.fw atftp.spec atftpd-0.7_circumvent_tftp_size_restrictions.patch atftpd-0.7_unprotected_assignments_crash.patch atftpd.init atftpd.logrotate atftpd.service atftpd.socket atftpd.sysconfig ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ atftp.spec ++++++ # # spec file for package atftp # # Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed # upon. The license for this file, and modifications and additions to the # file, is the same license as for the pristine package itself (unless the # license for the pristine package is not an Open Source License, in which # case the license is the MIT License). An "Open Source License" is a # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. # Please submit bugfixes or comments via http://bugs.opensuse.org/ # # %define _fwdefdir %{_sysconfdir}/sysconfig/SuSEfirewall2.d/services %define pkg_version 0.7 Name: atftp Version: 0.7.0 Release: 0 Summary: Advanced TFTP Server and Client License: GPL-2.0+ Group: System/Daemons Url: ftp://ftp.mamalinux.com/pub/atftp/ Source: %{name}-%{pkg_version}.tar.bz2 Source1: atftpd.init Source2: atftpd.sysconfig Source3: atftpd.logrotate Source4: atftp.fw Source5: atftpd.service Source6: atftpd.socket Patch1: atftp-0.7.dif Patch2: atftp-CLK_TCK.diff Patch3: atftp-0.7_compiler_warnings.patch Patch4: atftp-0.7_thread_crash.patch Patch5: atftp-0.7_sol_ip.patch Patch6: atftp-0.7_bug-213384_OPT_NUMBER.patch Patch7: atftpd-0.7_unprotected_assignments_crash.patch Patch8: atftpd-0.7_circumvent_tftp_size_restrictions.patch # PATCH-FIX-SUSE sorcerer's apprentice syndrom (bnc#727843) Patch9: atftp-0.7-sorcerers_apprentice.patch # PATCH-FIX-SUSE server receive thread race (bnc#599856) Patch10: atftp-0.7-server_receive_race.patch # PATCH-FIX-SUSE drop one duplicated ACK each round (bnc#774376) Patch12: atftp-0.7-ack_heuristic.patch Patch13: atftp-0.7-default_user_man.patch # PATCH-FIX-SUSE update default directory in man (bnc#507011) Patch14: atftp-0.7-default_dir_man.patch BuildRequires: autoconf BuildRequires: automake BuildRequires: pcre-devel BuildRequires: readline-devel BuildRequires: tcpd-devel Requires(pre): %fillup_prereq Requires(pre): pwdutils Recommends: logrotate Conflicts: tftp Provides: tftp(client) Provides: tftp(server) BuildRoot: %{_tmppath}/%{name}-%{version}-build %if 0%{?suse_version} >= 1210 BuildRequires: systemd-rpm-macros %{?systemd_requires} %else Requires(pre): %insserv_prereq %endif %description atftp stands for Advanced Trivial File Transfer Protocol. It is called "advanced", in contrast to others TFTP servers, for two reasons. First, it is intended to be fully compliant with all related RFCs. This includes RFC1350, RFC2090, RFC2347, RFC2348, and RFC2349. Second, atftp is intended for serving boot files to large clusters. It is multithreaded and will eventually support multicast, allowing faster boot of hundreds of machines simultaneously. %prep %setup -q -n %{name}-%{pkg_version} %patch1 %patch2 %patch3 %patch4 %patch5 %patch6 %patch7 %patch8 %patch9 %patch10 %patch12 %patch13 %patch14 %build autoreconf -fi CFLAGS="%optflags -fgnu89-inline" %configure make %{?_smp_mflags} %install make DESTDIR=%{buildroot} install %{?_smp_mflags} # SuSE rc %if 0%{?suse_version} >= 1210 install -D -m 0644 %{SOURCE5} %{buildroot}/%{_unitdir}/atftpd.service install -D -m 0644 %{SOURCE6} %{buildroot}/%{_unitdir}/atftpd.socket ln -s %{_sbindir}/service %{buildroot}%{_sbindir}/rcatftpd %else install -D -m 0755 %{SOURCE1} %{buildroot}%{_initddir}/atftpd ln -s -f ../..%{_initddir}/atftpd %{buildroot}%{_sbindir}/rcatftpd %endif install -D -m 0644 %{SOURCE2} %{buildroot}%{_localstatedir}/adm/fillup-templates/sysconfig.atftpd install -D -m 0644 %{SOURCE3} %{buildroot}%{_sysconfdir}/logrotate.d/%{name} mkdir -p %{buildroot}/%{_fwdefdir} install -m 0644 %{SOURCE4} %{buildroot}/%{_fwdefdir}/atftp install -d -m 0750 %{buildroot}/srv/tftpboot install -d -m 0750 %{buildroot}%{_localstatedir}/log/atftpd %pre # This group/user is shared with tftp, so please # keep this in sync with tftp.spec # add group %{_sbindir}/groupadd -r tftp 2>/dev/null || : # add user %{_sbindir}/useradd -c "TFTP account" -d /srv/tftpboot -G tftp -g tftp \ -r -s /bin/false tftp 2>/dev/null || : # fix sysconfig to get new defaults on Update if [ -f %{_sysconfdir}/sysconfig/atftpd ]; then sed -i -e "s@^\(ATFTPD_OPTIONS=\"--daemon \"\)@#\1@" %{_sysconfdir}/sysconfig/atftpd sed -i -e "s@^\(ATFTPD_DIRECTORY=\"/tftpboot\"\)@#\1@" %{_sysconfdir}/sysconfig/atftpd fi %if 0%{?suse_version} >= 1210 %service_add_pre atftpd.service atftpd.socket %endif %preun %if 0%{?suse_version} >= 1210 %service_del_preun atftpd.service atftpd.socket %else %stop_on_removal atftpd %endif %post %if 0%{?suse_version} >= 1210 %service_add_post atftpd.service atftpd.socket %endif %{fillup_only -n atftpd} %postun %if 0%{?suse_version} >= 1210 %service_del_postun atftpd.service atftpd.socket %else %restart_on_update atftpd %insserv_cleanup %endif %files %defattr(-,root,root) %doc BUGS FAQ LICENSE README README.MCAST README.PCRE TODO %{_bindir}/atftp %{_sbindir}/atftpd %{_sbindir}/in.tftpd %{_sbindir}/rcatftpd %if 0%{?suse_version} >= 1210 %{_unitdir}/atftpd.service %{_unitdir}/atftpd.socket %else %{_initddir}/atftpd %endif %config %{_sysconfdir}/logrotate.d/%{name} %{_localstatedir}/adm/fillup-templates/sysconfig.atftpd %{_mandir}/man1/atftp.1.gz %{_mandir}/man8/atftpd.8.gz %{_mandir}/man8/in.tftpd.8.gz %config %{_fwdefdir}/atftp %dir %attr(0750,tftp,tftp) /srv/tftpboot %dir %attr(0750,tftp,tftp) %{_localstatedir}/log/atftpd/ %changelog ++++++ atftp-0.7-ack_heuristic.patch ++++++ Index: tftpd_file.c =================================================================== --- tftpd_file.c.orig +++ tftpd_file.c @@ -402,7 +402,6 @@ int tftpd_send_file(struct thread_data * int timeout_state = state; int result; long block_number = 0; - long last_requested_block = -1; long last_block = -1; int block_loops = 0; int data_size; @@ -430,6 +429,11 @@ int tftpd_send_file(struct thread_data * long prev_file_pos = 0; int temp = 0; + long prev_sent_block = -1; + int prev_sent_count = 0; + int prev_ack_count = 0; + int curr_sent_count = 0; + /* look for mode option */ if (strcasecmp(data->tftp_options[OPT_MODE].value, "netascii") == 0) { @@ -786,8 +790,8 @@ int tftpd_send_file(struct thread_data * ntohs(client_info->client.sin_port)); sa = &client_info->client; - /* rewind the last_requested_block counter */ - last_requested_block = -1; + /* rewind the prev_sent_block counter */ + prev_sent_block = -1; state = S_SEND_OACK; break; @@ -856,6 +860,7 @@ int tftpd_send_file(struct thread_data * "source port mismatch, check bypassed"); } } + /* The ACK is from the current client */ number_of_timeout = 0; block_number = (block_loops * 65536) + ntohs(tftphdr->th_block); @@ -864,28 +869,88 @@ int tftpd_send_file(struct thread_data * logger(LOG_DEBUG, "received ACK <block: %d>", block_number); } - /* if turned on, check whether the block request isn't already fulfilled */ - if (tftpd_prevent_sas) { - /* multicast, block numbers could contain gaps */ - if (multicast) { - if (last_requested_block >= block_number) + /* Now check the ACK number and possibly ignore the request */ + + /* multicast, block numbers could contain gaps */ + if (multicast) { + /* if turned on, check whether the block request isn't already fulfilled */ + if (tftpd_prevent_sas) { + if (prev_sent_block >= block_number) { if (data->trace) - logger(LOG_DEBUG, "received duplicated ACK <block: %d >= %d>", last_requested_block, block_number); + logger(LOG_DEBUG, "received duplicated ACK <block: %d >= %d>", prev_sent_block, block_number); break; } else - last_requested_block = block_number; - /* unicast, blocks should be requested one after another */ - } else { - if (last_requested_block + 1 != block_number && last_requested_block != -1) + prev_sent_block = block_number; + } + /* don't prevent thes SAS */ + /* use a heuristic suggested by Vladimir Nadvornik */ + else { + /* here comes the ACK again */ + if (prev_sent_block == block_number) + { + /* drop if number of ACKs == times of previous block sending */ + if (++prev_ack_count == prev_sent_count) { + logger(LOG_DEBUG, "ACK count (%d) == previous block transmission count -> dropping ACK", prev_ack_count); + break; + } + /* else resend the block */ + logger(LOG_DEBUG, "resending block %d", block_number + 1); + } + /* received ACK to sent block -> move on to next block */ + else if (prev_sent_block < block_number) { + prev_sent_block = block_number; + prev_sent_count = curr_sent_count; + curr_sent_count = 0; + prev_ack_count = 1; + } + /* block with low number -> ignore it completely */ + else { + logger(LOG_DEBUG, "ignoring ACK %d", block_number); + break; + } + } + /* unicast, blocks should be requested one after another */ + } else { + /* if turned on, check whether the block request isn't already fulfilled */ + if (tftpd_prevent_sas) { + if (prev_sent_block + 1 != block_number) { + logger(LOG_WARNING, "timeout: retrying..."); if (data->trace) - logger(LOG_DEBUG, "received out of order ACK <block: %d != %d>", last_requested_block + 1, block_number); + logger(LOG_DEBUG, "received out of order ACK <block: %d != %d>", prev_sent_block + 1, block_number); + break; + } + else { + prev_sent_block = block_number; + } + /* don't prevent thes SAS */ + /* use a heuristic suggested by Vladimir Nadvornik */ + } else { + /* here comes the ACK again */ + if (prev_sent_block == block_number) + { + /* drop if number of ACKs == times of previous block sending */ + if (++prev_ack_count == prev_sent_count) { + logger(LOG_DEBUG, "ACK count (%d) == previous block transmission count -> dropping ACK", prev_ack_count); + break; + } + /* else resend the block */ + logger(LOG_DEBUG, "resending block %d", block_number + 1); + } + /* received ACK to sent block -> move on to next block */ + else if (prev_sent_block < block_number) { + prev_sent_block = block_number; + prev_sent_count = curr_sent_count; + curr_sent_count = 0; + prev_ack_count = 1; + } + /* nor previous nor current block number -> ignore it completely */ + else { + logger(LOG_DEBUG, "ignoring ACK %d", block_number); break; } - else - last_requested_block = block_number; } } @@ -898,6 +963,8 @@ int tftpd_send_file(struct thread_data * state = S_END; break; } + + curr_sent_count++; state = S_SEND_DATA; break; case GET_ERROR: @@ -989,7 +1056,7 @@ int tftpd_send_file(struct thread_data * state = S_SEND_OACK; fseek(fp, 0, SEEK_SET); /* reset the last block received counter */ - last_requested_block = -1; + prev_sent_block = -1; } else { ++++++ atftp-0.7-default_dir_man.patch ++++++ Index: atftpd.8 =================================================================== --- atftpd.8.orig +++ atftpd.8 @@ -210,7 +210,7 @@ Show summary of options. .B path This is the root directory used by the TFTP server. All requested files from a TFTP client must reside in this directory. If not -specified, the directory defaults to /tftpboot. Since +specified, the directory defaults to /srv/tftpboot. Since atftpd run as the tftp user, the permission of the directory must be set properly to allow file reading and writing. ++++++ atftp-0.7-default_user_man.patch ++++++ Index: atftpd.8 =================================================================== --- atftpd.8.orig +++ atftpd.8 @@ -80,10 +80,10 @@ acknowledging the 'multicast' request by .TP .B \-\-logfile <logfile> -Log to a specific file instead of only syslog. 'nobody' (or any user +Log to a specific file instead of only syslog. 'tftp' (or any user used to run the server) must have permissions on the given file. Assuming the file is /var/log/atftpd.log, simply run: "touch -/var/log/atftpd.log" and then "chown nobody.nogroup +/var/log/atftpd.log" and then "chown tftp.tftp /var/log/atftpd.log". When the server is ran in daemon mode, /dev/stdout or /dev/stderr can be used. @@ -105,8 +105,8 @@ specialized usage. .TP .B \-\-user <user[.group]> -By default, the server change identity to the user nobody and group -nogroup. Specify an alternate user.group with this option. +By default, the server change identity to the user tftp and group +tftp. Specify an alternate user.group with this option. .TP .B \-\-group <group> @@ -211,7 +211,7 @@ Show summary of options. This is the root directory used by the TFTP server. All requested files from a TFTP client must reside in this directory. If not specified, the directory defaults to /tftpboot. Since -atftpd run as the nobody user, the permission of the directory +atftpd run as the tftp user, the permission of the directory must be set properly to allow file reading and writing. .SH STATS ++++++ atftp-0.7-server_receive_race.patch ++++++ Index: tftpd_file.c =================================================================== --- tftpd_file.c.orig +++ tftpd_file.c @@ -114,7 +114,7 @@ int tftpd_receive_file(struct thread_dat struct sockaddr_in *sa = &data->client_info->client; struct sockaddr_in from; struct tftphdr *tftphdr = (struct tftphdr *)data->data_buffer; - FILE *fp; + FILE *fp = NULL; char filename[MAXLEN]; char string[MAXLEN]; int timeout = data->timeout; @@ -144,18 +144,6 @@ int tftpd_receive_file(struct thread_dat return ERR; } - /* Open the file for writing. */ - if ((fp = fopen(filename, "w")) == NULL) - { - /* Can't create the file. */ - logger(LOG_INFO, "Can't open %s for writing", filename); - tftp_send_error(sockfd, sa, EACCESS, data->data_buffer, data->data_buffer_size); - if (data->trace) - logger(LOG_DEBUG, "sent ERROR <code: %d, msg: %s>", EACCESS, - tftp_errmsg[EACCESS]); - return ERR; - } - /* tsize option */ if (((result = opt_get_tsize(data->tftp_options)) > -1) && !convert) { @@ -172,7 +160,6 @@ int tftpd_receive_file(struct thread_dat if (data->trace) logger(LOG_DEBUG, "sent ERROR <code: %d, msg: %s>", EOPTNEG, tftp_errmsg[EOPTNEG]); - fclose(fp); return ERR; } timeout = result; @@ -189,7 +176,6 @@ int tftpd_receive_file(struct thread_dat if (data->trace) logger(LOG_DEBUG, "sent ERROR <code: %d, msg: %s>", EOPTNEG, tftp_errmsg[EOPTNEG]); - fclose(fp); return ERR; } @@ -199,7 +185,6 @@ int tftpd_receive_file(struct thread_dat if (data->data_buffer == NULL) { logger(LOG_ERR, "memory allocation failure"); - fclose(fp); return ERR; } tftphdr = (struct tftphdr *)data->data_buffer; @@ -210,7 +195,6 @@ int tftpd_receive_file(struct thread_dat if (data->trace) logger(LOG_DEBUG, "sent ERROR <code: %d, msg: %s>", ENOSPACE, tftp_errmsg[ENOSPACE]); - fclose(fp); return ERR; } opt_set_blksize(result, data->tftp_options); @@ -343,6 +327,20 @@ int tftpd_receive_file(struct thread_dat } break; case S_DATA_RECEIVED: + if (fp == NULL) { + /* Open the file for writing. */ + if ((fp = fopen(filename, "w")) == NULL) + { + /* Can't create the file. */ + logger(LOG_INFO, "Can't open %s for writing", filename); + tftp_send_error(sockfd, sa, EACCESS, data->data_buffer, data->data_buffer_size); + if (data->trace) + logger(LOG_DEBUG, "sent ERROR <code: %d, msg: %s>", EACCESS, + tftp_errmsg[EACCESS]); + return ERR; + } + } + /* We need to seek to the right place in the file */ block_number = ntohs(tftphdr->th_block); if (data->trace) @@ -370,13 +368,13 @@ int tftpd_receive_file(struct thread_dat state = S_SEND_ACK; break; case S_END: - fclose(fp); + if (fp != NULL) fclose(fp); return OK; case S_ABORT: - fclose(fp); + if (fp != NULL) fclose(fp); return ERR; default: - fclose(fp); + if (fp != NULL) fclose(fp); logger(LOG_ERR, "%s: %d: tftpd_file.c: huh?", __FILE__, __LINE__); return ERR; ++++++ atftp-0.7-sorcerers_apprentice.patch ++++++ Index: tftp_file.c =================================================================== --- tftp_file.c.orig +++ tftp_file.c @@ -49,6 +49,7 @@ #define NB_BLOCK 2048 extern int tftp_cancel; +extern int tftp_prevent_sas; /* * Find a hole in the file bitmap. @@ -605,6 +606,7 @@ int tftp_send_file(struct client_data *d int timeout_state = state; /* what state should we go on when timeout */ int result; long block_number = 0; + long last_requested_block = -1; long last_block = -1; int data_size; /* size of data received */ int sockfd = data->sockfd; /* just to simplify calls */ @@ -765,6 +767,20 @@ int tftp_send_file(struct client_data *d connected = 1; } block_number = ntohs(tftphdr->th_block); + + /* if turned on, check whether the block request isn't already fulfilled */ + if (tftp_prevent_sas) { + if (last_requested_block >= block_number) + { + if (data->trace) + fprintf(stderr, "received duplicated ACK <block: %ld >= %ld>\n", + last_requested_block, block_number); + break; + } + else + last_requested_block = block_number; + } + if (data->trace) fprintf(stderr, "received ACK <block: %ld>\n", block_number); Index: tftpd_file.c =================================================================== --- tftpd_file.c.orig +++ tftpd_file.c @@ -55,6 +55,7 @@ extern char directory[MAXLEN]; /* read only except for the main thread */ extern int tftpd_cancel; +extern int tftpd_prevent_sas; #ifdef HAVE_PCRE extern tftpd_pcre_self_t *pcre_top; @@ -403,6 +404,7 @@ int tftpd_send_file(struct thread_data * int timeout_state = state; int result; long block_number = 0; + long last_requested_block = -1; long last_block = -1; int block_loops = 0; int data_size; @@ -785,6 +787,10 @@ int tftpd_send_file(struct thread_data * inet_ntoa(client_info->client.sin_addr), ntohs(client_info->client.sin_port)); sa = &client_info->client; + + /* rewind the last_requested_block counter */ + last_requested_block = -1; + state = S_SEND_OACK; break; } @@ -859,6 +865,32 @@ int tftpd_send_file(struct thread_data * { logger(LOG_DEBUG, "received ACK <block: %d>", block_number); } + + /* if turned on, check whether the block request isn't already fulfilled */ + if (tftpd_prevent_sas) { + /* multicast, block numbers could contain gaps */ + if (multicast) { + if (last_requested_block >= block_number) + { + if (data->trace) + logger(LOG_DEBUG, "received duplicated ACK <block: %d >= %d>", last_requested_block, block_number); + break; + } + else + last_requested_block = block_number; + /* unicast, blocks should be requested one after another */ + } else { + if (last_requested_block + 1 != block_number && last_requested_block != -1) + { + if (data->trace) + logger(LOG_DEBUG, "received out of order ACK <block: %d != %d>", last_requested_block + 1, block_number); + break; + } + else + last_requested_block = block_number; + } + } + if (ntohs(tftphdr->th_block) == 65535) { block_loops++; @@ -958,6 +990,8 @@ int tftpd_send_file(struct thread_data * /* nedd to send an oack to that client */ state = S_SEND_OACK; fseek(fp, 0, SEEK_SET); + /* reset the last block received counter */ + last_requested_block = -1; } else { Index: tftpd.c =================================================================== --- tftpd.c.orig +++ tftpd.c @@ -62,6 +62,7 @@ int retry_timeout = S_TIMEOUT; int tftpd_daemon = 0; /* By default we are started by inetd */ int tftpd_daemon_no_fork = 0; /* For who want a false daemon mode */ +int tftpd_prevent_sas = 0; /* For who don't want the sorcerer's apprentice syndrome */ short tftpd_port = 0; /* Port atftpd listen to */ char tftpd_addr[MAXLEN] = ""; /* IP address atftpd binds to */ @@ -833,6 +834,7 @@ int tftpd_cmd_line_options(int argc, cha { "mtftp", 1, NULL, OPT_MTFTP }, { "mtftp-port", 1, NULL, OPT_MTFTP_PORT }, #endif + { "prevent-sas", 0, NULL, 'X' }, { "no-source-port-checking", 0, NULL, OPT_PORT_CHECK }, { "mcast-switch-client", 0, NULL, OPT_MCAST_SWITCH }, { "version", 0, NULL, 'V' }, @@ -896,6 +898,9 @@ int tftpd_cmd_line_options(int argc, cha case 'N': tftpd_daemon_no_fork = 1; break; + case 'X': + tftpd_prevent_sas = 1; + break; case 'U': tmp = strtok(optarg, "."); if (tmp != NULL) @@ -1120,6 +1125,7 @@ void tftpd_usage(void) " --pidfile <file> : write PID to this file\n" " --daemon : run atftpd standalone (no inetd)\n" " --no-fork : run as a daemon, don't fork\n" + " --prevent-sas : prevent Sorcerer's Apprentice Syndrome\n" " --user <user[.group]> : default is nobody\n" " --group <group> : default is nogroup\n" " --port <port> : port on which atftp listen\n" Index: tftp.c =================================================================== --- tftp.c.orig +++ tftp.c @@ -57,6 +57,7 @@ /* defined as extern in tftp_file.c and mtftp_file.c, set by the signal handler */ int tftp_cancel = 0; +int tftp_prevent_sas = 0; /* local flags */ int interactive = 1; /* if false, we run in batch mode */ @@ -982,6 +983,7 @@ int tftp_cmd_line_options(int argc, char #endif { "mtftp", 1, NULL, '1'}, { "no-source-port-checking", 0, NULL, '0'}, + { "prevent-sas", 0, NULL, 'X'}, { "verbose", 0, NULL, 'v'}, { "trace", 0, NULL, 'd'}, #if DEBUG @@ -1086,6 +1088,9 @@ int tftp_cmd_line_options(int argc, char case '0': data.checkport = 0; break; + case 'X': + tftp_prevent_sas = 1; + break; case 'v': snprintf(string, sizeof(string), "verbose on"); make_arg(string, &ac, &av); @@ -1182,6 +1187,7 @@ void tftp_usage(void) " --mtftp <\"name value\"> : set mtftp variable to value\n" #endif " --no-source-port-checking: violate RFC, see man page\n" + " --prevent-sas : prevent Sorcerer's Apprentice Syndrome\n" " --verbose : set verbose mode on\n" " --trace : set trace mode on\n" #if DEBUG Index: atftpd.8 =================================================================== --- atftpd.8.orig +++ atftpd.8 @@ -180,6 +180,14 @@ implication. Be aware that this option v option has effect only for non-multicast transfer. .TP +.B \-\-prevent\-sas +Address the Sorcerer's Apprentice Syndrome situation as requested by RFC 1350. +This RFC requires repeated responses to a single packet to be +rejected. Thus a block will only get retransmitted on a timeout. +For backward compatibility, the default stays to ignore this RFC. +So blocks get transmitted on every request. + +.TP .B \-\-mcast\-switch\-client This option allow the server to proceed with the next multicast client as soon as the current client timeout. When the current master client Index: atftp.1 =================================================================== --- atftp.1.orig +++ atftp.1 @@ -77,6 +77,14 @@ to configure client side port to use. See atftpd's man page. .TP +.B \-\-prevent\-sas +Address the Sorcerer's Apprentice Syndrome situation as requested by RFC 1350. +This RFC requires repeated responses to a single packet to be +rejected. Thus a block will only get retransmitted on a timeout. +For backward compatibility, the default stays to ignore this RFC. +So blocks get transmitted on every request. + +.TP .B \-\-verbose Instruct atftp to be verbose. It will print more information about what's going on. ++++++ atftp-0.7.dif ++++++ Index: argz.h =================================================================== --- argz.h.orig +++ argz.h @@ -180,7 +180,7 @@ extern char *argz_next (__const char *__ #ifdef __USE_EXTERN_INLINES extern inline char * __argz_next (__const char *__argz, size_t __argz_len, - __const char *__entry) __THROW + __const char *__entry) { if (__entry) { @@ -194,7 +194,7 @@ __argz_next (__const char *__argz, size_ } extern inline char * argz_next (__const char *__argz, size_t __argz_len, - __const char *__entry) __THROW + __const char *__entry) { return __argz_next (__argz, __argz_len, __entry); } Index: tftp.c =================================================================== --- tftp.c.orig +++ tftp.c @@ -354,7 +354,7 @@ char *command_generator(const char *text void make_arg(char *string, int *argc, char ***argv) { static char *tmp = NULL; - int argz_len; + size_t argz_len; /* split the string to an argz vector */ if (argz_create_sep(string, ' ', &tmp, &argz_len) != 0) @@ -731,7 +731,7 @@ int get_file(int argc, char **argv) fsync(data.sockfd); close(data.sockfd); - return OK; + return tftp_result; } #ifdef HAVE_MTFTP Index: tftp_file.c =================================================================== --- tftp_file.c.orig +++ tftp_file.c @@ -59,9 +59,9 @@ int tftp_find_bitmap_hole(int prev_hole, unsigned int next_word; /* initial stuff */ - next_hole = prev_hole + 1; - next_word_no = next_hole / 32; - next_bit_no = next_hole % 32; + next_hole = 0; + next_word_no = next_hole / 32; /* effectively 0 */ + next_bit_no = next_hole % 32; /* effectively 0 */ next_word = bitmap[next_word_no]; /* Check if there is a remainder of the current word to traverse */ @@ -136,7 +136,7 @@ int tftp_receive_file(struct client_data struct hostent *host; int master_client = 0; unsigned int file_bitmap[NB_BLOCK]; - int prev_bitmap_hole = -1; /* the previous hole found in the bitmap */ + int prev_bitmap_hole = 0; /* the previous hole found in the bitmap */ char string[MAXLEN]; int prev_block_number = 0; /* needed to support netascii convertion */ ++++++ atftp-0.7_bug-213384_OPT_NUMBER.patch ++++++ --- options.h | 2 +- tftp_def.c | 2 +- tftp_def.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) Index: options.h =================================================================== --- options.h.orig +++ options.h @@ -27,7 +27,7 @@ struct tftp_opt { int enabled; /* enabled for use by server or client */ }; -extern struct tftp_opt tftp_default_options[OPT_NUMBER]; +extern struct tftp_opt tftp_default_options[OPT_NUMBER + 1]; int opt_parse_request(char *data, int data_size, struct tftp_opt *options); int opt_parse_options(char *data, int data_size, struct tftp_opt *options); Index: tftp_def.c =================================================================== --- tftp_def.c.orig +++ tftp_def.c @@ -30,7 +30,7 @@ */ // FIXME: is there a way to use TIMEOUT and SEGSIZE here? -struct tftp_opt tftp_default_options[OPT_NUMBER] = { +struct tftp_opt tftp_default_options[OPT_NUMBER + 1] = { { "filename", "", 0, 1}, /* file to transfer */ { "mode", "octet", 0, 1}, /* mode for transfer */ { "tsize", "0", 0, 1 }, /* RFC1350 options. See RFC2347, */ Index: tftp_def.h =================================================================== --- tftp_def.h.orig +++ tftp_def.h @@ -40,7 +40,7 @@ #define OPT_TIMEOUT 3 #define OPT_BLKSIZE 4 #define OPT_MULTICAST 5 -#define OPT_NUMBER 7 +#define OPT_NUMBER 6 #define OPT_SIZE 12 #define VAL_SIZE MAXLEN ++++++ atftp-0.7_compiler_warnings.patch ++++++ Index: logger.c =================================================================== --- logger.c.orig +++ logger.c @@ -27,6 +27,7 @@ #include <time.h> #include <unistd.h> #include <netdb.h> +#include <pthread.h> #include "logger.h" #define MAXLEN 128 @@ -102,17 +103,17 @@ void logger(int severity, const char *fm if (severity <= log_priority) { vsnprintf(message, sizeof(message), fmt, args); - + if (log_fp) { - fprintf(log_fp, "%s %s %s[%d.%d]: %s\n", time_buf, hostname, + fprintf(log_fp, "%s %s %s[%d.%ld]: %s\n", time_buf, hostname, log_ident, getpid(), pthread_self(), message); fflush(log_fp); } else if (log_syslog_is_open) syslog(severity, "%s", message); else - fprintf(stderr, "%s %s %s[%d.%d]: %s\n", time_buf, hostname, + fprintf(stderr, "%s %s %s[%d.%ld]: %s\n", time_buf, hostname, log_ident, getpid(), pthread_self(), message); } va_end(args); Index: configure.ac =================================================================== --- configure.ac.orig +++ configure.ac @@ -66,7 +66,7 @@ AC_PROG_CC dnl Check for AIX AC_AIX -CFLAGS="-g -Wall -D_REENTRANT" +CFLAGS="${CFLAGS} -g -Wall -D_REENTRANT" if test x$debug = xtrue; then CFLAGS="$CFLAGS -O0 -DDEBUG" Index: tftpd_list.c =================================================================== --- tftpd_list.c.orig +++ tftpd_list.c @@ -143,13 +143,13 @@ int tftpd_list_find_multicast_server_and char options[MAXLEN]; char string[MAXLEN]; char *index; - int len; + size_t len; *thread = NULL; opt_request_to_string(tftp_options, options, MAXLEN); index = strstr(options, "multicast"); - len = (int)index - (int)options; + len = (size_t)(index - options); /* lock the whole list before walking it */ pthread_mutex_lock(&thread_list_mutex); @@ -166,7 +166,7 @@ int tftpd_list_find_multicast_server_and /* must have exact same option string */ if (strncmp(string, options, len) == 0) { - *thread = current; + *thread = current; /* insert the new client at the end. If the client is already in the list, don't add it again. */ tmp = current->client_info; @@ -188,17 +188,17 @@ int tftpd_list_find_multicast_server_and } tmp->next = client; /* unlock mutex and exit */ - pthread_mutex_unlock(¤t->client_mutex); + pthread_mutex_unlock(¤t->client_mutex); pthread_mutex_unlock(&thread_list_mutex); return 1; } } - pthread_mutex_unlock(¤t->client_mutex); + pthread_mutex_unlock(¤t->client_mutex); } current = current->next; } pthread_mutex_unlock(&thread_list_mutex); - + return 0; } Index: tftp_mtftp.c =================================================================== --- tftp_mtftp.c.orig +++ tftp_mtftp.c @@ -63,7 +63,7 @@ extern int tftp_cancel; * If mode = 0, count missed packet from block 0. Else, start after first * received block. */ -int tftp_mtftp_missed_packet(int file_bitmap[], int last_block, int mode) +int tftp_mtftp_missed_packet(unsigned int file_bitmap[], int last_block, int mode) { int missed_block = 0; int block_number = 0; ++++++ atftp-0.7_sol_ip.patch ++++++ Index: tftp_io.c =================================================================== --- tftp_io.c.orig +++ tftp_io.c @@ -284,12 +284,14 @@ int tftp_get_packet(int sock1, int sock2 cmsg != NULL && cmsg->cmsg_len >= sizeof(*cmsg); cmsg = CMSG_NXTHDR(&msg, cmsg)) { +#ifdef SOL_IP if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO) { pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg); sa_to->sin_addr = pktinfo->ipi_addr; } +#endif break; } } ++++++ atftp-0.7_thread_crash.patch ++++++ http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=271816 Index: tftpd.c =================================================================== --- tftpd.c.orig +++ tftpd.c @@ -157,6 +157,7 @@ int main(int argc, char **argv) struct servent *serv; struct passwd *user; struct group *group; + pthread_t tid; #ifdef HAVE_MTFTP pthread_t mtftp_thread; @@ -466,7 +467,7 @@ int main(int argc, char **argv) new->client_info->next = NULL; /* Start a new server thread. */ - if (pthread_create(&new->tid, NULL, tftpd_receive_request, + if (pthread_create(&tid, NULL, tftpd_receive_request, (void *)new) != 0) { logger(LOG_ERR, "Failed to start new thread"); @@ -567,7 +568,8 @@ void *tftpd_receive_request(void *arg) /* Detach ourself. That way the main thread does not have to * wait for us with pthread_join. */ - pthread_detach(pthread_self()); + data->tid = pthread_self(); + pthread_detach(data->tid); /* Read the first packet from stdin. */ data_size = data->data_buffer_size; @@ -733,7 +735,7 @@ void *tftpd_receive_request(void *arg) /* free the thread structure */ free(data); - + logger(LOG_INFO, "Server thread exiting"); pthread_exit(NULL); } ++++++ atftp-CLK_TCK.diff ++++++ Index: stats.c =================================================================== --- stats.c.orig +++ stats.c @@ -142,6 +142,10 @@ void stats_thread_usage_locked(void) pthread_mutex_unlock(&s_stats.mutex); } +#ifndef CLK_TCK +#define CLK_TCK CLOCKS_PER_SEC +#endif + /* * Called at the end of the main thread, when no other threads are * running, to print the final statistics. ++++++ atftp.fw ++++++ ## Name: aTFTP Server ## Description: Opens ports for tftp service. # space separated list of allowed UDP ports UDP="tftp" ++++++ atftpd-0.7_circumvent_tftp_size_restrictions.patch ++++++ Fate #303031: Circumvent TFTP size restrictions in atftpd The size of a single image file that can be transferred with TFTP is limited to 2^(2*8) *BLOCKSIZE (as per RFC 1350 there are only two bytes for the block counter). This is problematic for one of our customers who needs to transfer 100+ MB Windows images using a TFTP client (NT bootloader) which has a hardwared BLOCKSIZE setting of 1432). block rollover http://www.compuphase.com/tftp.htm Index: tftp_def.h =================================================================== --- tftp_def.h.orig +++ tftp_def.h @@ -32,6 +32,7 @@ #define TIMEOUT 5 /* Client timeout */ #define S_TIMEOUT 5 /* Server timout. */ #define NB_OF_RETRY 5 +#define MAXBLOCKS 500000 /* maximum number of blocks in a download */ /* definition to use tftp_options structure */ #define OPT_FILENAME 0 Index: tftp_file.c =================================================================== --- tftp_file.c.orig +++ tftp_file.c @@ -604,8 +604,8 @@ int tftp_send_file(struct client_data *d int state = S_SEND_REQ; /* current state in the state machine */ int timeout_state = state; /* what state should we go on when timeout */ int result; - int block_number = 0; - int last_block = -1; + long block_number = 0; + long last_block = -1; int data_size; /* size of data received */ int sockfd = data->sockfd; /* just to simplify calls */ struct sockaddr_in sa; /* a copy of data.sa_peer */ @@ -618,8 +618,8 @@ int tftp_send_file(struct client_data *d int convert = 0; /* if true, do netascii convertion */ char string[MAXLEN]; - int prev_block_number = 0; /* needed to support netascii convertion */ - int prev_file_pos = 0; + long prev_block_number = 0; /* needed to support netascii convertion */ + long prev_file_pos = 0; int temp = 0; data->file_size = 0; @@ -726,7 +726,7 @@ int tftp_send_file(struct client_data *d data_size, data->data_buffer); data->file_size += data_size; if (data->trace) - fprintf(stderr, "sent DATA <block: %d, size: %d>\n", + fprintf(stderr, "sent DATA <block: %ld, size: %d>\n", block_number + 1, data_size - 4); state = S_WAIT_PACKET; break; @@ -766,7 +766,7 @@ int tftp_send_file(struct client_data *d } block_number = ntohs(tftphdr->th_block); if (data->trace) - fprintf(stderr, "received ACK <block: %d>\n", + fprintf(stderr, "received ACK <block: %ld>\n", block_number); if ((last_block != -1) && (block_number > last_block)) { Index: tftp_io.c =================================================================== --- tftp_io.c.orig +++ tftp_io.c @@ -334,8 +334,8 @@ int tftp_get_packet(int sock1, int sock2 /* * Read from file and do netascii conversion if needed */ -int tftp_file_read(FILE *fp, char *data_buffer, int data_buffer_size, int block_number, - int convert, int *prev_block_number, int *prev_file_pos, int *temp) +int tftp_file_read(FILE *fp, char *data_buffer, int data_buffer_size, long block_number, + int convert, long *prev_block_number, long *prev_file_pos, int *temp) { int i; int c; Index: tftp_io.h =================================================================== --- tftp_io.h.orig +++ tftp_io.h @@ -52,8 +52,8 @@ int tftp_send_data(int socket, struct so int tftp_get_packet(int sock1, int sock2, int *sock, struct sockaddr_in *sa, struct sockaddr_in *from, struct sockaddr_in *to, int timeout, int *size, char *data); -int tftp_file_read(FILE *fp, char *buffer, int buffer_size, int block_number, int convert, - int *prev_block_number, int *prev_file_pos, int *temp); +int tftp_file_read(FILE *fp, char *buffer, int buffer_size, long block_number, int convert, + long *prev_block_number, long *prev_file_pos, int *temp); int tftp_file_write(FILE *fp, char *data_buffer, int data_buffer_size, int block_number, int data_size, int convert, int *prev_block_number, int *temp); #endif Index: tftpd_file.c =================================================================== --- tftpd_file.c.orig +++ tftpd_file.c @@ -402,8 +402,9 @@ int tftpd_send_file(struct thread_data * int state = S_BEGIN; int timeout_state = state; int result; - int block_number = 0; - int last_block = -1; + long block_number = 0; + long last_block = -1; + int block_loops = 0; int data_size; struct sockaddr_in *sa = &data->client_info->client; struct sockaddr_in from; @@ -425,8 +426,8 @@ int tftpd_send_file(struct thread_data * struct client_info *client_old = NULL; struct tftp_opt options[OPT_NUMBER]; - int prev_block_number = 0; /* needed to support netascii convertion */ - int prev_file_pos = 0; + long prev_block_number = 0; /* needed to support netascii convertion */ + long prev_file_pos = 0; int temp = 0; /* look for mode option */ @@ -559,11 +560,12 @@ int tftpd_send_file(struct thread_data * logger(LOG_INFO, "blksize option -> %d", result); } - /* Verify that the file can be sent in 2^16 block of BLKSIZE octets */ - if ((file_stat.st_size / (data->data_buffer_size - 4)) > 65535) + /* Verify that the file can be sent in MAXBLOCKS blocks of BLKSIZE octets */ + if ((file_stat.st_size / (data->data_buffer_size - 4)) > MAXBLOCKS) { tftp_send_error(sockfd, sa, EUNDEF, data->data_buffer, data->data_buffer_size); - logger(LOG_NOTICE, "Requested file to big, increase BLKSIZE"); + logger(LOG_NOTICE, "Requested file too big, increase BLKSIZE"); + logger(LOG_NOTICE, "Only %d blocks of %d bytes can be served.", MAXBLOCKS, data->data_buffer_size); if (data->trace) logger(LOG_DEBUG, "sent ERROR <code: %d, msg: %s>", EUNDEF, tftp_errmsg[EUNDEF]); @@ -852,10 +854,15 @@ int tftpd_send_file(struct thread_data * } /* The ACK is from the current client */ number_of_timeout = 0; - block_number = ntohs(tftphdr->th_block); + block_number = (block_loops * 65536) + ntohs(tftphdr->th_block); if (data->trace) - logger(LOG_DEBUG, "received ACK <block: %d>", - block_number); + { + logger(LOG_DEBUG, "received ACK <block: %d>", block_number); + } + if (ntohs(tftphdr->th_block) == 65535) + { + block_loops++; + }; if ((last_block != -1) && (block_number > last_block)) { state = S_END; ++++++ atftpd-0.7_unprotected_assignments_crash.patch ++++++ Index: tftpd_list.c =================================================================== --- tftpd_list.c.orig +++ tftpd_list.c @@ -49,11 +49,11 @@ pthread_mutex_t thread_list_mutex = PTHR */ int tftpd_list_add(struct thread_data *new) { - struct thread_data *current = thread_data; + struct thread_data *current; int ret; pthread_mutex_lock(&thread_list_mutex); - + current = thread_data; number_of_thread++; ret = number_of_thread; @@ -81,11 +81,13 @@ int tftpd_list_add(struct thread_data *n */ int tftpd_list_remove(struct thread_data *old) { - struct thread_data *current = thread_data; + struct thread_data *current; int ret; pthread_mutex_lock(&thread_list_mutex); + current = thread_data; + number_of_thread--; ret = number_of_thread; @@ -137,23 +139,26 @@ int tftpd_list_find_multicast_server_and struct thread_data *data, struct client_info *client) { - struct thread_data *current = thread_data; /* head of the list */ - struct tftp_opt *tftp_options = data->tftp_options; + struct thread_data *current; /* head of the list */ + struct tftp_opt *tftp_options; struct client_info *tmp; char options[MAXLEN]; char string[MAXLEN]; char *index; size_t len; + /* lock the whole list before walking it */ + pthread_mutex_lock(&thread_list_mutex); + *thread = NULL; + current = thread_data; + tftp_options = data->tftp_options; + opt_request_to_string(tftp_options, options, MAXLEN); index = strstr(options, "multicast"); len = (size_t)(index - options); - /* lock the whole list before walking it */ - pthread_mutex_lock(&thread_list_mutex); - while (current) { if (current != data) @@ -215,9 +220,10 @@ inline void tftpd_clientlist_ready(struc void tftpd_clientlist_remove(struct thread_data *thread, struct client_info *client) { - struct client_info *tmp = thread->client_info; + struct client_info *tmp; pthread_mutex_lock(&thread->client_mutex); + tmp = thread->client_info; while ((tmp->next != client) && (tmp->next != NULL)) tmp = tmp->next; if (tmp->next == NULL) @@ -232,9 +238,11 @@ void tftpd_clientlist_remove(struct thre void tftpd_clientlist_free(struct thread_data *thread) { struct client_info *tmp; - struct client_info *head = thread->client_info; + struct client_info *head; pthread_mutex_lock(&thread->client_mutex); + head = thread->client_info; + while (head) { tmp = head; @@ -251,9 +259,10 @@ int tftpd_clientlist_done(struct thread_ struct client_info *client, struct sockaddr_in *sock) { - struct client_info *head = thread->client_info; + struct client_info *head; pthread_mutex_lock(&thread->client_mutex); + head = thread->client_info; if (client) { @@ -335,10 +344,10 @@ int tftpd_clientlist_next(struct thread_ void tftpd_list_kill_threads(void) { - struct thread_data *current = thread_data; /* head of list */ + struct thread_data *current; /* head of list */ pthread_mutex_lock(&thread_list_mutex); - + current = thread_data; while (current != NULL) { Index: tftpd_mcast.c =================================================================== --- tftpd_mcast.c.orig +++ tftpd_mcast.c @@ -51,9 +51,11 @@ struct tid *tid_list = NULL; */ int tftpd_mcast_get_tid(char **addr, short *port) { - struct tid *current = tid_list; + struct tid *current; pthread_mutex_lock(&mcast_tid_list); + current = tid_list; + /* walk the list for a free tid */ while (current != NULL) { @@ -74,9 +76,11 @@ int tftpd_mcast_get_tid(char **addr, sho int tftpd_mcast_free_tid(char *addr, short port) { - struct tid *current = tid_list; + struct tid *current; pthread_mutex_lock(&mcast_tid_list); + current = tid_list; + while (current != NULL) { if ((current->used == 1) && (current->port == port) && ++++++ atftpd.init ++++++ #! /bin/sh # Copyright (c) 2002,2003 SuSE Linux AG, Nuernberg, Germany. # All rights reserved. # # Author: Anas Nashif # # /etc/init.d/atftpd # and its symbolic link # /usr/sbin/rcatftpd # ### BEGIN INIT INFO # Provides: atftpd # Required-Start: $syslog $remote_fs # Required-Stop: $syslog $remote_fs # Default-Start: 3 5 # Default-Stop: 0 1 2 6 # Short-Description: launch atftpd server # Description: launch Advanced TFTP Server ### END INIT INFO # Shell functions sourced from /etc/rc.status: # rc_check check and set local and overall rc status # rc_status check and set local and overall rc status # rc_status -v ditto but be verbose in local rc status # rc_status -v -r ditto and clear the local rc status # rc_failed set local and overall rc status to failed # rc_failed <num> set local and overall rc status to <num><num> # rc_reset clear local rc status (overall remains) # rc_exit exit appropriate to overall rc status # rc_active checks whether a service is activated by symlinks . /etc/rc.status # First reset status of this service rc_reset # Return values acc. to LSB for all commands but status: # 0 - success # 1 - generic or unspecified error # 2 - invalid or excess argument(s) # 3 - unimplemented feature (e.g. "reload") # 4 - insufficient privilege # 5 - program is not installed # 6 - program is not configured # 7 - program is not running # # Note that starting an already running service, stopping # or restarting a not-running service as well as the restart # with force-reload (in case signalling is not supported) are # considered a success. ATFTP_BIN="/usr/sbin/atftpd" if [ ! -x $ATFTP_BIN ]; then echo -n "Advanced Trivial FTP server, $ATFTP_BIN is not installed." # Tell the user this has skipped rc_status -s exit 5 fi ATFTP_LOG_FILE="/var/log/atftpd/atftp.log" ATFTP_LOG_DIR="$(dirname ${ATFTP_LOG_FILE})" ATFTP_PID_DIR="/var/run/atftpd" # check for sysconfig file [ -f /etc/sysconfig/atftpd ] && . /etc/sysconfig/atftpd # Set default in case of missing sysconfig file ATFTP_USR=${ATFTPD_USER:="tftp"} ATFTP_GRP=${ATFTPD_GROUP:="tftp"} ATFTP_OPTS=${ATFTPD_OPTIONS:=""} ATFTP_USE_INETD=${ATFTPD_USE_INETD:="no"} ATFTP_DIR=${ATFTPD_DIRECTORY:="/srv/tftpboot"} ATFTP_BIND=${ATFTPD_BIND_ADDRESSES:=""} # start as daemon with some default opts ATFTP_DEF_OPTS="--daemon --user $ATFTP_USR --group $ATFTP_GRP --logfile $ATFTP_LOG_FILE" # create logfile and PID directory if they don't exist create_logfile_and_piddir(){ # /var/run is mounted as tmpfs on openSUSE >= 11.4 [ ! -d "$ATFTP_PID_DIR" ] && /usr/bin/install -o ${ATFTP_USR} -g ${ATFTP_GRP} -d "$ATFTP_PID_DIR"; # must exist otherwise atftp will log to syslog [ ! -f "$ATFTP_PID_DIR" ] && /usr/bin/install -m 0644 -o ${ATFTP_USR} -g ${ATFTP_GRP} /dev/null "$ATFTP_LOG_FILE" } if [ "$ATFTP_USE_INETD" = "yes" ]; then echo "ATFTP is set to start via inetd" exit 0; fi case "$1" in start) create_logfile_and_piddir if [ -n "$ATFTP_BIND" ]; then for IP in $ATFTP_BIND; do echo -n "Starting Advanced Trivial FTP server on $IP: " ## Start daemon with startproc(8). If this fails ## the echo return value is set appropriate. startproc -p "${ATFTP_PID_DIR}/$IP.pid" -f $ATFTP_BIN --pidfile "${ATFTP_PID_DIR}/$IP.pid" $ATFTP_DEF_OPTS $ATFTP_OPTS $ATFTP_DIR --bind-address $IP # Remember status and be verbose rc_status -v done else echo -n "Starting Advanced Trivial FTP server: " ## Start daemon with startproc(8). If this fails ## the echo return value is set appropriate. startproc $ATFTP_BIN --pidfile "${ATFTP_PID_DIR}/pid" $ATFTP_DEF_OPTS $ATFTP_OPTS $ATFTP_DIR # Remember status and be verbose rc_status -v fi ;; stop) echo -n "Stopping Advanced Trivial FTP server: " killproc -TERM $ATFTP_BIN # Remember status and be verbose rc_status -v ;; try-restart) ## Do a restart only if the service was active before. ## Note: try-restart is not (yet) part of LSB (as of 1.2) $0 status >/dev/null && $0 restart # Remember status and be quiet rc_status ;; restart) ## Stop the service and regardless of whether it was ## running or not, start it again. $0 stop $0 start # Remember status and be quiet rc_status ;; force-reload) #echo -n "Reloading Advanced Trivial FTP server: " ## if it supports it: #/sbin/killproc -HUP $ATFTP_BIN #touch /var/run/FOO.pid # Remember status and be verbose #rc_status -v ## Otherwise: $0 try-restart #rc_status ;; reload) echo -n "Reloading Advanced Trivial FTP server: " ## Like force-reload, but if daemon does not support ## signaling, do nothing (!) # If it supports signaling: #/sbin/killproc -HUP $ATFTP_BIN #touch /var/run/FOO.pid # Remember status and be verbose #rc_status -v ## Otherwise if it does not support reload: rc_failed 5 # Remember status and be verbose rc_status -v ;; status) echo -n "Checking for Advanced Trivial FTP server: " ## Check status with checkproc(8), if process is running ## checkproc will return with exit status 0. # Return value is slightly different for the status command: # 0 - service running # 1 - service dead, but /var/run/ pid file exists # 2 - service dead, but /var/lock/ lock file exists # 3 - service not running # NOTE: checkproc returns LSB compliant status values. checkproc $ATFTP_BIN # Remember status and be verbose rc_status -v ;; *) echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload}" exit 1 ;; esac rc_exit ++++++ atftpd.logrotate ++++++ /var/log/atftpd/atftp.log { su tftp tftp compress dateext maxage 365 rotate 99 size=+4096k notifempty missingok create 640 tftp tftp postrotate /etc/init.d/atftpd restart endscript } ++++++ atftpd.service ++++++ [Unit] Description=Advanced TFTP Server [Service] EnvironmentFile=/etc/sysconfig/atftpd ExecStart=/usr/sbin/atftpd --user $ATFTPD_USER --group $ATFTPD_GROUP $ATFTPD_OPTIONS $ATFTPD_DIRECTORY StandardInput=socket ++++++ atftpd.socket ++++++ [Unit] Description=Advanced tftp Server Activation Socket [Socket] ListenDatagram=0.0.0.0:69 [Install] WantedBy=sockets.target ++++++ atftpd.sysconfig ++++++ ## Path: Network/FTP/Atftpd ## Description: ATFTP Configuration ## Type: string ## Default: "tftp" # # daemon user (tftp) # ATFTPD_USER="tftp" ## Type: string ## Default: "tftp" # # daemon user (tftp) # ATFTPD_GROUP="tftp" ## Type: string ## Default: "" ## ## INFO: ## "--daemon, --user, --group, --logfile" can not be removed/replaced here as ## atftp is started with them as default opts: "--daemon --user atftp --group atftp " ## and ## logging to file is set as default: "--logfile /var/log/atftpd/atftp.log " # # atftpd options # ATFTPD_OPTIONS="" ## Type: yesno ## Default: no # # Use inetd instead of daemon # ATFTPD_USE_INETD="no" ## Type: string ## Default: "/srv/tftpboot" ## was "/tftpboot" but ## "/tftpboot" is not allowed anymore in FHS 2.2. # # TFTP directory must be a world readable/writable directory. # By default /srv/tftpboot is assumed. # ATFTPD_DIRECTORY="/srv/tftpboot" ## Type: string ## Default: "" # # Whitespace seperated list of IP addresses which ATFTPD binds to. # One instance of the service is started on each IP address. # By default atftpd will listen on all available IP addresses/interfaces. # ATFTPD_BIND_ADDRESSES=""
participants (1)
-
root@hilbert.suse.de