Re: [resend] ipv6 support for tftp

2012-04-27 Thread Brad Smith

On 19/04/12 2:54 PM, Gleydson Soares wrote:

On Tue, Mar 06, 2012 at 09:32:47AM +, Stuart Henderson wrote:

On 2011/01/22 19:40, Gleydson Soares wrote:

can anyone test this diff? your feedback will be most welcome
On Wed, Sep 08, 2010 at 11:51:11AM -0300, Gleydson Soares wrote:

hi,

- ipv6 support for tftp client.

based on an old itojun's diff.


weerd@ pointed out this old diff - here's a slightly updated version;
only minor tweaks from gsoares@ version: whitespace nits in some lines
touched in the diff, and I rewrote the manpage diff.

works for me against usr/sbin/tftpd; any comments?


Tested against OpenBSD's tftpd and dnsmasq. Working fine for me.

--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.



Re: [resend] ipv6 support for tftp

2012-04-27 Thread Gleydson Soares
On Fri, Apr 27, 2012 at 12:34:19PM -0400, Brad Smith wrote:
 Tested against OpenBSD's tftpd and dnsmasq. Working fine for me.

here is an updated version of the diff.

- setpeer0() and setpeer() were renamed accordingly for clarity and 
consistency. (requested by henning@)
- fix memleak(call freeaddrinfo() to release *res0)
- checks against valid server port number
- man page tweaked based on points by sthen@ and jmc@

this diff has been OK by sthen@ jmc@ henning@
i will commit it tomorrow if no objections till there.
? 1
? tftp_ipv6_3.diff
Index: main.c
===
RCS file: /cvs/src/usr.bin/tftp/main.c,v
retrieving revision 1.30
diff -u -p -r1.30 main.c
--- main.c  27 Oct 2009 23:59:44 -  1.30
+++ main.c  24 Apr 2012 15:39:19 -
@@ -68,7 +68,8 @@ void   put(int, char **);
 voidquit(int, char **);
 voidsetascii(int, char **);
 voidsetbinary(int, char **);
-voidsetpeer(int, char **);
+voidsetpeer(char *, char *);
+voidparsearg(int, char **);
 voidsetrexmt(int, char **);
 voidsettimeout(int, char **);
 voidsettrace(int, char **);
@@ -86,9 +87,8 @@ static __dead void command(void);
 struct cmd *getcmd(char *);
 char   *tail(char *);
 
-struct sockaddr_in  peeraddr;
+struct sockaddr_storage peeraddr;
 int f;
-short   port;
 int trace;
 int verbose;
 int connected;
@@ -98,7 +98,6 @@ intmargc;
 char   *margv[MAXARGV+1];
 char   *prompt = tftp;
 voidintr(int);
-struct servent *sp;
 int rexmtval = TIMEOUT;
 int maxtimeout = 5 * TIMEOUT;
 charhostname[MAXHOSTNAMELEN];
@@ -134,7 +133,7 @@ struct cmd {
 };
 
 struct cmd cmdtab[] = {
-   { connect,chelp,  setpeer },
+   { connect,chelp,  parsearg },
{ mode,   mhelp,  modecmd },
{ put,shelp,  put },
{ get,rhelp,  get },
@@ -170,26 +169,14 @@ structmodes {
 int
 main(int argc, char *argv[])
 {
-   struct sockaddr_in  s_in;
-
-   /* socket, bind */
-   sp = getservbyname(tftp, udp);
-   if (sp == 0)
-   errx(1, udp/tftp: unknown service);
-   f = socket(AF_INET, SOCK_DGRAM, 0);
-   if (f  0)
-   err(3, socket);
-   bzero((char *)s_in, sizeof(s_in));
-   s_in.sin_family = AF_INET;
-   if (bind(f, (struct sockaddr *)s_in, sizeof(s_in))  0)
-   err(1, bind);
+   f = -1;
 
/* set default transfer mode */
strlcpy(mode, netascii, sizeof(mode));
 
/* set peer if given */
if (argc  1)
-   setpeer(argc, argv);
+   parsearg(argc, argv);
 
/* catch SIGINT */
signal(SIGINT, intr);
@@ -205,11 +192,73 @@ main(int argc, char *argv[])
 }
 
 void
-setpeer(int argc, char *argv[])
+setpeer(char *host, char *port)
 {
-   struct hostent  *host;
-   const char  *errstr;
+   struct addrinfo hints, *res0, *res;
+   int error;
+   struct sockaddr_storage ss;
+   char *cause = unknown;
+
+   if (connected) {
+   close(f);
+   f = -1;
+   }
+   connected = 0;
+
+   memset(hints, 0, sizeof(hints));
+   hints.ai_family = PF_UNSPEC;
+   hints.ai_socktype = SOCK_DGRAM;
+   hints.ai_protocol = IPPROTO_UDP;
+   hints.ai_flags = AI_CANONNAME;
+   if (!port)
+   port = tftp;
+   error = getaddrinfo(host, port, hints, res0);
+   if (error) {
+   warnx(%s, gai_strerror(error));
+   return;
+   }
+
+   for (res = res0; res; res = res-ai_next) {
+   if (res-ai_addrlen  sizeof(peeraddr))
+   continue;
+   f = socket(res-ai_family, res-ai_socktype, res-ai_protocol);
+   if (f  0) {
+   cause = socket;
+   continue;
+   }
 
+   memset(ss, 0, sizeof(ss));
+   ss.ss_family = res-ai_family;
+   ss.ss_len = res-ai_addrlen;
+   if (bind(f, (struct sockaddr *)ss, ss.ss_len)  0) {
+   cause = bind;
+   close(f);
+   f = -1;
+   continue;
+   }
+
+   break;
+   }
+
+   if (f  0)
+   warn(%s, cause);
+   else {
+   /* res-ai_addr = sizeof(peeraddr) is guaranteed */
+   memcpy(peeraddr, res-ai_addr, res-ai_addrlen);
+   if (res-ai_canonname) {
+   (void) strncpy(hostname, res-ai_canonname,
+   

Re: [resend] ipv6 support for tftp

2012-04-19 Thread Gleydson Soares
On Tue, Mar 06, 2012 at 09:32:47AM +, Stuart Henderson wrote:
 On 2011/01/22 19:40, Gleydson Soares wrote:
  can anyone test this diff? your feedback will be most welcome
  On Wed, Sep 08, 2010 at 11:51:11AM -0300, Gleydson Soares wrote:
   hi,
   
   - ipv6 support for tftp client.
   
   based on an old itojun's diff.
 
 weerd@ pointed out this old diff - here's a slightly updated version;
 only minor tweaks from gsoares@ version: whitespace nits in some lines
 touched in the diff, and I rewrote the manpage diff.
 
 works for me against usr/sbin/tftpd; any comments?

anyone willing to give this diff a go?
Index: main.c
===
RCS file: /cvs/src/usr.bin/tftp/main.c,v
retrieving revision 1.30
diff -u -p -r1.30 main.c
--- main.c  27 Oct 2009 23:59:44 -  1.30
+++ main.c  19 Apr 2012 18:47:44 -
@@ -68,6 +68,7 @@ void   put(int, char **);
 voidquit(int, char **);
 voidsetascii(int, char **);
 voidsetbinary(int, char **);
+voidsetpeer0(char *, char *);
 voidsetpeer(int, char **);
 voidsetrexmt(int, char **);
 voidsettimeout(int, char **);
@@ -86,9 +87,8 @@ static __dead void command(void);
 struct cmd *getcmd(char *);
 char   *tail(char *);
 
-struct sockaddr_in  peeraddr;
+struct sockaddr_storage peeraddr;
 int f;
-short   port;
 int trace;
 int verbose;
 int connected;
@@ -98,7 +98,6 @@ intmargc;
 char   *margv[MAXARGV+1];
 char   *prompt = tftp;
 voidintr(int);
-struct servent *sp;
 int rexmtval = TIMEOUT;
 int maxtimeout = 5 * TIMEOUT;
 charhostname[MAXHOSTNAMELEN];
@@ -170,19 +169,7 @@ struct modes {
 int
 main(int argc, char *argv[])
 {
-   struct sockaddr_in  s_in;
-
-   /* socket, bind */
-   sp = getservbyname(tftp, udp);
-   if (sp == 0)
-   errx(1, udp/tftp: unknown service);
-   f = socket(AF_INET, SOCK_DGRAM, 0);
-   if (f  0)
-   err(3, socket);
-   bzero((char *)s_in, sizeof(s_in));
-   s_in.sin_family = AF_INET;
-   if (bind(f, (struct sockaddr *)s_in, sizeof(s_in))  0)
-   err(1, bind);
+   f = -1;
 
/* set default transfer mode */
strlcpy(mode, netascii, sizeof(mode));
@@ -205,11 +192,69 @@ main(int argc, char *argv[])
 }
 
 void
-setpeer(int argc, char *argv[])
+setpeer0(char *host, char *port)
 {
-   struct hostent  *host;
-   const char  *errstr;
+   struct addrinfo hints, *res0, *res;
+   int error;
+   struct sockaddr_storage ss;
+   char *cause = unknown;
+
+   if (connected) {
+   close(f);
+   f = -1;
+   connected = 0;
+   }
+
+   memset(hints, 0, sizeof(hints));
+   hints.ai_family = PF_UNSPEC;
+   hints.ai_socktype = SOCK_DGRAM;
+   hints.ai_protocol = IPPROTO_UDP;
+   hints.ai_flags = AI_CANONNAME;
+   if (!port)
+   port = tftp;
+   error = getaddrinfo(host, port, hints, res0);
+   if (error) {
+   warnx(%s, gai_strerror(error));
+   return;
+   }
+
+   for (res = res0; res; res = res-ai_next) {
+   f = socket(res-ai_family, res-ai_socktype, res-ai_protocol);
+   if (f  0) {
+   cause = socket;
+   continue;
+   }
+
+   memset(ss, 0, sizeof(ss));
+   ss.ss_family = res-ai_family;
+   ss.ss_len = res-ai_addrlen;
+   if (bind(f, (struct sockaddr *)ss, ss.ss_len)  0) {
+   cause = bind;
+   close(f);
+   f = -1;
+   continue;
+   }
+
+   break;
+   }
+
+   if (f  0)
+   warn(%s, cause);
+   else {
+   memcpy(peeraddr, res-ai_addr, res-ai_addrlen);
+   if (res-ai_canonname) {
+   (void) strncpy(hostname, res-ai_canonname,
+   sizeof(hostname));
+   } else
+   (void) strncpy(hostname, host, sizeof(hostname));
+   hostname[sizeof(hostname)-1] = 0;
+   connected = 1;
+   }
+}
 
+void
+setpeer(int argc, char *argv[])
+{
if (argc  2) {
strlcpy(line, Connect , sizeof(line));
printf((to) );
@@ -223,32 +268,10 @@ setpeer(int argc, char *argv[])
printf(usage: %s [host [port]]\n, argv[0]);
return;
}
-   if (inet_aton(argv[1], peeraddr.sin_addr) != 0) {
-

Re: [resend] ipv6 support for tftp

2012-03-06 Thread Stuart Henderson
On 2011/01/22 19:40, Gleydson Soares wrote:
 can anyone test this diff? your feedback will be most welcome
 On Wed, Sep 08, 2010 at 11:51:11AM -0300, Gleydson Soares wrote:
  hi,
  
  - ipv6 support for tftp client.
  
  based on an old itojun's diff.

weerd@ pointed out this old diff - here's a slightly updated version;
only minor tweaks from gsoares@ version: whitespace nits in some lines
touched in the diff, and I rewrote the manpage diff.

works for me against usr/sbin/tftpd; any comments?

Index: tftp.1
===
RCS file: /cvs/src/usr.bin/tftp/tftp.1,v
retrieving revision 1.19
diff -u -p -r1.19 tftp.1
--- tftp.1  1 Mar 2012 03:47:19 -   1.19
+++ tftp.1  6 Mar 2012 09:30:31 -
@@ -156,6 +156,10 @@ When using the
 argument, the
 .Ar host
 will be used as the default host for future transfers.
+A
+.Ar host
+specified as a numeric IPv6 address must be wrapped in square brackets:
+.Ar [host]:filename .
 If
 .Ar remotename
 is specified, the file is stored remotely as
Index: main.c
===
RCS file: /cvs/src/usr.bin/tftp/main.c,v
retrieving revision 1.30
diff -u -p -r1.30 main.c
--- main.c  27 Oct 2009 23:59:44 -  1.30
+++ main.c  6 Mar 2012 09:30:31 -
@@ -68,6 +68,7 @@ void   put(int, char **);
 voidquit(int, char **);
 voidsetascii(int, char **);
 voidsetbinary(int, char **);
+voidsetpeer0(char *, char *);
 voidsetpeer(int, char **);
 voidsetrexmt(int, char **);
 voidsettimeout(int, char **);
@@ -86,9 +87,8 @@ static __dead void command(void);
 struct cmd *getcmd(char *);
 char   *tail(char *);
 
-struct sockaddr_in  peeraddr;
+struct sockaddr_storage peeraddr;
 int f;
-short   port;
 int trace;
 int verbose;
 int connected;
@@ -98,7 +98,6 @@ intmargc;
 char   *margv[MAXARGV+1];
 char   *prompt = tftp;
 voidintr(int);
-struct servent *sp;
 int rexmtval = TIMEOUT;
 int maxtimeout = 5 * TIMEOUT;
 charhostname[MAXHOSTNAMELEN];
@@ -170,19 +169,7 @@ struct modes {
 int
 main(int argc, char *argv[])
 {
-   struct sockaddr_in  s_in;
-
-   /* socket, bind */
-   sp = getservbyname(tftp, udp);
-   if (sp == 0)
-   errx(1, udp/tftp: unknown service);
-   f = socket(AF_INET, SOCK_DGRAM, 0);
-   if (f  0)
-   err(3, socket);
-   bzero((char *)s_in, sizeof(s_in));
-   s_in.sin_family = AF_INET;
-   if (bind(f, (struct sockaddr *)s_in, sizeof(s_in))  0)
-   err(1, bind);
+   f = -1;
 
/* set default transfer mode */
strlcpy(mode, netascii, sizeof(mode));
@@ -205,11 +192,69 @@ main(int argc, char *argv[])
 }
 
 void
-setpeer(int argc, char *argv[])
+setpeer0(char *host, char *port)
 {
-   struct hostent  *host;
-   const char  *errstr;
+   struct addrinfo hints, *res0, *res;
+   int error;
+   struct sockaddr_storage ss;
+   char *cause = unknown;
+
+   if (connected) {
+   close(f);
+   f = -1;
+   connected = 0;
+   }
+
+   memset(hints, 0, sizeof(hints));
+   hints.ai_family = PF_UNSPEC;
+   hints.ai_socktype = SOCK_DGRAM;
+   hints.ai_protocol = IPPROTO_UDP;
+   hints.ai_flags = AI_CANONNAME;
+   if (!port)
+   port = tftp;
+   error = getaddrinfo(host, port, hints, res0);
+   if (error) {
+   warnx(%s, gai_strerror(error));
+   return;
+   }
+
+   for (res = res0; res; res = res-ai_next) {
+   f = socket(res-ai_family, res-ai_socktype, res-ai_protocol);
+   if (f  0) {
+   cause = socket;
+   continue;
+   }
+
+   memset(ss, 0, sizeof(ss));
+   ss.ss_family = res-ai_family;
+   ss.ss_len = res-ai_addrlen;
+   if (bind(f, (struct sockaddr *)ss, ss.ss_len)  0) {
+   cause = bind;
+   close(f);
+   f = -1;
+   continue;
+   }
+
+   break;
+   }
+
+   if (f  0)
+   warn(%s, cause);
+   else {
+   memcpy(peeraddr, res-ai_addr, res-ai_addrlen);
+   if (res-ai_canonname) {
+   (void) strncpy(hostname, res-ai_canonname,
+   sizeof(hostname));
+   } else
+   (void) strncpy(hostname, host, sizeof(hostname));
+   

[resend] ipv6 support for tftp

2011-01-22 Thread Gleydson Soares
can anyone test this diff? your feedback will be most welcome
On Wed, Sep 08, 2010 at 11:51:11AM -0300, Gleydson Soares wrote:
 hi,
 
 - ipv6 support for tftp client.
 
 based on an old itojun's diff.

Index: tftpsubs.c
===
RCS file: /cvs/src/usr.bin/tftp/tftpsubs.c,v
retrieving revision 1.14
diff -u -r1.14 tftpsubs.c
--- tftpsubs.c  27 Oct 2009 23:59:44 -  1.14
+++ tftpsubs.c  8 Sep 2010 14:01:19 -
@@ -258,7 +258,7 @@
 {
int i, j = 0;
charrbuf[SEGSIZE_MIN];
-   struct sockaddr_in  from;
+   struct sockaddr_storage from;
socklen_t   fromlen;
 
for (;;) {
Index: tftp.c
===
RCS file: /cvs/src/usr.bin/tftp/tftp.c,v
retrieving revision 1.22
diff -u -r1.22 tftp.c
--- tftp.c  27 Oct 2009 23:59:44 -  1.22
+++ tftp.c  8 Sep 2010 14:01:39 -
@@ -58,7 +58,7 @@
 #include tftpsubs.h
 
 static int makerequest(int, const char *, struct tftphdr *, const char *);
-static voidnak(int);
+static voidnak(int, struct sockaddr *);
 static voidtpacket(const char *, struct tftphdr *, int);
 static voidstartclock(void);
 static voidstopclock(void);
@@ -67,7 +67,7 @@
 static voidoack(struct tftphdr *, int, int);
 static int oack_set(const char *, const char *);
 
-extern struct sockaddr_in   peeraddr;  /* filled in by main */
+extern struct sockaddr_storage  peeraddr;  /* filled in by main */
 extern int  f; /* the opened socket */
 extern int  trace;
 extern int  verbose;
@@ -124,7 +124,8 @@
 sendfile(int fd, char *name, char *mode)
 {
struct tftphdr  *dp, *ap; /* data and ack packets */
-   struct sockaddr_in   from;
+   struct sockaddr_storage  from;
+   struct sockaddr_storage peer;
struct pollfdpfd[1];
unsigned longamount;
socklen_tfromlen;
@@ -138,6 +139,7 @@
convert = !strcmp(mode, netascii);
block = 0;
amount = 0;
+   memcpy(peer, peeraddr, peeraddr.ss_len);
 
do {
/* read data from file */
@@ -146,7 +148,7 @@
else {
size = readit(file, dp, convert, segment_size);
if (size  0) {
-   nak(errno + 100);
+   nak(errno + 100, (struct sockaddr *)peer);
break;
}
dp-th_opcode = htons((u_short)DATA);
@@ -164,8 +166,8 @@
if (trace)
tpacket(sent, dp, size + 4);
if (sendto(f, dp, size + 4, 0,
-   (struct sockaddr *)peeraddr,
-   sizeof(peeraddr)) != size + 4) {
+   (struct sockaddr *)peer,
+   peer.ss_len) != size + 4) {
warn(sendto);
goto abort;
}
@@ -202,7 +204,19 @@
warn(recvfrom);
goto abort;
}
-   peeraddr.sin_port = from.sin_port;  /* added */
+   switch (peer.ss_family) {   /* added */
+   case AF_INET:
+   ((struct sockaddr_in *)peer)-sin_port =
+   ((struct sockaddr_in *)from)-sin_port;
+   break;
+   case AF_INET6:
+   ((struct sockaddr_in6 *)peer)-sin6_port =
+   ((struct sockaddr_in6 *)from)-sin6_port;
+   break;
+   default:
+   /* unsupported */
+   break;
+   }
if (trace)
tpacket(received, ap, n);
 
@@ -256,7 +270,8 @@
 recvfile(int fd, char *name, char *mode)
 {
struct tftphdr  *dp, *ap; /* data and ack packets */
-   struct sockaddr_in   from;
+   struct sockaddr_storage  from;
+   struct sockaddr_storage peer;
struct pollfdpfd[1];
unsigned longamount;
socklen_tfromlen;
@@ -273,6 +288,7 @@
block = 1;
amount = 0;
firsttrip = 1;
+   memcpy(peer, peeraddr, peeraddr.ss_len);
 
 options:
do {
@@ -298,8 +314,8 @@
if (trace)
tpacket(sent, ap, size);
if (sendto(f, ackbuf, size, 0,
-