diff mbox

[GIT,PULL,net-next,04/17] ndisc: Introduce ndisc_fill_redirect_hdr_option().

Message ID 50D04B4B.7060002@linux-ipv6.org
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

YOSHIFUJI Hideaki / 吉藤英明 Dec. 18, 2012, 10:54 a.m. UTC
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
---
 net/ipv6/ndisc.c |   21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

Comments

YOSHIFUJI Hideaki / 吉藤英明 Dec. 19, 2012, 3:08 a.m. UTC | #1
YOSHIFUJI Hideaki wrote:
> Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
> ---
>  net/ipv6/ndisc.c |   21 +++++++++++++++------
>  1 file changed, 15 insertions(+), 6 deletions(-)
> 
> diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
> index a181113..0a4f3a9 100644
> --- a/net/ipv6/ndisc.c
> +++ b/net/ipv6/ndisc.c
> @@ -1332,6 +1332,19 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
>  	icmpv6_notify(skb, NDISC_REDIRECT, 0, 0);
>  }
>  
> +static u8 *ndisc_fill_redirect_hdr_option(u8 *opt, struct sk_buff *orig_skb,
> +					  int rd_len)
> +{
> +	memset(opt, 0, 8);
> +	*(opt++) = ND_OPT_REDIRECT_HDR;
> +	*(opt++) = (rd_len >> 3);
> +	opt += 6;
> +
> +	memcpy(opt, ipv6_hdr(orig_skb), rd_len - 8);
> +
> +	return opt;
> +}
> +
>  void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
>  {
>  	struct net_device *dev = skb->dev;

By the way, is it really safe to use memcpy here?
Should we use skb_copy_bits() instead?

--yoshfuji

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Bjørn Mork Dec. 19, 2012, 11:47 a.m. UTC | #2
YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> writes:

> Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
> ---
>  net/ipv6/ndisc.c |   21 +++++++++++++++------
>  1 file changed, 15 insertions(+), 6 deletions(-)
>
> diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
> index a181113..0a4f3a9 100644
> --- a/net/ipv6/ndisc.c
> +++ b/net/ipv6/ndisc.c
> @@ -1332,6 +1332,19 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
>  	icmpv6_notify(skb, NDISC_REDIRECT, 0, 0);
>  }
>  
> +static u8 *ndisc_fill_redirect_hdr_option(u8 *opt, struct sk_buff *orig_skb,
> +					  int rd_len)
> +{
> +	memset(opt, 0, 8);
> +	*(opt++) = ND_OPT_REDIRECT_HDR;
> +	*(opt++) = (rd_len >> 3);
> +	opt += 6;
> +
> +	memcpy(opt, ipv6_hdr(orig_skb), rd_len - 8);
> +
> +	return opt;
> +}
> +

I realize that it doesn't currently matter, but the above modification
of "opt" looks like a bug-waiting-to-happen to me.

>  void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
>  {
>  	struct net_device *dev = skb->dev;
> @@ -1461,12 +1474,8 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
>  	 *	build redirect option and copy skb over to the new packet.
>  	 */
>  
> -	memset(opt, 0, 8);
> -	*(opt++) = ND_OPT_REDIRECT_HDR;
> -	*(opt++) = (rd_len >> 3);
> -	opt += 6;
> -
> -	memcpy(opt, ipv6_hdr(skb), rd_len - 8);
> +	if (rd_len)
> +		opt = ndisc_fill_redirect_hdr_option(opt, skb, rd_len);


I understand that opt isn't currently used after this, but if it ever is
then it is going to come as big a surprise that this implies opt += 8;

This was previously quite clear when the code was inline, but it becomes
problematic when it is factored out.


Bjørn
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
YOSHIFUJI Hideaki / 吉藤英明 Dec. 19, 2012, 4:25 p.m. UTC | #3
Bjørn Mork wrote:
> YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> writes:
> 
>> Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
>> ---
>>  net/ipv6/ndisc.c |   21 +++++++++++++++------
>>  1 file changed, 15 insertions(+), 6 deletions(-)
>>
>> diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
>> index a181113..0a4f3a9 100644
>> --- a/net/ipv6/ndisc.c
>> +++ b/net/ipv6/ndisc.c
>> @@ -1332,6 +1332,19 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
>>  	icmpv6_notify(skb, NDISC_REDIRECT, 0, 0);
>>  }
>>  
>> +static u8 *ndisc_fill_redirect_hdr_option(u8 *opt, struct sk_buff *orig_skb,
>> +					  int rd_len)
>> +{
>> +	memset(opt, 0, 8);
>> +	*(opt++) = ND_OPT_REDIRECT_HDR;
>> +	*(opt++) = (rd_len >> 3);
>> +	opt += 6;
>> +
>> +	memcpy(opt, ipv6_hdr(orig_skb), rd_len - 8);
>> +
>> +	return opt;
>> +}
>> +
> 
> I realize that it doesn't currently matter, but the above modification
> of "opt" looks like a bug-waiting-to-happen to me.
> 
>>  void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
>>  {
>>  	struct net_device *dev = skb->dev;
>> @@ -1461,12 +1474,8 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
>>  	 *	build redirect option and copy skb over to the new packet.
>>  	 */
>>  
>> -	memset(opt, 0, 8);
>> -	*(opt++) = ND_OPT_REDIRECT_HDR;
>> -	*(opt++) = (rd_len >> 3);
>> -	opt += 6;
>> -
>> -	memcpy(opt, ipv6_hdr(skb), rd_len - 8);
>> +	if (rd_len)
>> +		opt = ndisc_fill_redirect_hdr_option(opt, skb, rd_len);
> 
> 
> I understand that opt isn't currently used after this, but if it ever is
> then it is going to come as big a surprise that this implies opt += 8;
> 
> This was previously quite clear when the code was inline, but it becomes
> problematic when it is factored out.

I understand your concern.  opt will be disappeared by following
changeset (12 of 17).

--yoshfuji
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
YOSHIFUJI Hideaki / 吉藤英明 Dec. 19, 2012, 5:27 p.m. UTC | #4
(2012年12月20日 01:25), YOSHIFUJI Hideaki wrote:
> Bjørn Mork wrote:
>> YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> writes:

>>> +static u8 *ndisc_fill_redirect_hdr_option(u8 *opt, struct sk_buff *orig_skb,
>>> +					  int rd_len)
>>> +{
>>> +	memset(opt, 0, 8);
>>> +	*(opt++) = ND_OPT_REDIRECT_HDR;
>>> +	*(opt++) = (rd_len >> 3);
>>> +	opt += 6;
>>> +
>>> +	memcpy(opt, ipv6_hdr(orig_skb), rd_len - 8);
>>> +
>>> +	return opt;
>>> +}
:
>> I understand that opt isn't currently used after this, but if it ever is
>> then it is going to come as big a surprise that this implies opt += 8;
>>
>> This was previously quite clear when the code was inline, but it becomes
>> problematic when it is factored out.
> 
> I understand your concern.  opt will be disappeared by following
> changeset (12 of 17).

Argh, I now notice return value was not quite right; it should
return opt + rd_len - 8.

Fixed in my local tree.  Thanks.

--yoshfuji

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index a181113..0a4f3a9 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1332,6 +1332,19 @@  static void ndisc_redirect_rcv(struct sk_buff *skb)
 	icmpv6_notify(skb, NDISC_REDIRECT, 0, 0);
 }
 
+static u8 *ndisc_fill_redirect_hdr_option(u8 *opt, struct sk_buff *orig_skb,
+					  int rd_len)
+{
+	memset(opt, 0, 8);
+	*(opt++) = ND_OPT_REDIRECT_HDR;
+	*(opt++) = (rd_len >> 3);
+	opt += 6;
+
+	memcpy(opt, ipv6_hdr(orig_skb), rd_len - 8);
+
+	return opt;
+}
+
 void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
 {
 	struct net_device *dev = skb->dev;
@@ -1461,12 +1474,8 @@  void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
 	 *	build redirect option and copy skb over to the new packet.
 	 */
 
-	memset(opt, 0, 8);
-	*(opt++) = ND_OPT_REDIRECT_HDR;
-	*(opt++) = (rd_len >> 3);
-	opt += 6;
-
-	memcpy(opt, ipv6_hdr(skb), rd_len - 8);
+	if (rd_len)
+		opt = ndisc_fill_redirect_hdr_option(opt, skb, rd_len);
 
 	msg->icmph.icmp6_cksum = csum_ipv6_magic(&saddr_buf, &ipv6_hdr(skb)->saddr,
 						 len, IPPROTO_ICMPV6,