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 /net/ipv6/addrconf.c | |
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>
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r-- | net/ipv6/addrconf.c | 90 |
1 files changed, 47 insertions, 43 deletions
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) |