package tftpd tags 536509 + patch thanks Now I deliver a fully functional patch to let tftpd __and__ tftp enjoy the blessing of IPv6 support. For your information it is worth to point out that the client side is harder to implement by a magnitude, since the server is inetd-based.
The mailing list debian-ipv6 har been one of utterly silence since I mentioned this endeouvor, so I had to do all the research on my own, but here is the outcome. Best regards -- Mats Erik Andersson, fil. dr <deb...@gisladisker.se>
diff -Nru netkit-tftp-0.17/debian/changelog netkit-tftp-0.17/debian/changelog --- netkit-tftp-0.17/debian/changelog 2010-04-17 03:41:02.000000000 +0200 +++ netkit-tftp-0.17/debian/changelog 2010-04-17 02:58:32.000000000 +0200 @@ -1,3 +1,26 @@ +netkit-tftp (0.17-17.1) unstable; urgency=low + + * Non-maintainer upload. + * Migrate to source format 3.0 quilt. + + Deposit legacy patches in debian/patches/. + * Standards 3.8.4, compatibility level 7. + * debian/control: Add ${misc:Depends} for both binary packages. + * debian/rules: Use dh_strip and dh_prep. + * debian/watch: New file. + * Augmented patches: + + 33_tftp_tftpsubs_c.diff: Missing include. + + 10_tftp_manpage.diff: Groff error. + * New patches for IPv6-enabled binaries: + + Closes: #536509 + + 50_tftpd_inet6.diff + + 55_tftpsubs_inet6.diff + + 60_tftp_inet6.diff + * debian/tftpd.examples: debian/local/tftpd.xinetd + * [lintian] Use the idiom 'set -e' in maintainer scripts. + * [lintian] Insert stanza Homepage in control file. + + -- Mats Erik Andersson <mats.anders...@gisladisker.se> Sat, 17 Apr 2010 02:57:02 +0200 + netkit-tftp (0.17-17) unstable; urgency=low * Require hostname for connection name (Closes: #375365) diff -Nru netkit-tftp-0.17/debian/compat netkit-tftp-0.17/debian/compat --- netkit-tftp-0.17/debian/compat 2010-04-17 03:41:02.000000000 +0200 +++ netkit-tftp-0.17/debian/compat 2010-04-17 02:26:15.000000000 +0200 @@ -1 +1 @@ -4 +7 diff -Nru netkit-tftp-0.17/debian/control netkit-tftp-0.17/debian/control --- netkit-tftp-0.17/debian/control 2010-04-17 03:41:02.000000000 +0200 +++ netkit-tftp-0.17/debian/control 2010-04-17 02:32:47.000000000 +0200 @@ -2,12 +2,13 @@ Section: net Priority: optional Maintainer: Alberto Gonzalez Iniesta <a...@inittab.org> -Standards-Version: 3.8.0.0 -Build-Depends: debhelper (>= 4.0.2) +Standards-Version: 3.8.4 +Build-Depends: debhelper (>= 7) +Homepage: http://ftp.uk.linux.org/pub/linux/Networking/netkit/ Package: tftp Architecture: any -Depends: netbase, ${shlibs:Depends} +Depends: netbase, ${shlibs:Depends}, ${misc:Depends} Replaces: netstd Description: Trivial file transfer protocol client Tftp is the user interface to the Internet TFTP (Trivial File Transfer @@ -17,7 +18,7 @@ Package: tftpd Architecture: any -Depends: openbsd-inetd | inet-superserver, ${shlibs:Depends} +Depends: openbsd-inetd | inet-superserver, ${shlibs:Depends}, ${misc:Depends} Replaces: netstd Description: Trivial file transfer protocol server Tftpd is a server which supports the Internet Trivial File Transfer Protocol diff -Nru netkit-tftp-0.17/debian/local/tftpd.xinetd netkit-tftp-0.17/debian/local/tftpd.xinetd --- netkit-tftp-0.17/debian/local/tftpd.xinetd 1970-01-01 01:00:00.000000000 +0100 +++ netkit-tftp-0.17/debian/local/tftpd.xinetd 2010-02-06 12:11:28.000000000 +0100 @@ -0,0 +1,13 @@ +service tftp +{ + disable = no + socket_type = dgram + protocol = udp + flags = IPv6 + wait = yes + user = nobody + server = /usr/sbin/in.tftpd + server_args = /srv/tftp + log_type = SYSLOG daemon info + log_on_success = HOST +} diff -Nru netkit-tftp-0.17/debian/patches/05_mrules.diff netkit-tftp-0.17/debian/patches/05_mrules.diff --- netkit-tftp-0.17/debian/patches/05_mrules.diff 1970-01-01 01:00:00.000000000 +0100 +++ netkit-tftp-0.17/debian/patches/05_mrules.diff 2010-02-05 18:31:18.000000000 +0100 @@ -0,0 +1,14 @@ +X-Comment: Recovered from previous package releases. +--- netkit-tftp-0.17.orig/MRULES ++++ netkit-tftp-0.17/MRULES +@@ -1,8 +1,8 @@ + # Standard compilation rules (don't use make builtins) + + %.o: %.c +- $(CC) $(CFLAGS) -I../include $< -c ++ $(CC) $(CFLAGS) $< -c + + %.o: %.cc +- $(CC) $(CFLAGS) -I../include $< -c ++ $(CC) $(CFLAGS) $< -c + diff -Nru netkit-tftp-0.17/debian/patches/10_tftp_manpage.diff netkit-tftp-0.17/debian/patches/10_tftp_manpage.diff --- netkit-tftp-0.17/debian/patches/10_tftp_manpage.diff 1970-01-01 01:00:00.000000000 +0100 +++ netkit-tftp-0.17/debian/patches/10_tftp_manpage.diff 2010-02-06 12:07:00.000000000 +0100 @@ -0,0 +1,21 @@ +X-Comment: Recovered from previous package releases. +--- netkit-tftp-0.17.orig/tftp/tftp.1 ++++ netkit-tftp-0.17/tftp/tftp.1 +@@ -60,7 +60,7 @@ + Once + .Nm tftp + is running, it issues the prompt +-.LI tftp> ++\f(CWtftp>\fP + and recognizes the following commands: + .Pp + .Bl -tag -width verbose -compact +@@ -84,7 +84,7 @@ + protocol, unlike the + .Tn FTP + protocol, +-does not maintain connections betweeen transfers; thus, the ++does not maintain connections between transfers; thus, the + .Cm connect + command does not actually create a connection, + but merely remembers what host is to be used for transfers. diff -Nru netkit-tftp-0.17/debian/patches/15_tftpd_manpage.diff netkit-tftp-0.17/debian/patches/15_tftpd_manpage.diff --- netkit-tftp-0.17/debian/patches/15_tftpd_manpage.diff 1970-01-01 01:00:00.000000000 +0100 +++ netkit-tftp-0.17/debian/patches/15_tftpd_manpage.diff 2010-02-05 18:34:03.000000000 +0100 @@ -0,0 +1,32 @@ +Author: Herbert Xu <herb...@debian.org> +X-Comment: Recovered from previous package releases. +--- netkit-tftp-0.17.orig/tftpd/tftpd.8 ++++ netkit-tftp-0.17/tftpd/tftpd.8 +@@ -42,6 +42,8 @@ + Trivial File Transfer Protocol server + .Sh SYNOPSIS + .Nm tftpd ++.Op Fl n ++.Op Fl s + .Op Ar directory ... + .Sh DESCRIPTION + .Nm Tftpd +@@ -111,6 +113,18 @@ + can be used to ensure that replies go out from the correct address. + These considerations are important, because most tftp clients will + reject reply packets that appear to come from an unexpected address. ++.Pp ++The options are: ++.Bl -tag -width Ds ++.It Fl n ++Suppresses negative acknowledgement of requests for nonexistent relative ++filenames. ++.It Fl s ++All absolute filenames are treated as if they were preceded by the first ++directory argument, or ++.Pa /tftpboot ++if there is none. ++.El + .Sh SEE ALSO + .Xr tftp 1 , + .Xr inetd 8 diff -Nru netkit-tftp-0.17/debian/patches/20_tftp_main_c.diff netkit-tftp-0.17/debian/patches/20_tftp_main_c.diff --- netkit-tftp-0.17/debian/patches/20_tftp_main_c.diff 1970-01-01 01:00:00.000000000 +0100 +++ netkit-tftp-0.17/debian/patches/20_tftp_main_c.diff 2010-02-05 18:17:16.000000000 +0100 @@ -0,0 +1,68 @@ +Description: Various sanity checks. +Author: Michael Welle, Alberto Gonzales Iniesta +Forwarded: no +X-Comment: Recovered from earlier package releases. +--- netkit-tftp-0.17.orig/tftp/main.c ++++ netkit-tftp-0.17/tftp/main.c +@@ -69,7 +69,7 @@ + #define TIMEOUT 5 /* secs between rexmt's */ + + struct sockaddr_in s_inn; +-int f; ++int f = -1; + int trace; + int verbose; + int rexmtval = TIMEOUT; +@@ -151,17 +151,11 @@ + static struct cmd *getcmd(const char *name); + static char *tail(char *filename); + +-int +-main(int argc, char *argv[]) +-{ ++void initsock() { + struct sockaddr_in s_in; +- int top; + +- sp = getservbyname("tftp", "udp"); +- if (sp == 0) { +- fprintf(stderr, "tftp: udp/tftp: unknown service\n"); +- exit(1); +- } ++ if (f >= 0) ++ close(f); + f = socket(AF_INET, SOCK_DGRAM, 0); + if (f < 0) { + perror("tftp: socket"); +@@ -173,6 +167,19 @@ + perror("tftp: bind"); + exit(1); + } ++} ++ ++int ++main(int argc, char *argv[]) ++{ ++ int top; ++ ++ sp = getservbyname("tftp", "udp"); ++ if (sp == 0) { ++ fprintf(stderr, "tftp: udp/tftp: unknown service\n"); ++ exit(1); ++ } ++ initsock(); + strcpy(mode, "netascii"); + mysignal(SIGINT, intr); + if (argc > 1) { +@@ -202,7 +209,10 @@ + argc = margc; + argv = margv; + } +- if (argc > 3) { ++ /* We should have 2 or 3 args now: the cmd and its ++ * parameters. If not, we bail out here. ++ */ ++ if (argc != 2 && argc != 3) { + printf("usage: %s host-name [port]\n", argv[0]); + return; + } diff -Nru netkit-tftp-0.17/debian/patches/30_tftp_tftp_c.diff netkit-tftp-0.17/debian/patches/30_tftp_tftp_c.diff --- netkit-tftp-0.17/debian/patches/30_tftp_tftp_c.diff 1970-01-01 01:00:00.000000000 +0100 +++ netkit-tftp-0.17/debian/patches/30_tftp_tftp_c.diff 2010-02-05 18:36:47.000000000 +0100 @@ -0,0 +1,79 @@ +Description: Various sanity checks. +Author: Michael Welle, Alberto Gonzales Iniesta +Forwarded: no +X-Comment: Recovered from previous package releases. +--- netkit-tftp-0.17.orig/tftp/tftp.c ++++ netkit-tftp-0.17/tftp/tftp.c +@@ -174,19 +174,13 @@ + goto abort; + } + if (ap->th_opcode == ACK) { +- volatile int j = 0; +- + if (ap->th_block == block) { + break; + } + /* On an error, try to synchronize + * both sides. + */ +- j = synchnet(f); +- if (j && trace) { +- printf("discarded %d packets\n", +- j); +- } ++ synchnet(f, trace); + if (ap->th_block == (block-1)) { + goto send_data; + } +@@ -197,10 +191,14 @@ + } + else { + amount += size; ++ if (size != SEGSIZE) { ++ break; ++ } + } + block++; +- } while (size == SEGSIZE); ++ } while (1); + abort: ++ initsock(); + fclose(file); + stopclock(); + if (amount > 0) +@@ -278,18 +276,13 @@ + goto abort; + } + if (dp->th_opcode == DATA) { +- volatile int j = 0; +- + if (dp->th_block == block) { + break; /* have next packet */ + } + /* On an error, try to synchronize + * both sides. + */ +- j = synchnet(f); +- if (j && trace) { +- printf("discarded %d packets\n", j); +- } ++ synchnet(f, trace); + if (dp->th_block == (block-1)) { + goto send_ack; /* resend ack */ + } +@@ -303,10 +296,14 @@ + } + amount += size; + } while (size == SEGSIZE); +-abort: /* ok to ack, since user */ ++ + ap->th_opcode = htons((u_short)ACK); /* has seen err msg */ + ap->th_block = htons((u_short)block); + (void) sendto(f, ackbuf, 4, 0, (struct sockaddr *)&s_inn, sizeof(s_inn)); ++ ++abort: ++ initsock(); ++ + write_behind(file, convert); /* flush last buffer */ + fclose(file); + stopclock(); diff -Nru netkit-tftp-0.17/debian/patches/33_tftp_tftpsubs_c.diff netkit-tftp-0.17/debian/patches/33_tftp_tftpsubs_c.diff --- netkit-tftp-0.17/debian/patches/33_tftp_tftpsubs_c.diff 1970-01-01 01:00:00.000000000 +0100 +++ netkit-tftp-0.17/debian/patches/33_tftp_tftpsubs_c.diff 2010-02-05 18:37:27.000000000 +0100 @@ -0,0 +1,34 @@ +X-Comment: Recovered from previous package releases. +--- netkit-tftp-0.17.orig/tftp/tftpsubs.c ++++ netkit-tftp-0.17/tftp/tftpsubs.c +@@ -55,6 +55,7 @@ + #include <arpa/tftp.h> + #include <unistd.h> + #include <stdio.h> ++#include <string.h> + #include <signal.h> + + #ifndef FIONREAD +@@ -249,8 +250,8 @@ + * when trace is active). + */ + +-int +-synchnet(int f /* socket to flush */) ++void ++synchnet(int f /* socket to flush */, int trace) + { + int i, j = 0; + char rbuf[PKTSIZE]; +@@ -265,7 +266,10 @@ + (void) recvfrom(f, rbuf, sizeof (rbuf), 0, + (struct sockaddr *)&from, &fromlen); + } else { +- return(j); ++ if (j && trace) { ++ printf("discarded %d packets\n", j); ++ } ++ return; + } + } + } diff -Nru netkit-tftp-0.17/debian/patches/37_tftp_tftpsubs_h.diff netkit-tftp-0.17/debian/patches/37_tftp_tftpsubs_h.diff --- netkit-tftp-0.17/debian/patches/37_tftp_tftpsubs_h.diff 1970-01-01 01:00:00.000000000 +0100 +++ netkit-tftp-0.17/debian/patches/37_tftp_tftpsubs_h.diff 2010-02-05 18:37:52.000000000 +0100 @@ -0,0 +1,12 @@ +X-Comment: Recovered from previous package releases. +--- netkit-tftp-0.17.orig/tftp/tftpsubs.h ++++ netkit-tftp-0.17/tftp/tftpsubs.h +@@ -1,6 +1,7 @@ + #define PKTSIZE SEGSIZE+4 /* should be moved to tftp.h */ + +-int synchnet(int); ++void initsock(void); ++void synchnet(int, int); + struct tftphdr *r_init(void); + struct tftphdr *w_init(void); + int readit(FILE *file, struct tftphdr **dpp, int convert); diff -Nru netkit-tftp-0.17/debian/patches/40_tftpd_tftpd_c.diff netkit-tftp-0.17/debian/patches/40_tftpd_tftpd_c.diff --- netkit-tftp-0.17/debian/patches/40_tftpd_tftpd_c.diff 1970-01-01 01:00:00.000000000 +0100 +++ netkit-tftp-0.17/debian/patches/40_tftpd_tftpd_c.diff 2010-02-05 18:34:56.000000000 +0100 @@ -0,0 +1,112 @@ +Description: Various sanity checks. +Author: Herbert Xu, Tomasz Nowiaski, Alberto Gonzales Iniesta +Forwarded: no +X-Comment: Recovered from earlier package releases. +--- netkit-tftp-0.17.orig/tftpd/tftpd.c ++++ netkit-tftp-0.17/tftpd/tftpd.c +@@ -92,8 +92,11 @@ + static struct sockaddr_in from; + static socklen_t fromlen; + +-#define MAXARG 4 +-static char *dirs[MAXARG+1]; ++static const char *default_dirs[] = { "/tftpboot", 0 }; ++static const char **dirs = default_dirs; ++ ++static int suppress_naks; ++static int secure_tftp; + + int + main(int ac, char **av) +@@ -105,12 +108,25 @@ + register struct tftphdr *tp; + register int n = 0; + int on = 1; ++ int ch; + +- ac--; av++; +- if (ac==0) dirs[0] = "/tftpboot"; /* default directory */ +- while (ac-- > 0 && n < MAXARG) +- dirs[n++] = *av++; + openlog("tftpd", LOG_PID, LOG_DAEMON); ++ opterr = 0; ++ while ((ch = getopt(ac, av, "ns")) != EOF) { ++ switch (ch) { ++ case 'n': ++ suppress_naks = 1; ++ break; ++ case 's': ++ secure_tftp = 1; ++ break; ++ default: ++ syslog(LOG_ERR, "unknown option -%c", ch); ++ exit(1); ++ } ++ } ++ ++ if (av[optind]) dirs = (const char **) &av[optind]; + if (ioctl(0, FIONBIO, &on) < 0) { + syslog(LOG_ERR, "ioctl(FIONBIO): %m\n"); + exit(1); +@@ -279,6 +295,12 @@ + } + ecode = (*pf->f_validate)(filename, tp->th_opcode); + if (ecode) { ++ /* ++ * Avoid storms of naks to a RRQ broadcast for a relative ++ * bootfile pathname from a diskless Sun. ++ */ ++ if (suppress_naks && *filename != '/' && ecode == ENOTFOUND) ++ exit(0); + nak(ecode); + exit(1); + } +@@ -310,13 +332,17 @@ + struct stat stbuf; + int fd; + const char *cp; +- char **dirp; ++ const char **dirp; + + syslog(LOG_NOTICE, "tftpd: trying to get file: %s\n", filename); + +- if (*filename != '/') { ++ if (*filename != '/' || secure_tftp) { + syslog(LOG_NOTICE, "tftpd: serving file from %s\n", dirs[0]); +- chdir(dirs[0]); ++ /*chdir(dirs[0]);*/ ++ if ( chdir(dirs[0]) < 0 ) ++ return (EACCESS); ++ while (*filename == '/') ++ filename++; + } else { + for (dirp = dirs; *dirp; dirp++) + if (strncmp(filename, *dirp, strlen(*dirp)) == 0) +@@ -366,7 +392,8 @@ + if ((stbuf.st_mode & S_IWOTH) == 0) + return (EACCESS); + } +- fd = open(filename, mode == RRQ ? O_RDONLY : O_WRONLY|O_TRUNC); ++ ++ fd = open(filename, mode == RRQ ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT, 0600); + if (fd < 0) + return (errno + 100); + file = fdopen(fd, (mode == RRQ)? "r":"w"); +@@ -441,7 +468,7 @@ + break; + } + /* Re-synchronize with the other side */ +- (void) synchnet(peer); ++ (void) synchnet(peer, 0); + if (ap->th_block == (block -1)) { + goto send_data; + } +@@ -506,7 +533,7 @@ + break; /* normal */ + } + /* Re-synchronize with the other side */ +- (void) synchnet(peer); ++ (void) synchnet(peer, 0); + if (dp->th_block == (block-1)) + goto send_ack; /* rexmit */ + } diff -Nru netkit-tftp-0.17/debian/patches/50_tftpd_inet6.diff netkit-tftp-0.17/debian/patches/50_tftpd_inet6.diff --- netkit-tftp-0.17/debian/patches/50_tftpd_inet6.diff 1970-01-01 01:00:00.000000000 +0100 +++ netkit-tftp-0.17/debian/patches/50_tftpd_inet6.diff 2010-04-17 02:22:09.000000000 +0200 @@ -0,0 +1,102 @@ +Description: Enable IPv6 sockets for the tftp server. + Using the super structure 'struct sockaddr_storage', and adaptive + capture of the address family from the incoming socket, the server + in.tftpd will be IPv6-enabled. +X-Depends-on-Previous-Patch: 40_tftpd_tftpd_c.diff +Author: Mats Erik Andersson <deb...@gisladisker.se> +Forwarded: no +Last-Update: 2010-04-17 +--- netkit-tftp-0.17.debian/tftpd/tftpd.c ++++ netkit-tftp-0.17/tftpd/tftpd.c +@@ -89,7 +89,7 @@ + + static char buf[PKTSIZE]; + static char ackbuf[PKTSIZE]; +-static struct sockaddr_in from; ++static struct sockaddr_storage from; + static socklen_t fromlen; + + static const char *default_dirs[] = { "/tftpboot", 0 }; +@@ -101,7 +101,7 @@ + int + main(int ac, char **av) + { +- struct sockaddr_in sn; ++ struct sockaddr_storage sn; + socklen_t snsize; + int dobind=1; + +@@ -173,7 +173,7 @@ main(int ac, char **av) + */ + k = sizeof(from); + i = recvfrom(0, buf, sizeof (buf), 0, +- (struct sockaddr *)&from, &k); ++ (struct sockaddr *)&from, &k); + if (i > 0) { + n = i; + fromlen = k; +@@ -202,7 +202,6 @@ main(int ac, char **av) + exit(1); + } + } +- from.sin_family = AF_INET; + alarm(0); + + /* +@@ -213,15 +212,35 @@ main(int ac, char **av) + * interface. + */ + snsize = sizeof(sn); +- if (getsockname(0, (struct sockaddr *)&sn, &snsize)<0 || +- sn.sin_addr.s_addr == INADDR_ANY) { ++ if ( getsockname(0, (struct sockaddr *)&sn, &snsize) < 0 ) { + dobind = 0; + } +- sn.sin_port = 0; ++ ++ if ( dobind ) { ++ /* Was the wildcard address contained in the socket? */ ++ if ( ((sn.ss_family == AF_INET) && ++ ((struct sockaddr_in *)&sn)->sin_addr.s_addr ++ == INADDR_ANY ) ++ || ((sn.ss_family == AF_INET6) && ++ (memcmp( &((struct sockaddr_in6 *)&sn)->sin6_addr, ++ &in6addr_any, ++ sizeof(struct in6_addr)) == 0) ) ++ ) ++ { ++ /* Implicit binding suffices for wildcard addresses. */ ++ dobind = 0; ++ } ++ } ++ ++ if ( sn.ss_family == AF_INET ) ++ ((struct sockaddr_in *) &sn)->sin_port = 0; ++ else if ( sn.ss_family == AF_INET6 ) ++ ((struct sockaddr_in6 *) &sn)->sin6_port = 0; + + close(0); + close(1); +- peer = socket(AF_INET, SOCK_DGRAM, 0); ++ ++ peer = socket(from.ss_family, SOCK_DGRAM, 0); + if (peer < 0) { + syslog(LOG_ERR, "socket: %m\n"); + exit(1); +@@ -232,10 +251,15 @@ main(int ac, char **av) + exit(1); + } + +- if (connect(peer, (struct sockaddr *)&from, sizeof(from)) < 0) { ++ if ( connect(peer, (struct sockaddr *)&from, ++ (from.ss_family == AF_INET6) ++ ? sizeof(struct sockaddr_in6) ++ : sizeof(struct sockaddr_in)) ++ < 0 ) { + syslog(LOG_ERR, "connect: %m\n"); + exit(1); + } ++ + tp = (struct tftphdr *)buf; + tp->th_opcode = ntohs(tp->th_opcode); + if (tp->th_opcode == RRQ || tp->th_opcode == WRQ) diff -Nru netkit-tftp-0.17/debian/patches/55_tftpsubs_inet6.diff netkit-tftp-0.17/debian/patches/55_tftpsubs_inet6.diff --- netkit-tftp-0.17/debian/patches/55_tftpsubs_inet6.diff 1970-01-01 01:00:00.000000000 +0100 +++ netkit-tftp-0.17/debian/patches/55_tftpsubs_inet6.diff 2010-04-17 02:22:25.000000000 +0200 @@ -0,0 +1,30 @@ +Description: Enable IPv6 sockets. + Use 'struct sockaddr_storage' to insure that the address structure + can accomodate IPv4 as well as IPv6. + . + Needed for address family independence of the tftp client. +X-Depends-on-Previous-Patch: 33_tftp_tftpsubs_c.diff +Author: Mats Erik Andersson <deb...@gisladisker.se> +Forwarded: no +Last-Update: 2010-02-17 +--- netkit-tftp-0.17.debian/tftp/tftpsubs.c ++++ netkit-tftp-0.17/tftp/tftpsubs.c +@@ -255,7 +255,7 @@ synchnet(int f /* socket to flush */, in + { + int i, j = 0; + char rbuf[PKTSIZE]; +- struct sockaddr_in from; ++ struct sockaddr_storage from; + socklen_t fromlen; + + while (1) { +--- netkit-tftp-0.17.debian/tftp/tftpsubs.h ++++ netkit-tftp-0.17/tftp/tftpsubs.h +@@ -1,6 +1,6 @@ + #define PKTSIZE SEGSIZE+4 /* should be moved to tftp.h */ + +-void initsock(void); ++void initsock(int); + void synchnet(int, int); + struct tftphdr *r_init(void); + struct tftphdr *w_init(void); diff -Nru netkit-tftp-0.17/debian/patches/60_tftp_inet6.diff netkit-tftp-0.17/debian/patches/60_tftp_inet6.diff --- netkit-tftp-0.17/debian/patches/60_tftp_inet6.diff 1970-01-01 01:00:00.000000000 +0100 +++ netkit-tftp-0.17/debian/patches/60_tftp_inet6.diff 2010-04-17 02:22:45.000000000 +0200 @@ -0,0 +1,494 @@ +Description: Enable coexisting IPv6 and IPv4 for tftp client. + Using the super structure 'struct sockaddr_storage', and adaptive + capture of the address family from configured interfaces, the client + binary tftp will be IPv6-enabled. + . + Care has to be taken to let the address family, needed for a + specific host connection, trickle down into ever send and recv + calls during transportation. +X-Depends-on-Previous-Patches: 20_tftp_main_c.diff 30_tftp_tftp_c.diff + 55_tftpsubs_inet6.diff +Author: Mats Erik Andersson <deb...@gisladisker.se> +Forwarded: no +Last-Update: 2010-04-17 +--- netkit-tftp-0.17.debian/tftp/main.c ++++ netkit-tftp-0.17/tftp/main.c +@@ -68,7 +68,7 @@ + + #define TIMEOUT 5 /* secs between rexmt's */ + +-struct sockaddr_in s_inn; ++struct sockaddr_storage s_inn; + int f = -1; + int trace; + int verbose; +@@ -79,7 +79,7 @@ void sendfile(int fd, char *name, char * + void recvfile(int fd, char *name, char *modestr); + + +-static int connected; ++static int connected; /* If non-zero, contains active address family! */ + static short port; + static char mode[32]; + static char line[200]; +@@ -151,22 +151,63 @@ + static struct cmd *getcmd(const char *name); + static char *tail(char *filename); + +-void initsock() { +- struct sockaddr_in s_in; ++static void ++set_port(struct sockaddr_storage *ss) { ++ switch (ss->ss_family) { ++ case AF_INET6: ++ ((struct sockaddr_in6 *) ss)->sin6_port = port; ++ break; ++ case AF_INET: ++ default: ++ ((struct sockaddr_in *) ss)->sin_port = port; ++ break; ++ } ++} ++ ++void initsock(int af) { ++ struct sockaddr_storage s_in; ++ struct addrinfo hints, *ai, *aiptr; ++ ++ memset(&hints, 0, sizeof(hints)); ++ hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG; ++ hints.ai_family = af; ++ hints.ai_socktype = SOCK_DGRAM; + ++ if ( getaddrinfo(NULL, "tftp", &hints, &aiptr) != 0 ) { ++ perror("tftp: getaddrinfo"); ++ exit(1); ++ } + if (f >= 0) + close(f); +- f = socket(AF_INET, SOCK_DGRAM, 0); +- if (f < 0) { +- perror("tftp: socket"); +- exit(3); ++ ++ /* At least one valid adress found. */ ++ for ( ai=aiptr; ai ; ai=ai->ai_next ) { ++ if ( (f = socket(ai->ai_family, SOCK_DGRAM, 0)) < 0 ) ++ /* Failure, next candidate. */ ++ continue; ++ ++ memset(&s_in, 0, sizeof(s_in)); ++ s_in.ss_family = ai->ai_family; ++ if ( bind(f, (struct sockaddr *)&s_in, ++ (s_in.ss_family == AF_INET6) ++ ? sizeof(struct sockaddr_in6) ++ : sizeof(struct sockaddr_in)) ++ < 0) { ++ /* Could not bind. */ ++ close(f); ++ continue; ++ } ++ /* Successfully bound to a socket. ++ * Now ai != NULL. */ ++ break; + } +- memset(&s_in, 0, sizeof(s_in)); +- s_in.sin_family = AF_INET; +- if (bind(f, (struct sockaddr *)&s_in, sizeof (s_in)) < 0) { +- perror("tftp: bind"); +- exit(1); ++ ++ if ( ai == NULL ) { ++ /* Could not bind or create the socket. */ ++ perror("tftp: socket/bind"); ++ exit(3); + } ++ freeaddrinfo(aiptr); + } + + int +@@ -179,7 +220,7 @@ main(int argc, char *argv[]) + fprintf(stderr, "tftp: udp/tftp: unknown service\n"); + exit(1); + } +- initsock(); ++ initsock(AF_UNSPEC); + strcpy(mode, "netascii"); + mysignal(SIGINT, intr); + if (argc > 1) { +@@ -197,7 +238,7 @@ + void + setpeer(int argc, char *argv[]) + { +- struct hostent *host; ++ struct addrinfo hints, *aiptr, *ai; + size_t len; + + if (argc < 2) { +@@ -216,25 +257,37 @@ setpeer(int argc, char *argv[]) + printf("usage: %s host-name [port]\n", argv[0]); + return; + } +- host = gethostbyname(argv[1]); +- if (host) { +- s_inn.sin_family = host->h_addrtype; +- if (host->h_length > (int)sizeof(s_inn.sin_addr)) { +- host->h_length = sizeof(s_inn.sin_addr); +- } +- memcpy(&s_inn.sin_addr, host->h_addr, host->h_length); +- strncpy(hostname, host->h_name, sizeof(hostname)); +- hostname[sizeof(hostname)-1] = 0; +- } +- else { +- s_inn.sin_family = AF_INET; +- if (!inet_aton(argv[1], &s_inn.sin_addr)) { +- connected = 0; +- printf("%s: unknown host\n", argv[1]); +- return; +- } +- strcpy(hostname, argv[1]); ++ ++ memset(&hints, 0, sizeof(hints)); ++ hints.ai_flags = AI_ALL | AI_V4MAPPED | AI_ADDRCONFIG | AI_CANONNAME; ++ hints.ai_family = AF_UNSPEC; ++ hints.ai_socktype = SOCK_DGRAM; ++ ++ if ( getaddrinfo(argv[1], "tftp", &hints, &aiptr) ) { ++ connected = 0; ++ printf("%s: unknown host\n", argv[1]); ++ return; + } ++ ++ /* Choose first applicable address. */ ++ ai = aiptr; ++ ++ while ( ai && (ai->ai_family != AF_INET6) ++ && (ai->ai_family != AF_INET) ) ++ ai = ai->ai_next; ++ ++ if ( ai == NULL ) { ++ connected = 0; ++ printf("%s: unknown host\n", argv[1]); ++ freeaddrinfo(aiptr); ++ return; ++ } ++ ++ memcpy(&s_inn, ai->ai_addr, ai->ai_addrlen); ++ connected = ai->ai_family; ++ strcpy(hostname, aiptr->ai_canonname); ++ freeaddrinfo(aiptr); ++ + port = sp->s_port; + if (argc == 3) { + port = atoi(argv[2]); +@@ -245,7 +298,8 @@ setpeer(int argc, char *argv[]) + } + port = htons(port); + } +- connected = 1; ++ /* Test and set socket for the relevant address family. */ ++ initsock(connected); + } + + struct modes { +@@ -346,7 +400,8 @@ put(int argc, char *argv[]) + targ = argv[argc - 1]; + if (strchr(argv[argc - 1], ':')) { + char *cp; +- struct hostent *hp; ++ struct addrinfo hints, *aiptr, *ai; ++ int status; + + for (n = 1; n < argc - 1; n++) + if (strchr(argv[n], ':')) { +@@ -356,19 +411,34 @@ put(int argc, char *argv[]) + cp = argv[argc - 1]; + targ = strchr(cp, ':'); + *targ++ = 0; +- hp = gethostbyname(cp); +- if (hp == NULL) { ++ ++ memset(&hints, 0, sizeof(hints)); ++ hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG | AI_CANONNAME; ++ hints.ai_family = connected; //AF_UNSPEC; ++ hints.ai_socktype = SOCK_DGRAM; ++ ++ status = getaddrinfo(cp, "tftp", &hints, &aiptr); ++ if ( status != 0 ) { + fprintf(stderr, "tftp: %s: ", cp); + herror((char *)NULL); + return; + } +- if (hp->h_length > (int)sizeof(s_inn.sin_addr)) { +- hp->h_length = sizeof(s_inn.sin_addr); ++ ++ ai = aiptr; ++ while ( ai && (ai->ai_family != AF_INET) ++ && (ai->ai_family != AF_INET6) ) ++ ai = ai->ai_next; ++ if ( ai == NULL ) { ++ freeaddrinfo(aiptr); ++ fprintf(stderr, "tftp: %s: ", cp); ++ herror((char *)NULL); ++ return; + } +- memcpy(&s_inn.sin_addr, hp->h_addr, hp->h_length); +- s_inn.sin_family = hp->h_addrtype; +- connected = 1; +- strncpy(hostname, hp->h_name, sizeof(hostname)); ++ ++ memcpy(&s_inn, ai->ai_addr, ai->ai_addrlen); ++ strncpy(hostname, aiptr->ai_canonname, sizeof(hostname)); ++ connected = ai->ai_family; ++ freeaddrinfo(aiptr); + hostname[sizeof(hostname)-1] = 0; + } + if (!connected) { +@@ -386,7 +456,8 @@ put(int argc, char *argv[]) + if (verbose) + printf("putting %s to %s:%s [%s]\n", + ccp, hostname, targ, mode); +- s_inn.sin_port = port; ++ ++ set_port(&s_inn); + sendfile(fd, targ, mode); + return; + } +@@ -404,7 +475,8 @@ put(int argc, char *argv[]) + if (verbose) + printf("putting %s to %s:%s [%s]\n", + argv[n], hostname, targ, mode); +- s_inn.sin_port = port; ++ ++ set_port(&s_inn); + sendfile(fd, targ, mode); + } + } +@@ -453,22 +525,36 @@ get(int argc, char *argv[]) + if (src == NULL) + src = argv[n]; + else { +- struct hostent *hp; ++ struct addrinfo hints, *aiptr, *ai; + + *src++ = 0; +- hp = gethostbyname(argv[n]); +- if (hp == NULL) { ++ memset(&hints, 0, sizeof(hints)); ++ hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG | AI_CANONNAME; ++ hints.ai_family = connected; // AF_UNSPEC; ++ hints.ai_socktype = SOCK_DGRAM; ++ ++ if ( getaddrinfo(argv[n], "tftp", &hints, &aiptr) ) { + fprintf(stderr, "tftp: %s: ", argv[n]); +- herror(NULL); ++ herror((char *)NULL); + continue; + } +- if (hp->h_length > (int)sizeof(s_inn.sin_addr)) { +- hp->h_length = sizeof(s_inn.sin_addr); ++ ++ ai = aiptr; ++ while ( ai && (ai->ai_family != AF_INET) ++ && (ai->ai_family != AF_INET6) ) ++ ai = ai->ai_next; ++ if ( ai == NULL ) { ++ freeaddrinfo(aiptr); ++ fprintf(stderr, "tftp: %s: ", argv[n]); ++ herror((char *)NULL); ++ continue; + } +- memcpy(&s_inn.sin_addr, hp->h_addr, hp->h_length); +- s_inn.sin_family = hp->h_addrtype; +- connected = 1; +- strncpy(hostname, hp->h_name, sizeof(hostname)); ++ ++ memcpy(&s_inn, ai->ai_addr, ai->ai_addrlen); ++ connected = ai->ai_family; ++ strncpy(hostname, aiptr->ai_canonname, ++ sizeof(hostname)); ++ freeaddrinfo(aiptr); + hostname[sizeof(hostname)-1] = 0; + } + if (argc < 4) { +@@ -481,7 +567,8 @@ get(int argc, char *argv[]) + if (verbose) + printf("getting from %s:%s to %s [%s]\n", + hostname, src, cp, mode); +- s_inn.sin_port = port; ++ ++ set_port(&s_inn); + recvfile(fd, src, mode); + break; + } +@@ -494,7 +581,8 @@ get(int argc, char *argv[]) + if (verbose) + printf("getting from %s:%s to %s [%s]\n", + hostname, src, cp, mode); +- s_inn.sin_port = port; ++ ++ set_port(&s_inn); + recvfile(fd, src, mode); + } + } +--- netkit-tftp-0.17.debian/tftp/tftp.c ++++ netkit-tftp-0.17/tftp/tftp.c +@@ -61,7 +61,7 @@ + + #include "../version.h" + +-extern struct sockaddr_in s_inn; /* filled in by main */ ++extern struct sockaddr_storage s_inn; /* filled in by main */ + extern int f; /* the opened socket */ + extern int trace; + extern int verbose; +@@ -100,6 +100,31 @@ + } + + /* ++ * Copy port number, hiding dependency on IPv4 and IPv6. ++ */ ++static ++void ++copy_port(struct sockaddr_storage *to, struct sockaddr_storage *from) ++{ ++ if ( from->ss_family == AF_INET6 ) { ++ if ( to->ss_family == AF_INET6 ) ++ ((struct sockaddr_in6 *) to)->sin6_port = ++ ((struct sockaddr_in6 *) from)->sin6_port; ++ else ++ ((struct sockaddr_in *) to)->sin_port = ++ ((struct sockaddr_in6 *) from)->sin6_port; ++ } ++ else { ++ if ( to->ss_family == AF_INET6 ) ++ ((struct sockaddr_in6 *) to)->sin6_port = ++ ((struct sockaddr_in *) from)->sin_port; ++ else ++ ((struct sockaddr_in *) to)->sin_port = ++ ((struct sockaddr_in *) from)->sin_port; ++ } ++} ++ ++/* + * Send the requested file. + */ + void +@@ -111,7 +136,7 @@ sendfile(int fd, char *name, char *mode) + volatile u_int16_t block = 0; + int n; + volatile unsigned long amount = 0; +- struct sockaddr_in from; ++ struct sockaddr_storage from; + socklen_t fromlen; + volatile int convert; /* true if doing nl->crlf conversion */ + FILE *file; +@@ -143,8 +168,11 @@ sendfile(int fd, char *name, char *mode) + send_data: + if (trace) + tpacket("sent", dp, size + 4); +- n = sendto(f, dp, size + 4, 0, +- (struct sockaddr *)&s_inn, sizeof(s_inn)); ++ ++ n = sendto(f, dp, size + 4, 0, (struct sockaddr *)&s_inn, ++ (s_inn.ss_family == AF_INET6) ++ ? sizeof(struct sockaddr_in6) ++ : sizeof(struct sockaddr_in)); + if (n != size + 4) { + perror("tftp: sendto"); + goto abort; +@@ -162,7 +190,9 @@ send_data: + perror("tftp: recvfrom"); + goto abort; + } +- s_inn.sin_port = from.sin_port; /* added */ ++ ++ copy_port(&s_inn, &from); ++ + if (trace) + tpacket("received", ap, n); + /* should verify packet came from server */ +@@ -198,11 +228,11 @@ send_data: + block++; + } while (1); + abort: +- initsock(); + fclose(file); + stopclock(); + if (amount > 0) + printstats("Sent", amount); ++ initsock(s_inn.ss_family); /* Synchronize address family. */ + } + + /* +@@ -217,7 +247,7 @@ recvfile(int fd, char *name, char *mode) + volatile u_int16_t block = 1; + int n; + volatile unsigned long amount = 0; +- struct sockaddr_in from; ++ struct sockaddr_storage from; + socklen_t fromlen; + volatile int firsttrip = 1; + FILE *file; +@@ -245,8 +275,13 @@ recvfile(int fd, char *name, char *mode) + send_ack: + if (trace) + tpacket("sent", ap, size); +- if (sendto(f, ackbuf, size, 0, (struct sockaddr *)&s_inn, +- sizeof (s_inn)) != size) { ++ ++ n = sendto(f, ackbuf, size, 0, (struct sockaddr *)&s_inn, ++ (s_inn.ss_family == AF_INET6) ++ ? sizeof(struct sockaddr_in6) ++ : sizeof(struct sockaddr_in)); ++ ++ if ( n != size) { + alarm(0); + perror("tftp: sendto"); + goto abort; +@@ -264,7 +299,9 @@ send_ack: + perror("tftp: recvfrom"); + goto abort; + } +- s_inn.sin_port = from.sin_port; /* added */ ++ ++ copy_port(&s_inn, &from); ++ + if (trace) + tpacket("received", dp, n); + /* should verify client address */ +@@ -299,16 +336,18 @@ send_ack: + + ap->th_opcode = htons((u_short)ACK); /* has seen err msg */ + ap->th_block = htons((u_short)block); +- (void) sendto(f, ackbuf, 4, 0, (struct sockaddr *)&s_inn, sizeof(s_inn)); ++ (void) sendto(f, ackbuf, 4, 0, (struct sockaddr *)&s_inn, ++ (s_inn.ss_family == AF_INET6) ++ ? sizeof(struct sockaddr_in6) ++ : sizeof(struct sockaddr_in)); + + abort: +- initsock(); +- + write_behind(file, convert); /* flush last buffer */ + fclose(file); + stopclock(); + if (amount > 0) + printstats("Received", amount); ++ initsock(s_inn.ss_family); /* Synchronize address family. */ + } + + int +@@ -369,8 +408,11 @@ nak(int error) + length = strlen(pe->e_msg) + 4; + if (trace) + tpacket("sent", tp, length); +- if (sendto(f, ackbuf, length, 0, (struct sockaddr *)&s_inn, +- sizeof (s_inn)) != length) ++ if ( sendto(f, ackbuf, length, 0, (struct sockaddr *)&s_inn, ++ (s_inn.ss_family == AF_INET6) ++ ? sizeof(struct sockaddr_in6) ++ : sizeof(struct sockaddr_in)) ++ != length ) + perror("nak"); + } + diff -Nru netkit-tftp-0.17/debian/patches/series netkit-tftp-0.17/debian/patches/series --- netkit-tftp-0.17/debian/patches/series 1970-01-01 01:00:00.000000000 +0100 +++ netkit-tftp-0.17/debian/patches/series 2010-04-17 03:27:15.000000000 +0200 @@ -0,0 +1,11 @@ +05_mrules.diff +10_tftp_manpage.diff +15_tftpd_manpage.diff +20_tftp_main_c.diff +30_tftp_tftp_c.diff +33_tftp_tftpsubs_c.diff +37_tftp_tftpsubs_h.diff +40_tftpd_tftpd_c.diff +50_tftpd_inet6.diff +55_tftpsubs_inet6.diff +60_tftp_inet6.diff diff -Nru netkit-tftp-0.17/debian/rules netkit-tftp-0.17/debian/rules --- netkit-tftp-0.17/debian/rules 2010-04-17 03:41:02.000000000 +0200 +++ netkit-tftp-0.17/debian/rules 2010-04-17 02:55:10.000000000 +0200 @@ -17,7 +17,7 @@ if [ ! -f MCONFIG ]; then \ ./configure; \ - sed -e 's/^CFLAGS=\(.*\)$$/CFLAGS= -g \1/' MCONFIG \ + sed -e 's/^CFLAGS=\(.*\)$$/CFLAGS= -g \1 -fno-strict-aliasing/' MCONFIG \ > MCONFIG.new; \ mv MCONFIG.new MCONFIG; \ fi @@ -38,7 +38,7 @@ install: build dh_testdir dh_testroot - dh_clean -k + dh_prep dh_installdirs $(MAKE) -C tftp install INSTALLROOT=`pwd`/debian/tftp \ @@ -73,6 +73,7 @@ dh_fixperms # You may want to make some executables suid here. # dh_makeshlibs + dh_strip dh_installdeb # dh_perl dh_shlibdeps diff -Nru netkit-tftp-0.17/debian/source/format netkit-tftp-0.17/debian/source/format --- netkit-tftp-0.17/debian/source/format 1970-01-01 01:00:00.000000000 +0100 +++ netkit-tftp-0.17/debian/source/format 2010-04-17 03:41:04.000000000 +0200 @@ -0,0 +1 @@ +3.0 (quilt) diff -Nru netkit-tftp-0.17/debian/tftpd.examples netkit-tftp-0.17/debian/tftpd.examples --- netkit-tftp-0.17/debian/tftpd.examples 1970-01-01 01:00:00.000000000 +0100 +++ netkit-tftp-0.17/debian/tftpd.examples 2010-02-09 01:06:31.000000000 +0100 @@ -0,0 +1 @@ +debian/local/tftpd.xinetd diff -Nru netkit-tftp-0.17/debian/tftpd.postinst netkit-tftp-0.17/debian/tftpd.postinst --- netkit-tftp-0.17/debian/tftpd.postinst 2010-04-17 03:41:02.000000000 +0200 +++ netkit-tftp-0.17/debian/tftpd.postinst 2010-04-17 02:25:39.000000000 +0200 @@ -1,6 +1,8 @@ -#!/bin/sh -e +#!/bin/sh # $Id: tftpd.postinst,v 1.1 1999/10/26 04:43:01 herbert Exp $ +set -e + case "$1" in abort-upgrade | abort-deconfigure | abort-remove) update-inetd --enable tftp diff -Nru netkit-tftp-0.17/debian/tftpd.postrm netkit-tftp-0.17/debian/tftpd.postrm --- netkit-tftp-0.17/debian/tftpd.postrm 2010-04-17 03:41:02.000000000 +0200 +++ netkit-tftp-0.17/debian/tftpd.postrm 2010-04-17 02:25:39.000000000 +0200 @@ -1,6 +1,8 @@ -#!/bin/sh -e +#!/bin/sh # $Id: tftpd.postrm,v 1.2 2002/12/22 05:17:12 herbert Exp $ +set -e + case "$1" in abort-install | abort-upgrade | upgrade | failed-upgrade | disappear) ;; diff -Nru netkit-tftp-0.17/debian/watch netkit-tftp-0.17/debian/watch --- netkit-tftp-0.17/debian/watch 1970-01-01 01:00:00.000000000 +0100 +++ netkit-tftp-0.17/debian/watch 2010-02-04 15:20:43.000000000 +0100 @@ -0,0 +1,2 @@ +version=3 +http://ftp.uk.linux.org/pub/linux/Networking/netkit/netkit-tftp-([.0-9]+)\.tar\.gz debian uupdate diff -Nru netkit-tftp-0.17/MRULES netkit-tftp-0.17/MRULES --- netkit-tftp-0.17/MRULES 2010-04-17 03:41:02.000000000 +0200 +++ netkit-tftp-0.17/MRULES 2000-07-22 20:59:18.000000000 +0200 @@ -1,8 +1,8 @@ # Standard compilation rules (don't use make builtins) %.o: %.c - $(CC) $(CFLAGS) $< -c + $(CC) $(CFLAGS) -I../include $< -c %.o: %.cc - $(CC) $(CFLAGS) $< -c + $(CC) $(CFLAGS) -I../include $< -c diff -Nru netkit-tftp-0.17/tftp/main.c netkit-tftp-0.17/tftp/main.c --- netkit-tftp-0.17/tftp/main.c 2010-04-17 03:41:02.000000000 +0200 +++ netkit-tftp-0.17/tftp/main.c 2000-07-22 21:06:29.000000000 +0200 @@ -69,7 +69,7 @@ #define TIMEOUT 5 /* secs between rexmt's */ struct sockaddr_in s_inn; -int f = -1; +int f; int trace; int verbose; int rexmtval = TIMEOUT; @@ -151,11 +151,17 @@ static struct cmd *getcmd(const char *name); static char *tail(char *filename); -void initsock() { +int +main(int argc, char *argv[]) +{ struct sockaddr_in s_in; + int top; - if (f >= 0) - close(f); + sp = getservbyname("tftp", "udp"); + if (sp == 0) { + fprintf(stderr, "tftp: udp/tftp: unknown service\n"); + exit(1); + } f = socket(AF_INET, SOCK_DGRAM, 0); if (f < 0) { perror("tftp: socket"); @@ -167,19 +173,6 @@ perror("tftp: bind"); exit(1); } -} - -int -main(int argc, char *argv[]) -{ - int top; - - sp = getservbyname("tftp", "udp"); - if (sp == 0) { - fprintf(stderr, "tftp: udp/tftp: unknown service\n"); - exit(1); - } - initsock(); strcpy(mode, "netascii"); mysignal(SIGINT, intr); if (argc > 1) { @@ -209,10 +202,7 @@ argc = margc; argv = margv; } - /* We should have 2 or 3 args now: the cmd and its - * parameters. If not, we bail out here. - */ - if (argc != 2 && argc != 3) { + if (argc > 3) { printf("usage: %s host-name [port]\n", argv[0]); return; } diff -Nru netkit-tftp-0.17/tftp/tftp.1 netkit-tftp-0.17/tftp/tftp.1 --- netkit-tftp-0.17/tftp/tftp.1 2010-04-17 03:41:02.000000000 +0200 +++ netkit-tftp-0.17/tftp/tftp.1 2000-07-31 01:57:10.000000000 +0200 @@ -84,7 +84,7 @@ protocol, unlike the .Tn FTP protocol, -does not maintain connections betwen transfers; thus, the +does not maintain connections betweeen transfers; thus, the .Cm connect command does not actually create a connection, but merely remembers what host is to be used for transfers. diff -Nru netkit-tftp-0.17/tftp/tftp.c netkit-tftp-0.17/tftp/tftp.c --- netkit-tftp-0.17/tftp/tftp.c 2010-04-17 03:41:02.000000000 +0200 +++ netkit-tftp-0.17/tftp/tftp.c 2000-07-22 21:06:29.000000000 +0200 @@ -174,13 +174,19 @@ goto abort; } if (ap->th_opcode == ACK) { + volatile int j = 0; + if (ap->th_block == block) { break; } /* On an error, try to synchronize * both sides. */ - synchnet(f, trace); + j = synchnet(f); + if (j && trace) { + printf("discarded %d packets\n", + j); + } if (ap->th_block == (block-1)) { goto send_data; } @@ -191,14 +197,10 @@ } else { amount += size; - if (size != SEGSIZE) { - break; - } } block++; - } while (1); + } while (size == SEGSIZE); abort: - initsock(); fclose(file); stopclock(); if (amount > 0) @@ -276,13 +278,18 @@ goto abort; } if (dp->th_opcode == DATA) { + volatile int j = 0; + if (dp->th_block == block) { break; /* have next packet */ } /* On an error, try to synchronize * both sides. */ - synchnet(f, trace); + j = synchnet(f); + if (j && trace) { + printf("discarded %d packets\n", j); + } if (dp->th_block == (block-1)) { goto send_ack; /* resend ack */ } @@ -296,14 +303,10 @@ } amount += size; } while (size == SEGSIZE); - +abort: /* ok to ack, since user */ ap->th_opcode = htons((u_short)ACK); /* has seen err msg */ ap->th_block = htons((u_short)block); (void) sendto(f, ackbuf, 4, 0, (struct sockaddr *)&s_inn, sizeof(s_inn)); - -abort: - initsock(); - write_behind(file, convert); /* flush last buffer */ fclose(file); stopclock(); diff -Nru netkit-tftp-0.17/tftp/tftpsubs.c netkit-tftp-0.17/tftp/tftpsubs.c --- netkit-tftp-0.17/tftp/tftpsubs.c 2010-04-17 03:41:02.000000000 +0200 +++ netkit-tftp-0.17/tftp/tftpsubs.c 2000-07-22 21:06:29.000000000 +0200 @@ -249,8 +249,8 @@ * when trace is active). */ -void -synchnet(int f /* socket to flush */, int trace) +int +synchnet(int f /* socket to flush */) { int i, j = 0; char rbuf[PKTSIZE]; @@ -265,10 +265,7 @@ (void) recvfrom(f, rbuf, sizeof (rbuf), 0, (struct sockaddr *)&from, &fromlen); } else { - if (j && trace) { - printf("discarded %d packets\n", j); - } - return; + return(j); } } } diff -Nru netkit-tftp-0.17/tftp/tftpsubs.h netkit-tftp-0.17/tftp/tftpsubs.h --- netkit-tftp-0.17/tftp/tftpsubs.h 2010-04-17 03:41:02.000000000 +0200 +++ netkit-tftp-0.17/tftp/tftpsubs.h 2000-07-22 21:06:29.000000000 +0200 @@ -1,7 +1,6 @@ #define PKTSIZE SEGSIZE+4 /* should be moved to tftp.h */ -void initsock(void); -void synchnet(int, int); +int synchnet(int); struct tftphdr *r_init(void); struct tftphdr *w_init(void); int readit(FILE *file, struct tftphdr **dpp, int convert); diff -Nru netkit-tftp-0.17/tftpd/tftpd.8 netkit-tftp-0.17/tftpd/tftpd.8 --- netkit-tftp-0.17/tftpd/tftpd.8 2010-04-17 03:41:02.000000000 +0200 +++ netkit-tftp-0.17/tftpd/tftpd.8 2000-07-31 01:57:10.000000000 +0200 @@ -42,8 +42,6 @@ Trivial File Transfer Protocol server .Sh SYNOPSIS .Nm tftpd -.Op Fl n -.Op Fl s .Op Ar directory ... .Sh DESCRIPTION .Nm Tftpd @@ -113,18 +111,6 @@ can be used to ensure that replies go out from the correct address. These considerations are important, because most tftp clients will reject reply packets that appear to come from an unexpected address. -.Pp -The options are: -.Bl -tag -width Ds -.It Fl n -Suppresses negative acknowledgement of requests for nonexistent relative -filenames. -.It Fl s -All absolute filenames are treated as if they were preceded by the first -directory argument, or -.Pa /tftpboot -if there is none. -.El .Sh SEE ALSO .Xr tftp 1 , .Xr inetd 8 diff -Nru netkit-tftp-0.17/tftpd/tftpd.c netkit-tftp-0.17/tftpd/tftpd.c --- netkit-tftp-0.17/tftpd/tftpd.c 2010-04-17 03:41:02.000000000 +0200 +++ netkit-tftp-0.17/tftpd/tftpd.c 2000-07-29 20:37:21.000000000 +0200 @@ -92,11 +92,8 @@ static struct sockaddr_in from; static socklen_t fromlen; -static const char *default_dirs[] = { "/tftpboot", 0 }; -static const char **dirs = default_dirs; - -static int suppress_naks; -static int secure_tftp; +#define MAXARG 4 +static char *dirs[MAXARG+1]; int main(int ac, char **av) @@ -108,25 +105,12 @@ register struct tftphdr *tp; register int n = 0; int on = 1; - int ch; + ac--; av++; + if (ac==0) dirs[0] = "/tftpboot"; /* default directory */ + while (ac-- > 0 && n < MAXARG) + dirs[n++] = *av++; openlog("tftpd", LOG_PID, LOG_DAEMON); - opterr = 0; - while ((ch = getopt(ac, av, "ns")) != EOF) { - switch (ch) { - case 'n': - suppress_naks = 1; - break; - case 's': - secure_tftp = 1; - break; - default: - syslog(LOG_ERR, "unknown option -%c", ch); - exit(1); - } - } - - if (av[optind]) dirs = (const char **) &av[optind]; if (ioctl(0, FIONBIO, &on) < 0) { syslog(LOG_ERR, "ioctl(FIONBIO): %m\n"); exit(1); @@ -295,12 +279,6 @@ } ecode = (*pf->f_validate)(filename, tp->th_opcode); if (ecode) { - /* - * Avoid storms of naks to a RRQ broadcast for a relative - * bootfile pathname from a diskless Sun. - */ - if (suppress_naks && *filename != '/' && ecode == ENOTFOUND) - exit(0); nak(ecode); exit(1); } @@ -332,17 +310,13 @@ struct stat stbuf; int fd; const char *cp; - const char **dirp; + char **dirp; syslog(LOG_NOTICE, "tftpd: trying to get file: %s\n", filename); - if (*filename != '/' || secure_tftp) { + if (*filename != '/') { syslog(LOG_NOTICE, "tftpd: serving file from %s\n", dirs[0]); - /*chdir(dirs[0]);*/ - if ( chdir(dirs[0]) < 0 ) - return (EACCESS); - while (*filename == '/') - filename++; + chdir(dirs[0]); } else { for (dirp = dirs; *dirp; dirp++) if (strncmp(filename, *dirp, strlen(*dirp)) == 0) @@ -392,8 +366,7 @@ if ((stbuf.st_mode & S_IWOTH) == 0) return (EACCESS); } - - fd = open(filename, mode == RRQ ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT, 0600); + fd = open(filename, mode == RRQ ? O_RDONLY : O_WRONLY|O_TRUNC); if (fd < 0) return (errno + 100); file = fdopen(fd, (mode == RRQ)? "r":"w"); @@ -468,7 +441,7 @@ break; } /* Re-synchronize with the other side */ - (void) synchnet(peer, 0); + (void) synchnet(peer); if (ap->th_block == (block -1)) { goto send_data; } @@ -533,7 +506,7 @@ break; /* normal */ } /* Re-synchronize with the other side */ - (void) synchnet(peer, 0); + (void) synchnet(peer); if (dp->th_block == (block-1)) goto send_ack; /* rexmit */ }
signature.asc
Description: Digital signature