diff options
| author | Shan Wei <shanwei@cn.fujitsu.com> | 2008-06-19 19:29:39 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2008-06-19 19:29:39 -0400 |
| commit | aea7427f70cce5fa8f99ce447b213e9e3b49f24c (patch) | |
| tree | cf247ed4683d498ed7c067da7e6ef315ad97f3ff | |
| parent | ef3a62d272f033989e83eb1f26505f93f93e3e69 (diff) | |
ipv6: Remove options header when setsockopt's optlen is 0
Remove the sticky Hop-by-Hop options header by calling setsockopt()
for IPV6_HOPOPTS with a zero option length, per RFC3542.
Routing header and Destination options header does the same as
Hop-by-Hop options header.
Signed-off-by: Shan Wei <shanwei@cn.fujitsu.com>
Acked-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | net/ipv6/ipv6_sockglue.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index c042ce19bd14..86e28a75267f 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
| @@ -345,18 +345,21 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
| 345 | case IPV6_DSTOPTS: | 345 | case IPV6_DSTOPTS: |
| 346 | { | 346 | { |
| 347 | struct ipv6_txoptions *opt; | 347 | struct ipv6_txoptions *opt; |
| 348 | |||
| 349 | /* remove any sticky options header with a zero option | ||
| 350 | * length, per RFC3542. | ||
| 351 | */ | ||
| 348 | if (optlen == 0) | 352 | if (optlen == 0) |
| 349 | optval = NULL; | 353 | optval = NULL; |
| 354 | else if (optlen < sizeof(struct ipv6_opt_hdr) || | ||
| 355 | optlen & 0x7 || optlen > 8 * 255) | ||
| 356 | goto e_inval; | ||
| 350 | 357 | ||
| 351 | /* hop-by-hop / destination options are privileged option */ | 358 | /* hop-by-hop / destination options are privileged option */ |
| 352 | retv = -EPERM; | 359 | retv = -EPERM; |
| 353 | if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) | 360 | if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) |
| 354 | break; | 361 | break; |
| 355 | 362 | ||
| 356 | if (optlen < sizeof(struct ipv6_opt_hdr) || | ||
| 357 | optlen & 0x7 || optlen > 8 * 255) | ||
| 358 | goto e_inval; | ||
| 359 | |||
| 360 | opt = ipv6_renew_options(sk, np->opt, optname, | 363 | opt = ipv6_renew_options(sk, np->opt, optname, |
| 361 | (struct ipv6_opt_hdr __user *)optval, | 364 | (struct ipv6_opt_hdr __user *)optval, |
| 362 | optlen); | 365 | optlen); |
