0dc2f1396e5874654ed1cfec3370e4a9477f48e9
[linux-flexiantxendom0-3.2.10.git] / net / ipv6 / mobile_ip6 / util.h
1 /*
2  *      MIPL Mobile IPv6 Utility functions
3  *
4  *      $Id: s.util.h 1.16 03/09/26 00:30:23+03:00 vnuorval@cs78179138.pp.htv.fi $
5  *
6  *      This program is free software; you can redistribute it and/or
7  *      modify it under the terms of the GNU General Public License
8  *      as published by the Free Software Foundation; either version
9  *      2 of the License, or (at your option) any later version.
10  */
11
12 #ifndef _UTIL_H
13 #define _UTIL_H
14
15 #include <linux/in6.h>
16 #include <asm/byteorder.h>
17
18 /**
19  * mipv6_prefix_compare - Compare two IPv6 prefixes
20  * @addr: IPv6 address
21  * @prefix: IPv6 address
22  * @nprefix: number of bits to compare
23  *
24  * Perform prefix comparison bitwise for the @nprefix first bits
25  * Returns 1, if the prefixes are the same, 0 otherwise 
26  **/
27 static inline int mipv6_prefix_compare(const struct in6_addr *addr,
28                                        const struct in6_addr *prefix, 
29                                        const unsigned int pfix_len)
30 {
31         int i;
32         unsigned int nprefix = pfix_len;
33
34         if (nprefix > 128)
35                 return 0;
36
37         for (i = 0; nprefix > 0; nprefix -= 32, i++) {
38                 if (nprefix >= 32) {
39                         if (addr->s6_addr32[i] != prefix->s6_addr32[i])
40                                 return 0;
41                 } else {
42                         if (((addr->s6_addr32[i] ^ prefix->s6_addr32[i]) &
43                              ((~0) << (32 - nprefix))) != 0)
44                                 return 0;
45                         return 1;
46                 }
47         }
48
49         return 1;
50 }
51
52 /**
53  * homeagent_anycast - Compute Home Agent anycast address
54  * @ac_addr: append home agent anycast suffix to passed prefix
55  * @prefix: prefix ha anycast address is generated from
56  * @plen: length of prefix in bits
57  *
58  * Calculate corresponding Home Agent Anycast Address (RFC2526) in a
59  * given subnet.
60  */
61 static inline int 
62 mipv6_ha_anycast(struct in6_addr *ac_addr, struct in6_addr *prefix, int plen)
63 {
64         if (plen <= 0 || plen > 120)  {
65                 /* error, interface id should be minimum 8 bits */
66                 return -1;
67         }
68         ipv6_addr_copy(ac_addr, prefix);
69
70         if (plen < 32)
71                 ac_addr->s6_addr32[0] |= htonl((u32)(~0) >> plen);
72         if (plen < 64)
73                 ac_addr->s6_addr32[1] |= htonl((u32)(~0) >> (plen > 32 ? plen % 32 : 0));
74         if (plen < 92)
75                 ac_addr->s6_addr32[2] |= htonl((u32)(~0) >> (plen > 64 ? plen % 32 : 0));
76         if (plen <= 120)
77                 ac_addr->s6_addr32[3] |= htonl((u32)(~0) >> (plen > 92 ? plen % 32 : 0));
78
79         /* RFC2526: for interface identifiers in EUI-64
80          * format, the universal/local bit in the interface
81          * identifier MUST be set to 0. */
82         if (plen == 64) {
83                 ac_addr->s6_addr32[2] &= (int)htonl(0xfdffffff);
84         }
85         /* Mobile IPv6 Home-Agents anycast id (0x7e) */
86         ac_addr->s6_addr32[3] &= (int)htonl(0xfffffffe);
87
88         return 0;
89 }
90
91 #endif /* _UTIL_H */