Re: [U-Boot] [RFC PATCH 6/8] net: TFTP over IPv6

2015-11-05 Thread Joe Hershberger
Hi Chris,

On Wed, Nov 4, 2015 at 2:42 AM, Chris Packham  wrote:
> On Wed, Nov 4, 2015 at 8:43 AM, Joe Hershberger
>  wrote:
>> Hi Chris,
>>
>> On Tue, Nov 3, 2015 at 4:15 AM, Chris Packham  
>> wrote:
>>> On Tue, Nov 3, 2015 at 9:43 AM, Joe Hershberger
>>>  wrote:
 Hi Chris,

 On Mon, Oct 12, 2015 at 2:43 AM, Chris Packham  
 wrote:
> Add support for UDP/TFTP over IPv6.
>
> Signed-off-by: Chris Packham 
> ---
> One problem with the [hostIpAddr:]fileName syntax is that IPv6 addresses
> contains colons. So tftp_start() would be confused by 'tftpboot6
> $loadaddr 2001:db8::1:zImage'. It is probably possible to change the
> parsing to separate the host from the filename by parsing from the end
> (i.e. use strrchr() instead of strchr()) but then there are error cases
> that may not be handled correctly (e.g. omitting the filename).

 I think we should just change the filename separator for tftp6. How about 
 ','?

>>>
>>> The other strategy that is often used is to use square brackets to
>>> separate the address from other data e.g. http://[2001:db8::1]:8080/.
>>> Maybe that is a better (or at least more common) approach.
>>
>> Sounds good to me - I'm all for going with a common approach.
>>
>
> One wrinkle I've just discovered with this suggestion is the command
> line help text. Consider the following
>
>   => help tftpboot
>   Usage:
>   tftpboot [loadAddress] [[hostIPaddr:]bootfilename]
>
> Now the IPv6 version if the above syntax is supported
>   => help tftpboot6
>   Usage:
>   tftpboot6 [loadAddress] [[[hostIP6addr]:]bootfilename]
>
> How do we convey that the address before the bootfilename is optional
> but if it is specified square brackets are required around the
> address. In other words
>
>   tftpboot6 (valid)
>   tftpboot6 zImage (valid)
>   tftpboot6 2001:db8::1:zImage (invalid)
>   tftpboot6 [2001:db8::1]:zImage (valid)
>
> I still like the square bracket syntax and I'm still planning on
> implementing it but I thought I'd raise this now to give people a
> chance to object.

That's unfortunate.

Maybe something like

tftpboot6 [loadAddress] [[\[hostIP6addr\]:]bootfilename]

or

tftpboot6 [loadAddress] [['['hostIP6addr']':]bootfilename]

I don't love either, but does it get the message across?

-Joe
___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


Re: [U-Boot] [RFC PATCH 6/8] net: TFTP over IPv6

2015-11-04 Thread Angga
Chris

Have a look at https://www.ietf.org/rfc/rfc2732.txt, might give you some hints.


Kind regards

Angga

-Original Message-
From: Chris Packham [mailto:judge.pack...@gmail.com] 
Sent: Wednesday, 4 November 2015 9:43 p.m.
To: Joe Hershberger
Cc: u-boot; Joe Hershberger; jp.tos...@acksys.fr; Hanna Hawa; Angga
Subject: Re: [U-Boot] [RFC PATCH 6/8] net: TFTP over IPv6

On Wed, Nov 4, 2015 at 8:43 AM, Joe Hershberger  
wrote:
> Hi Chris,
>
> On Tue, Nov 3, 2015 at 4:15 AM, Chris Packham  wrote:
>> On Tue, Nov 3, 2015 at 9:43 AM, Joe Hershberger 
>>  wrote:
>>> Hi Chris,
>>>
>>> On Mon, Oct 12, 2015 at 2:43 AM, Chris Packham  
>>> wrote:
>>>> Add support for UDP/TFTP over IPv6.
>>>>
>>>> Signed-off-by: Chris Packham 
>>>> ---
>>>> One problem with the [hostIpAddr:]fileName syntax is that IPv6 
>>>> addresses contains colons. So tftp_start() would be confused by 
>>>> 'tftpboot6 $loadaddr 2001:db8::1:zImage'. It is probably possible 
>>>> to change the parsing to separate the host from the filename by 
>>>> parsing from the end (i.e. use strrchr() instead of strchr()) but 
>>>> then there are error cases that may not be handled correctly (e.g. 
>>>> omitting the filename).
>>>
>>> I think we should just change the filename separator for tftp6. How about 
>>> ','?
>>>
>>
>> The other strategy that is often used is to use square brackets to 
>> separate the address from other data e.g. http://[2001:db8::1]:8080/.
>> Maybe that is a better (or at least more common) approach.
>
> Sounds good to me - I'm all for going with a common approach.
>

One wrinkle I've just discovered with this suggestion is the command line help 
text. Consider the following

  => help tftpboot
  Usage:
  tftpboot [loadAddress] [[hostIPaddr:]bootfilename]

Now the IPv6 version if the above syntax is supported
  => help tftpboot6
  Usage:
  tftpboot6 [loadAddress] [[[hostIP6addr]:]bootfilename]

How do we convey that the address before the bootfilename is optional but if it 
is specified square brackets are required around the address. In other words

  tftpboot6 (valid)
  tftpboot6 zImage (valid)
  tftpboot6 2001:db8::1:zImage (invalid)
  tftpboot6 [2001:db8::1]:zImage (valid)

I still like the square bracket syntax and I'm still planning on implementing 
it but I thought I'd raise this now to give people a chance to object.
___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


Re: [U-Boot] [RFC PATCH 6/8] net: TFTP over IPv6

2015-11-04 Thread Chris Packham
On Wed, Nov 4, 2015 at 8:43 AM, Joe Hershberger
 wrote:
> Hi Chris,
>
> On Tue, Nov 3, 2015 at 4:15 AM, Chris Packham  wrote:
>> On Tue, Nov 3, 2015 at 9:43 AM, Joe Hershberger
>>  wrote:
>>> Hi Chris,
>>>
>>> On Mon, Oct 12, 2015 at 2:43 AM, Chris Packham  
>>> wrote:
 Add support for UDP/TFTP over IPv6.

 Signed-off-by: Chris Packham 
 ---
 One problem with the [hostIpAddr:]fileName syntax is that IPv6 addresses
 contains colons. So tftp_start() would be confused by 'tftpboot6
 $loadaddr 2001:db8::1:zImage'. It is probably possible to change the
 parsing to separate the host from the filename by parsing from the end
 (i.e. use strrchr() instead of strchr()) but then there are error cases
 that may not be handled correctly (e.g. omitting the filename).
>>>
>>> I think we should just change the filename separator for tftp6. How about 
>>> ','?
>>>
>>
>> The other strategy that is often used is to use square brackets to
>> separate the address from other data e.g. http://[2001:db8::1]:8080/.
>> Maybe that is a better (or at least more common) approach.
>
> Sounds good to me - I'm all for going with a common approach.
>

One wrinkle I've just discovered with this suggestion is the command
line help text. Consider the following

  => help tftpboot
  Usage:
  tftpboot [loadAddress] [[hostIPaddr:]bootfilename]

Now the IPv6 version if the above syntax is supported
  => help tftpboot6
  Usage:
  tftpboot6 [loadAddress] [[[hostIP6addr]:]bootfilename]

How do we convey that the address before the bootfilename is optional
but if it is specified square brackets are required around the
address. In other words

  tftpboot6 (valid)
  tftpboot6 zImage (valid)
  tftpboot6 2001:db8::1:zImage (invalid)
  tftpboot6 [2001:db8::1]:zImage (valid)

I still like the square bracket syntax and I'm still planning on
implementing it but I thought I'd raise this now to give people a
chance to object.
___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


Re: [U-Boot] [RFC PATCH 6/8] net: TFTP over IPv6

2015-11-03 Thread Joe Hershberger
Hi Jean-Pierre,

On Tue, Nov 3, 2015 at 4:41 AM, Jean-Pierre Tosoni  wrote:
> Hi all,
>
>> -Message d'origine-
>> De : Joe Hershberger [mailto:joe.hershber...@gmail.com]
>> Envoyé : lundi 2 novembre 2015 21:44
>> À : Chris Packham
>> Cc : u-boot; Joe Hershberger; jp.tos...@acksys.fr; Hanna Hawa; Angga
>> Objet : Re: [U-Boot] [RFC PATCH 6/8] net: TFTP over IPv6
>>
> (...)
>> > ---
>> > One problem with the [hostIpAddr:]fileName syntax is that IPv6
>> > addresses contains colons. So tftp_start() would be confused by
>> > 'tftpboot6 $loadaddr 2001:db8::1:zImage'. It is probably possible to
>> > change the parsing to separate the host from the filename by parsing
>> > from the end (i.e. use strrchr() instead of strchr()) but then there
>> > are error cases that may not be handled correctly (e.g. omitting the
>> filename).
>>
>> I think we should just change the filename separator for tftp6. How about
>> ','?
>>
>
> How about a '/' to make it look like an URL ? More intuitive maybe.

That might work, but it also could be part of the path to the file
itself. It doesn't seem good to be ambiguous about that or to require
2001:db8::1//kernel.tgz

-Joe
___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


Re: [U-Boot] [RFC PATCH 6/8] net: TFTP over IPv6

2015-11-03 Thread Joe Hershberger
Hi Chris,

On Tue, Nov 3, 2015 at 4:15 AM, Chris Packham  wrote:
> On Tue, Nov 3, 2015 at 9:43 AM, Joe Hershberger
>  wrote:
>> Hi Chris,
>>
>> On Mon, Oct 12, 2015 at 2:43 AM, Chris Packham  
>> wrote:
>>> Add support for UDP/TFTP over IPv6.
>>>
>>> Signed-off-by: Chris Packham 
>>> ---
>>> One problem with the [hostIpAddr:]fileName syntax is that IPv6 addresses
>>> contains colons. So tftp_start() would be confused by 'tftpboot6
>>> $loadaddr 2001:db8::1:zImage'. It is probably possible to change the
>>> parsing to separate the host from the filename by parsing from the end
>>> (i.e. use strrchr() instead of strchr()) but then there are error cases
>>> that may not be handled correctly (e.g. omitting the filename).
>>
>> I think we should just change the filename separator for tftp6. How about 
>> ','?
>>
>
> The other strategy that is often used is to use square brackets to
> separate the address from other data e.g. http://[2001:db8::1]:8080/.
> Maybe that is a better (or at least more common) approach.

Sounds good to me - I'm all for going with a common approach.

>>>  common/cmd_net.c | 13 
>>>  include/net6.h   |  4 
>>>  net/net.c|  3 +++
>>>  net/net6.c   | 64 
>>> 
>>>  net/tftp.c   | 37 
>>>  5 files changed, 121 insertions(+)

--8< snip 8<--
___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


Re: [U-Boot] [RFC PATCH 6/8] net: TFTP over IPv6

2015-11-03 Thread Jean-Pierre Tosoni
Hi all,

> -Message d'origine-
> De : Joe Hershberger [mailto:joe.hershber...@gmail.com]
> Envoyé : lundi 2 novembre 2015 21:44
> À : Chris Packham
> Cc : u-boot; Joe Hershberger; jp.tos...@acksys.fr; Hanna Hawa; Angga
> Objet : Re: [U-Boot] [RFC PATCH 6/8] net: TFTP over IPv6
> 
(...)
> > ---
> > One problem with the [hostIpAddr:]fileName syntax is that IPv6
> > addresses contains colons. So tftp_start() would be confused by
> > 'tftpboot6 $loadaddr 2001:db8::1:zImage'. It is probably possible to
> > change the parsing to separate the host from the filename by parsing
> > from the end (i.e. use strrchr() instead of strchr()) but then there
> > are error cases that may not be handled correctly (e.g. omitting the
> filename).
> 
> I think we should just change the filename separator for tftp6. How about
> ','?
> 

How about a '/' to make it look like an URL ? More intuitive maybe.

(...)

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


Re: [U-Boot] [RFC PATCH 6/8] net: TFTP over IPv6

2015-11-03 Thread Chris Packham
On Tue, Nov 3, 2015 at 9:43 AM, Joe Hershberger
 wrote:
> Hi Chris,
>
> On Mon, Oct 12, 2015 at 2:43 AM, Chris Packham  
> wrote:
>> Add support for UDP/TFTP over IPv6.
>>
>> Signed-off-by: Chris Packham 
>> ---
>> One problem with the [hostIpAddr:]fileName syntax is that IPv6 addresses
>> contains colons. So tftp_start() would be confused by 'tftpboot6
>> $loadaddr 2001:db8::1:zImage'. It is probably possible to change the
>> parsing to separate the host from the filename by parsing from the end
>> (i.e. use strrchr() instead of strchr()) but then there are error cases
>> that may not be handled correctly (e.g. omitting the filename).
>
> I think we should just change the filename separator for tftp6. How about ','?
>

The other strategy that is often used is to use square brackets to
separate the address from other data e.g. http://[2001:db8::1]:8080/.
Maybe that is a better (or at least more common) approach.

>>  common/cmd_net.c | 13 
>>  include/net6.h   |  4 
>>  net/net.c|  3 +++
>>  net/net6.c   | 64 
>> 
>>  net/tftp.c   | 37 
>>  5 files changed, 121 insertions(+)
>>
>> diff --git a/common/cmd_net.c b/common/cmd_net.c
>> index 271f91d..3541599 100644
>> --- a/common/cmd_net.c
>> +++ b/common/cmd_net.c
>> @@ -42,6 +42,19 @@ U_BOOT_CMD(
>> "[loadAddress] [[hostIPaddr:]bootfilename]"
>>  );
>>
>> +#ifdef CONFIG_CMD_NET6
>> +int do_tftpb6(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
>> +{
>> +   return netboot_common(TFTP6, cmdtp, argc, argv);
>> +}
>> +
>> +U_BOOT_CMD(
>> +   tftpboot6,  3,  1,  do_tftpb6,
>> +   "boot image via network using TFTP protocol",
>> +   "[loadAddress] [bootfilename]"
>> +);
>> +#endif
>> +
>>  #ifdef CONFIG_CMD_TFTPPUT
>>  int do_tftpput(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
>>  {
>> diff --git a/include/net6.h b/include/net6.h
>> index a0374df..df6d38e 100644
>> --- a/include/net6.h
>> +++ b/include/net6.h
>> @@ -264,6 +264,10 @@ void ping6_start(void);
>>  void ping6_receive(struct ethernet_hdr *et, struct ip6_hdr *ip6,
>>   int len);
>>
>> +/* Transmit UDP packet using IPv6, performing neighbour discovery if needed 
>> */
>> +int net_send_udp_packet6(uchar *ether, struct in6_addr *dest,
>> +   int dport, int sport, int len);
>> +
>>  /* handler for incoming IPv6 echo packet */
>>  void net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6,
>> int len);
>> diff --git a/net/net.c b/net/net.c
>> index 349a18e..9e682b4 100644
>> --- a/net/net.c
>> +++ b/net/net.c
>> @@ -454,6 +454,9 @@ restart:
>>  #ifdef CONFIG_CMD_TFTPPUT
>> case TFTPPUT:
>>  #endif
>> +#ifdef CONFIG_CMD_NET6
>> +   case TFTP6:
>> +#endif
>> /* always use ARP to get server ethernet address */
>> tftp_start(protocol);
>> break;
>> diff --git a/net/net6.c b/net/net6.c
>> index 2315704..f5e272a 100644
>> --- a/net/net6.c
>> +++ b/net/net6.c
>> @@ -322,6 +322,50 @@ ip6_add_hdr(uchar *xip, struct in6_addr *src, struct 
>> in6_addr *dest,
>> return sizeof(struct ip6_hdr);
>>  }
>>
>> +int
>> +net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport, int 
>> sport, int len)
>> +{
>> +   uchar *pkt;
>> +   struct udp_hdr *udp;
>> +
>> +   udp = (struct udp_hdr *)((uchar *)net_tx_packet + net_eth_hdr_size() 
>> + IP6_HDR_SIZE);
>> +
>> +   udp->udp_dst = htons(dport);
>> +   udp->udp_src = htons(sport);
>> +   udp->udp_len = htons(len + IP6_UDPHDR_SIZE);
>> +   /* checksum */
>> +   udp->udp_xsum = 0;
>> +   udp->udp_xsum = csum_ipv6_magic(&net_ip6, dest, len + 
>> IP6_UDPHDR_SIZE,
>> +   IPPROTO_UDP, csum_partial((__u8 *)udp, len + 
>> IP6_UDPHDR_SIZE, 0));
>> +
>> +   /* if MAC address was not discovered yet, save the packet and do 
>> neighbour discovery */
>> +   if (memcmp(ether, net_null_ethaddr, 6) == 0) {
>> +   net_copy_ip6(&net_nd_sol_packet_ip6, dest);
>> +   net_nd_packet_mac = ether;
>> +
>> +   pkt = net_nd_tx_packet;
>> +   pkt += net_set_ether(pkt, net_nd_packet_mac, PROT_IP6);
>> +   pkt += ip6_add_hdr(pkt, &net_ip6, dest, IPPROTO_UDP, 64, len 
>> + IP6_UDPHDR_SIZE);
>> +   memcpy(pkt, (uchar *)udp, len + IP6_UDPHDR_SIZE);
>> +
>> +   /* size of the waiting packet */
>> +   net_nd_tx_packet_size = (pkt - net_nd_tx_packet) + 
>> IP6_UDPHDR_SIZE + len;
>> +
>> +   /* and do the neighbor solicitation */
>> +   net_nd_try = 1;
>> +   net_nd_timer_start = get_timer(0);
>> +   ip6_NDISC_Request();
>> +   return 1;   /* waiting */
>> +   }
>> +
>> +   pkt = (uchar *)net_tx_packet;
>> +   

Re: [U-Boot] [RFC PATCH 6/8] net: TFTP over IPv6

2015-11-02 Thread Joe Hershberger
Hi Chris,

On Mon, Oct 12, 2015 at 2:43 AM, Chris Packham  wrote:
> Add support for UDP/TFTP over IPv6.
>
> Signed-off-by: Chris Packham 
> ---
> One problem with the [hostIpAddr:]fileName syntax is that IPv6 addresses
> contains colons. So tftp_start() would be confused by 'tftpboot6
> $loadaddr 2001:db8::1:zImage'. It is probably possible to change the
> parsing to separate the host from the filename by parsing from the end
> (i.e. use strrchr() instead of strchr()) but then there are error cases
> that may not be handled correctly (e.g. omitting the filename).

I think we should just change the filename separator for tftp6. How about ','?

>  common/cmd_net.c | 13 
>  include/net6.h   |  4 
>  net/net.c|  3 +++
>  net/net6.c   | 64 
> 
>  net/tftp.c   | 37 
>  5 files changed, 121 insertions(+)
>
> diff --git a/common/cmd_net.c b/common/cmd_net.c
> index 271f91d..3541599 100644
> --- a/common/cmd_net.c
> +++ b/common/cmd_net.c
> @@ -42,6 +42,19 @@ U_BOOT_CMD(
> "[loadAddress] [[hostIPaddr:]bootfilename]"
>  );
>
> +#ifdef CONFIG_CMD_NET6
> +int do_tftpb6(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> +   return netboot_common(TFTP6, cmdtp, argc, argv);
> +}
> +
> +U_BOOT_CMD(
> +   tftpboot6,  3,  1,  do_tftpb6,
> +   "boot image via network using TFTP protocol",
> +   "[loadAddress] [bootfilename]"
> +);
> +#endif
> +
>  #ifdef CONFIG_CMD_TFTPPUT
>  int do_tftpput(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
>  {
> diff --git a/include/net6.h b/include/net6.h
> index a0374df..df6d38e 100644
> --- a/include/net6.h
> +++ b/include/net6.h
> @@ -264,6 +264,10 @@ void ping6_start(void);
>  void ping6_receive(struct ethernet_hdr *et, struct ip6_hdr *ip6,
>   int len);
>
> +/* Transmit UDP packet using IPv6, performing neighbour discovery if needed 
> */
> +int net_send_udp_packet6(uchar *ether, struct in6_addr *dest,
> +   int dport, int sport, int len);
> +
>  /* handler for incoming IPv6 echo packet */
>  void net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6,
> int len);
> diff --git a/net/net.c b/net/net.c
> index 349a18e..9e682b4 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -454,6 +454,9 @@ restart:
>  #ifdef CONFIG_CMD_TFTPPUT
> case TFTPPUT:
>  #endif
> +#ifdef CONFIG_CMD_NET6
> +   case TFTP6:
> +#endif
> /* always use ARP to get server ethernet address */
> tftp_start(protocol);
> break;
> diff --git a/net/net6.c b/net/net6.c
> index 2315704..f5e272a 100644
> --- a/net/net6.c
> +++ b/net/net6.c
> @@ -322,6 +322,50 @@ ip6_add_hdr(uchar *xip, struct in6_addr *src, struct 
> in6_addr *dest,
> return sizeof(struct ip6_hdr);
>  }
>
> +int
> +net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport, int 
> sport, int len)
> +{
> +   uchar *pkt;
> +   struct udp_hdr *udp;
> +
> +   udp = (struct udp_hdr *)((uchar *)net_tx_packet + net_eth_hdr_size() 
> + IP6_HDR_SIZE);
> +
> +   udp->udp_dst = htons(dport);
> +   udp->udp_src = htons(sport);
> +   udp->udp_len = htons(len + IP6_UDPHDR_SIZE);
> +   /* checksum */
> +   udp->udp_xsum = 0;
> +   udp->udp_xsum = csum_ipv6_magic(&net_ip6, dest, len + IP6_UDPHDR_SIZE,
> +   IPPROTO_UDP, csum_partial((__u8 *)udp, len + IP6_UDPHDR_SIZE, 
> 0));
> +
> +   /* if MAC address was not discovered yet, save the packet and do 
> neighbour discovery */
> +   if (memcmp(ether, net_null_ethaddr, 6) == 0) {
> +   net_copy_ip6(&net_nd_sol_packet_ip6, dest);
> +   net_nd_packet_mac = ether;
> +
> +   pkt = net_nd_tx_packet;
> +   pkt += net_set_ether(pkt, net_nd_packet_mac, PROT_IP6);
> +   pkt += ip6_add_hdr(pkt, &net_ip6, dest, IPPROTO_UDP, 64, len 
> + IP6_UDPHDR_SIZE);
> +   memcpy(pkt, (uchar *)udp, len + IP6_UDPHDR_SIZE);
> +
> +   /* size of the waiting packet */
> +   net_nd_tx_packet_size = (pkt - net_nd_tx_packet) + 
> IP6_UDPHDR_SIZE + len;
> +
> +   /* and do the neighbor solicitation */
> +   net_nd_try = 1;
> +   net_nd_timer_start = get_timer(0);
> +   ip6_NDISC_Request();
> +   return 1;   /* waiting */
> +   }
> +
> +   pkt = (uchar *)net_tx_packet;
> +   pkt += net_set_ether(pkt, ether, PROT_IP6);
> +   pkt += ip6_add_hdr(pkt, &net_ip6, dest, IPPROTO_UDP, 64, len + 
> IP6_UDPHDR_SIZE);
> +   (void) eth_send(net_tx_packet, (pkt - net_tx_packet) + 
> IP6_UDPHDR_SIZE + len);
> +
> +   return 0;   /* transmitted */
> +}
> +
>  void net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len)
>  {
> struct in_addr

[U-Boot] [RFC PATCH 6/8] net: TFTP over IPv6

2015-10-12 Thread Chris Packham
Add support for UDP/TFTP over IPv6.

Signed-off-by: Chris Packham 
---
One problem with the [hostIpAddr:]fileName syntax is that IPv6 addresses
contains colons. So tftp_start() would be confused by 'tftpboot6
$loadaddr 2001:db8::1:zImage'. It is probably possible to change the
parsing to separate the host from the filename by parsing from the end
(i.e. use strrchr() instead of strchr()) but then there are error cases
that may not be handled correctly (e.g. omitting the filename).

 common/cmd_net.c | 13 
 include/net6.h   |  4 
 net/net.c|  3 +++
 net/net6.c   | 64 
 net/tftp.c   | 37 
 5 files changed, 121 insertions(+)

diff --git a/common/cmd_net.c b/common/cmd_net.c
index 271f91d..3541599 100644
--- a/common/cmd_net.c
+++ b/common/cmd_net.c
@@ -42,6 +42,19 @@ U_BOOT_CMD(
"[loadAddress] [[hostIPaddr:]bootfilename]"
 );
 
+#ifdef CONFIG_CMD_NET6
+int do_tftpb6(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+   return netboot_common(TFTP6, cmdtp, argc, argv);
+}
+
+U_BOOT_CMD(
+   tftpboot6,  3,  1,  do_tftpb6,
+   "boot image via network using TFTP protocol",
+   "[loadAddress] [bootfilename]"
+);
+#endif
+
 #ifdef CONFIG_CMD_TFTPPUT
 int do_tftpput(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
diff --git a/include/net6.h b/include/net6.h
index a0374df..df6d38e 100644
--- a/include/net6.h
+++ b/include/net6.h
@@ -264,6 +264,10 @@ void ping6_start(void);
 void ping6_receive(struct ethernet_hdr *et, struct ip6_hdr *ip6,
  int len);
 
+/* Transmit UDP packet using IPv6, performing neighbour discovery if needed */
+int net_send_udp_packet6(uchar *ether, struct in6_addr *dest,
+   int dport, int sport, int len);
+
 /* handler for incoming IPv6 echo packet */
 void net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6,
int len);
diff --git a/net/net.c b/net/net.c
index 349a18e..9e682b4 100644
--- a/net/net.c
+++ b/net/net.c
@@ -454,6 +454,9 @@ restart:
 #ifdef CONFIG_CMD_TFTPPUT
case TFTPPUT:
 #endif
+#ifdef CONFIG_CMD_NET6
+   case TFTP6:
+#endif
/* always use ARP to get server ethernet address */
tftp_start(protocol);
break;
diff --git a/net/net6.c b/net/net6.c
index 2315704..f5e272a 100644
--- a/net/net6.c
+++ b/net/net6.c
@@ -322,6 +322,50 @@ ip6_add_hdr(uchar *xip, struct in6_addr *src, struct 
in6_addr *dest,
return sizeof(struct ip6_hdr);
 }
 
+int
+net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport, int 
sport, int len)
+{
+   uchar *pkt;
+   struct udp_hdr *udp;
+
+   udp = (struct udp_hdr *)((uchar *)net_tx_packet + net_eth_hdr_size() + 
IP6_HDR_SIZE);
+
+   udp->udp_dst = htons(dport);
+   udp->udp_src = htons(sport);
+   udp->udp_len = htons(len + IP6_UDPHDR_SIZE);
+   /* checksum */
+   udp->udp_xsum = 0;
+   udp->udp_xsum = csum_ipv6_magic(&net_ip6, dest, len + IP6_UDPHDR_SIZE,
+   IPPROTO_UDP, csum_partial((__u8 *)udp, len + IP6_UDPHDR_SIZE, 
0));
+
+   /* if MAC address was not discovered yet, save the packet and do 
neighbour discovery */
+   if (memcmp(ether, net_null_ethaddr, 6) == 0) {
+   net_copy_ip6(&net_nd_sol_packet_ip6, dest);
+   net_nd_packet_mac = ether;
+
+   pkt = net_nd_tx_packet;
+   pkt += net_set_ether(pkt, net_nd_packet_mac, PROT_IP6);
+   pkt += ip6_add_hdr(pkt, &net_ip6, dest, IPPROTO_UDP, 64, len + 
IP6_UDPHDR_SIZE);
+   memcpy(pkt, (uchar *)udp, len + IP6_UDPHDR_SIZE);
+
+   /* size of the waiting packet */
+   net_nd_tx_packet_size = (pkt - net_nd_tx_packet) + 
IP6_UDPHDR_SIZE + len;
+
+   /* and do the neighbor solicitation */
+   net_nd_try = 1;
+   net_nd_timer_start = get_timer(0);
+   ip6_NDISC_Request();
+   return 1;   /* waiting */
+   }
+
+   pkt = (uchar *)net_tx_packet;
+   pkt += net_set_ether(pkt, ether, PROT_IP6);
+   pkt += ip6_add_hdr(pkt, &net_ip6, dest, IPPROTO_UDP, 64, len + 
IP6_UDPHDR_SIZE);
+   (void) eth_send(net_tx_packet, (pkt - net_tx_packet) + IP6_UDPHDR_SIZE 
+ len);
+
+   return 0;   /* transmitted */
+}
+
 void net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len)
 {
struct in_addr zero_ip = {.s_addr = 0 };
@@ -368,6 +412,26 @@ void net_ip6_handler(struct ethernet_hdr *et, struct 
ip6_hdr *ip6, int len)
}
break;
 
+   case IPPROTO_UDP:
+   udp = (struct udp_hdr *)(((uchar *)ip6) + IP6_HDR_SIZE);
+   csum = udp->udp_xsum;
+   hlen = ntohs(ip6->payload_len);
+   udp->udp_xsum = 0;
+   /* check