ipv6: routing header fixes

This patch fixes two bugs:

1. setsockopt() of anything but a Type 2 routing header should return
EINVAL instead of EPERM. Noticed by Shan Wei
(shanwei@cn.fujitsu.com).

2. setsockopt()/sendmsg() of a Type 2 routing header with invalid
length or segments should return EINVAL. These values are statically
fixed in RFC 3775, unlike the variable Type 0 was.

Signed-off-by: Brian Haley <brian.haley@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by Brian Haley and committed by David S. Miller 6e093d9d b2af2c1d

+10
+5
net/ipv6/datagram.c
··· 661 661 switch (rthdr->type) { 662 662 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 663 663 case IPV6_SRCRT_TYPE_2: 664 + if (rthdr->hdrlen != 2 || 665 + rthdr->segments_left != 1) { 666 + err = -EINVAL; 667 + goto exit_f; 668 + } 664 669 break; 665 670 #endif 666 671 default:
+5
net/ipv6/ipv6_sockglue.c
··· 366 366 } 367 367 368 368 /* routing header option needs extra check */ 369 + retv = -EINVAL; 369 370 if (optname == IPV6_RTHDR && opt && opt->srcrt) { 370 371 struct ipv6_rt_hdr *rthdr = opt->srcrt; 371 372 switch (rthdr->type) { 372 373 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 373 374 case IPV6_SRCRT_TYPE_2: 375 + if (rthdr->hdrlen != 2 || 376 + rthdr->segments_left != 1) 377 + goto sticky_done; 378 + 374 379 break; 375 380 #endif 376 381 default: