diff options
| author | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2005-11-08 12:38:12 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2005-11-08 12:38:12 -0500 |
| commit | b1cacb6820e0afc4aeeea67bcb5296a316862cad (patch) | |
| tree | e7a563d832dfb028b31492ec76054ca30c2c8878 | |
| parent | 971f359ddcb2e7a0d577479c7561bda407febe1b (diff) | |
[IPV6]: Make ipv6_addr_type() more generic so that we can use it for source address selection.
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | include/net/ipv6.h | 19 | ||||
| -rw-r--r-- | net/ipv6/addrconf.c | 90 | ||||
| -rw-r--r-- | net/ipv6/ipv6_syms.c | 2 |
3 files changed, 64 insertions, 47 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 98661fa4fc78..6addb4d464d6 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h | |||
| @@ -252,12 +252,25 @@ typedef int (*inet_getfrag_t) (const void *data, | |||
| 252 | char *, | 252 | char *, |
| 253 | unsigned int, unsigned int); | 253 | unsigned int, unsigned int); |
| 254 | 254 | ||
| 255 | 255 | extern int __ipv6_addr_type(const struct in6_addr *addr); | |
| 256 | extern int ipv6_addr_type(const struct in6_addr *addr); | 256 | static inline int ipv6_addr_type(const struct in6_addr *addr) |
| 257 | { | ||
| 258 | return __ipv6_addr_type(addr) & 0xffff; | ||
| 259 | } | ||
| 257 | 260 | ||
| 258 | static inline int ipv6_addr_scope(const struct in6_addr *addr) | 261 | static inline int ipv6_addr_scope(const struct in6_addr *addr) |
| 259 | { | 262 | { |
| 260 | return ipv6_addr_type(addr) & IPV6_ADDR_SCOPE_MASK; | 263 | return __ipv6_addr_type(addr) & IPV6_ADDR_SCOPE_MASK; |
| 264 | } | ||
| 265 | |||
| 266 | static inline int __ipv6_addr_src_scope(int type) | ||
| 267 | { | ||
| 268 | return (type == IPV6_ADDR_ANY ? __IPV6_ADDR_SCOPE_INVALID : (type >> 16)); | ||
| 269 | } | ||
| 270 | |||
| 271 | static inline int ipv6_addr_src_scope(const struct in6_addr *addr) | ||
| 272 | { | ||
| 273 | return __ipv6_addr_src_scope(__ipv6_addr_type(addr)); | ||
| 261 | } | 274 | } |
| 262 | 275 | ||
| 263 | static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr *a2) | 276 | static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr *a2) |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 2c5f57299d63..ff895da6395b 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -35,6 +35,9 @@ | |||
| 35 | * YOSHIFUJI Hideaki @USAGI : ARCnet support | 35 | * YOSHIFUJI Hideaki @USAGI : ARCnet support |
| 36 | * YOSHIFUJI Hideaki @USAGI : convert /proc/net/if_inet6 to | 36 | * YOSHIFUJI Hideaki @USAGI : convert /proc/net/if_inet6 to |
| 37 | * seq_file. | 37 | * seq_file. |
| 38 | * YOSHIFUJI Hideaki @USAGI : improved source address | ||
| 39 | * selection; consider scope, | ||
| 40 | * status etc. | ||
| 38 | */ | 41 | */ |
| 39 | 42 | ||
| 40 | #include <linux/config.h> | 43 | #include <linux/config.h> |
| @@ -193,46 +196,51 @@ const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; | |||
| 193 | #endif | 196 | #endif |
| 194 | const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; | 197 | const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; |
| 195 | 198 | ||
| 196 | int ipv6_addr_type(const struct in6_addr *addr) | 199 | #define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) |
| 200 | |||
| 201 | static inline unsigned ipv6_addr_scope2type(unsigned scope) | ||
| 202 | { | ||
| 203 | switch(scope) { | ||
| 204 | case IPV6_ADDR_SCOPE_NODELOCAL: | ||
| 205 | return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_NODELOCAL) | | ||
| 206 | IPV6_ADDR_LOOPBACK); | ||
| 207 | case IPV6_ADDR_SCOPE_LINKLOCAL: | ||
| 208 | return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL) | | ||
| 209 | IPV6_ADDR_LINKLOCAL); | ||
| 210 | case IPV6_ADDR_SCOPE_SITELOCAL: | ||
| 211 | return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL) | | ||
| 212 | IPV6_ADDR_SITELOCAL); | ||
| 213 | } | ||
| 214 | return IPV6_ADDR_SCOPE_TYPE(scope); | ||
| 215 | } | ||
| 216 | |||
| 217 | int __ipv6_addr_type(const struct in6_addr *addr) | ||
| 197 | { | 218 | { |
| 198 | int type; | ||
| 199 | u32 st; | 219 | u32 st; |
| 200 | 220 | ||
| 201 | st = addr->s6_addr32[0]; | 221 | st = addr->s6_addr32[0]; |
| 202 | 222 | ||
| 203 | if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) { | ||
| 204 | type = IPV6_ADDR_MULTICAST; | ||
| 205 | |||
| 206 | switch((st & htonl(0x00FF0000))) { | ||
| 207 | case __constant_htonl(0x00010000): | ||
| 208 | type |= IPV6_ADDR_LOOPBACK; | ||
| 209 | break; | ||
| 210 | |||
| 211 | case __constant_htonl(0x00020000): | ||
| 212 | type |= IPV6_ADDR_LINKLOCAL; | ||
| 213 | break; | ||
| 214 | |||
| 215 | case __constant_htonl(0x00050000): | ||
| 216 | type |= IPV6_ADDR_SITELOCAL; | ||
| 217 | break; | ||
| 218 | }; | ||
| 219 | return type; | ||
| 220 | } | ||
| 221 | |||
| 222 | type = IPV6_ADDR_UNICAST; | ||
| 223 | |||
| 224 | /* Consider all addresses with the first three bits different of | 223 | /* Consider all addresses with the first three bits different of |
| 225 | 000 and 111 as finished. | 224 | 000 and 111 as unicasts. |
| 226 | */ | 225 | */ |
| 227 | if ((st & htonl(0xE0000000)) != htonl(0x00000000) && | 226 | if ((st & htonl(0xE0000000)) != htonl(0x00000000) && |
| 228 | (st & htonl(0xE0000000)) != htonl(0xE0000000)) | 227 | (st & htonl(0xE0000000)) != htonl(0xE0000000)) |
| 229 | return type; | 228 | return (IPV6_ADDR_UNICAST | |
| 230 | 229 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); | |
| 231 | if ((st & htonl(0xFFC00000)) == htonl(0xFE800000)) | ||
| 232 | return (IPV6_ADDR_LINKLOCAL | type); | ||
| 233 | 230 | ||
| 231 | if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) { | ||
| 232 | /* multicast */ | ||
| 233 | /* addr-select 3.1 */ | ||
| 234 | return (IPV6_ADDR_MULTICAST | | ||
| 235 | ipv6_addr_scope2type(IPV6_ADDR_MC_SCOPE(addr))); | ||
| 236 | } | ||
| 237 | |||
| 238 | if ((st & htonl(0xFFC00000)) == htonl(0xFE800000)) | ||
| 239 | return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST | | ||
| 240 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.1 */ | ||
| 234 | if ((st & htonl(0xFFC00000)) == htonl(0xFEC00000)) | 241 | if ((st & htonl(0xFFC00000)) == htonl(0xFEC00000)) |
| 235 | return (IPV6_ADDR_SITELOCAL | type); | 242 | return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST | |
| 243 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL)); /* addr-select 3.1 */ | ||
| 236 | 244 | ||
| 237 | if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) { | 245 | if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) { |
| 238 | if (addr->s6_addr32[2] == 0) { | 246 | if (addr->s6_addr32[2] == 0) { |
| @@ -240,24 +248,20 @@ int ipv6_addr_type(const struct in6_addr *addr) | |||
| 240 | return IPV6_ADDR_ANY; | 248 | return IPV6_ADDR_ANY; |
| 241 | 249 | ||
| 242 | if (addr->s6_addr32[3] == htonl(0x00000001)) | 250 | if (addr->s6_addr32[3] == htonl(0x00000001)) |
| 243 | return (IPV6_ADDR_LOOPBACK | type); | 251 | return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST | |
| 252 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.4 */ | ||
| 244 | 253 | ||
| 245 | return (IPV6_ADDR_COMPATv4 | type); | 254 | return (IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST | |
| 255 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */ | ||
| 246 | } | 256 | } |
| 247 | 257 | ||
| 248 | if (addr->s6_addr32[2] == htonl(0x0000ffff)) | 258 | if (addr->s6_addr32[2] == htonl(0x0000ffff)) |
| 249 | return IPV6_ADDR_MAPPED; | 259 | return (IPV6_ADDR_MAPPED | |
| 250 | } | 260 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */ |
| 251 | 261 | } | |
| 252 | st &= htonl(0xFF000000); | 262 | |
| 253 | if (st == 0) | 263 | return (IPV6_ADDR_RESERVED | |
| 254 | return IPV6_ADDR_RESERVED; | 264 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.4 */ |
| 255 | st &= htonl(0xFE000000); | ||
| 256 | if (st == htonl(0x02000000)) | ||
| 257 | return IPV6_ADDR_RESERVED; /* for NSAP */ | ||
| 258 | if (st == htonl(0x04000000)) | ||
| 259 | return IPV6_ADDR_RESERVED; /* for IPX */ | ||
| 260 | return type; | ||
| 261 | } | 265 | } |
| 262 | 266 | ||
| 263 | static void addrconf_del_timer(struct inet6_ifaddr *ifp) | 267 | static void addrconf_del_timer(struct inet6_ifaddr *ifp) |
diff --git a/net/ipv6/ipv6_syms.c b/net/ipv6/ipv6_syms.c index 37a4a99c9fe9..16482785bdfd 100644 --- a/net/ipv6/ipv6_syms.c +++ b/net/ipv6/ipv6_syms.c | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include <net/ip6_route.h> | 7 | #include <net/ip6_route.h> |
| 8 | #include <net/xfrm.h> | 8 | #include <net/xfrm.h> |
| 9 | 9 | ||
| 10 | EXPORT_SYMBOL(ipv6_addr_type); | 10 | EXPORT_SYMBOL(__ipv6_addr_type); |
| 11 | EXPORT_SYMBOL(icmpv6_send); | 11 | EXPORT_SYMBOL(icmpv6_send); |
| 12 | EXPORT_SYMBOL(icmpv6_statistics); | 12 | EXPORT_SYMBOL(icmpv6_statistics); |
| 13 | EXPORT_SYMBOL(icmpv6_err_convert); | 13 | EXPORT_SYMBOL(icmpv6_err_convert); |
