diff options
author | Brian Haley <brian.haley@hp.com> | 2006-12-12 20:09:49 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-13 19:48:25 -0500 |
commit | befffe901649e2cc421d0d150c4379d01658cf6b (patch) | |
tree | a990965641fb181bdf1228d2a347ecdf87ab8742 | |
parent | 832e3ca62d6ee1893db05f5202c24ae5331e19ba (diff) |
[IPV6]: Fix IPV6_UNICAST_HOPS getsockopt().
> Relevant standard (RFC 3493) notes:
>
> The IPV6_UNICAST_HOPS option may be used with getsockopt() to
> determine the hop limit value that the system will use for subsequent
> unicast packets sent via that socket.
>
> I don't reckon -1 could be the hop limit value.
-1 means un-initialized.
> IMHO, the value from
> case 1 (if socket is connected to some destination), otherwise case 2
> (if bound to a scope interface) or ultimately the default hop limit
> ought to be returned instead, as it will be most often correct, while
> the current behavior is always wrong, unless setsockopt() has been used
> first. I don't if some people may think doing a route lookup in
> getsockopt might be overly expensive, but at least the two other cases
> should be ok, particularly the last one.
The following patch seems to work for me, but this code has behaved this
way for a while, so don't know if it will break any existing apps.
Signed-off-by: Brian Haley <brian.haley@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 1eafcfc95e81..352690e2ab82 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -978,12 +978,27 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
978 | break; | 978 | break; |
979 | 979 | ||
980 | case IPV6_UNICAST_HOPS: | 980 | case IPV6_UNICAST_HOPS: |
981 | val = np->hop_limit; | ||
982 | break; | ||
983 | |||
984 | case IPV6_MULTICAST_HOPS: | 981 | case IPV6_MULTICAST_HOPS: |
985 | val = np->mcast_hops; | 982 | { |
983 | struct dst_entry *dst; | ||
984 | |||
985 | if (optname == IPV6_UNICAST_HOPS) | ||
986 | val = np->hop_limit; | ||
987 | else | ||
988 | val = np->mcast_hops; | ||
989 | |||
990 | dst = sk_dst_get(sk); | ||
991 | if (dst) { | ||
992 | if (val < 0) | ||
993 | val = dst_metric(dst, RTAX_HOPLIMIT); | ||
994 | if (val < 0) | ||
995 | val = ipv6_get_hoplimit(dst->dev); | ||
996 | dst_release(dst); | ||
997 | } | ||
998 | if (val < 0) | ||
999 | val = ipv6_devconf.hop_limit; | ||
986 | break; | 1000 | break; |
1001 | } | ||
987 | 1002 | ||
988 | case IPV6_MULTICAST_LOOP: | 1003 | case IPV6_MULTICAST_LOOP: |
989 | val = np->mc_loop; | 1004 | val = np->mc_loop; |