xref: /minix/minix/net/lwip/addrpol.c (revision ef8d499e)
1 /* LWIP service - addrpol.c - address policy table and values */
2 /*
3  * The main purpose of this module is to implement the address policy table
4  * described in RFC 6724.  In general, the policy table is used for two
5  * purposes: source address selection, which is part of this service, and
6  * destination address selection, which is implemented in libc.  NetBSD 7, the
7  * version that MINIX 3 is synced against at this moment, does not actually
8  * implement the libc part yet, though.  That will change with NetBSD 8, where
9  * libc uses sysctl(7) to obtain the kernel's policy table, which itself can be
10  * changed with the new ip6addrctl(8) utility.  Once we resync to NetBSD 8, we
11  * will also have to support this new functionality, and this module is where
12  * it would be implemented.  Since NetBSD 7 is even lacking the necessary
13  * definitions, we cannot do that ahead of time, though.  Thus, until then,
14  * this module is rather simple, as it only implements a static policy table
15  * used for source address selection.  No changes beyond this module should be
16  * necessary, e.g. we are purposely not caching labels for local addresses.
17  */
18 
19 #include "lwip.h"
20 
21 /*
22  * Address policy table.  Currently hardcoded to the default of RFC 6724.
23  * Sorted by prefix length, so that the first match is always also the longest.
24  */
25 static const struct {
26 	ip_addr_t ipaddr;
27 	unsigned int prefix;
28 	int precedence;
29 	int label;
30 } addrpol_table[] = {
31 	{ IPADDR6_INIT_HOST(0, 0, 0, 1),		128, 50,  0 },
32 	{ IPADDR6_INIT_HOST(0, 0, 0x0000ffffUL, 0),	 96, 35,  4 },
33 	{ IPADDR6_INIT_HOST(0, 0, 0, 0),		 96,  1,  3 },
34 	{ IPADDR6_INIT_HOST(0x20010000UL, 0, 0, 0),	 32,  5,  5 },
35 	{ IPADDR6_INIT_HOST(0x20020000UL, 0, 0, 0),	 16, 30,  2 },
36 	{ IPADDR6_INIT_HOST(0x3ffe0000UL, 0, 0, 0),	 16,  1, 12 },
37 	{ IPADDR6_INIT_HOST(0xfec00000UL, 0, 0, 0),	 10,  1, 11 },
38 	{ IPADDR6_INIT_HOST(0xfc000000UL, 0, 0, 0),	  7,  3, 13 },
39 	{ IPADDR6_INIT_HOST(0, 0, 0, 0),		  0, 40,  1 }
40 };
41 
42 /*
43  * Obtain the label value for the given IP address from the address policy
44  * table.  Currently only IPv6 addresses may be given.  This function is linear
45  * in number of address policy table entries, requiring a relatively expensive
46  * normalization operation for each entry, so it should not be called lightly.
47  * Its results should not be cached beyond local contexts either, because the
48  * policy table itself may be changed from userland (in the future).
49  *
50  * TODO: convert IPv4 addresses to IPv4-mapped IPv6 addresses.
51  * TODO: embed the interface index in link-local addresses.
52  */
53 int
addrpol_get_label(const ip_addr_t * iporig)54 addrpol_get_label(const ip_addr_t * iporig)
55 {
56 	ip_addr_t ipaddr;
57 	unsigned int i;
58 
59 	assert(IP_IS_V6(iporig));
60 
61 	/*
62 	 * The policy table is sorted by prefix length such that the first
63 	 * match is also the one with the longest prefix, and as such the best.
64 	 */
65 	for (i = 0; i < __arraycount(addrpol_table); i++) {
66 		addr_normalize(&ipaddr, iporig, addrpol_table[i].prefix);
67 
68 		if (ip_addr_cmp(&addrpol_table[i].ipaddr, &ipaddr))
69 			return addrpol_table[i].label;
70 	}
71 
72 	/*
73 	 * We cannot possibly get here with the default policy table, because
74 	 * the last entry will always match.  It is not clear what we should
75 	 * return if there is no matching entry, though.  For now, we return
76 	 * the default label value for the default (::/0) entry, which is 1.
77 	 */
78 	return 1;
79 }
80 
81 /*
82  * Return an opaque positive value (possibly zero) that represents the scope of
83  * the given IP address.  A larger value indicates a wider scope.  The 'is_src'
84  * flag indicates whether the address is a source or a destination address,
85  * which affects the value returned for unknown addresses.  A scope is a direct
86  * function of only the given address, so the result may be cached on a per-
87  * address basis without risking invalidation at any point in time.
88  */
89 int
addrpol_get_scope(const ip_addr_t * ipaddr,int is_src)90 addrpol_get_scope(const ip_addr_t * ipaddr, int is_src)
91 {
92 	const ip6_addr_t *ip6addr;
93 
94 	/*
95 	 * For now, all IPv4 addresses are considered global.  This function is
96 	 * currently called only for IPv6 addresses anyway.
97 	 */
98 	if (IP_IS_V4(ipaddr))
99 		return IP6_MULTICAST_SCOPE_GLOBAL;
100 
101 	assert(IP_IS_V6(ipaddr));
102 
103 	ip6addr = ip_2_ip6(ipaddr);
104 
105 	/*
106 	 * These are ordered not by ascending scope, but (roughly) by expected
107 	 * likeliness to match, for performance reasons.
108 	 */
109 	if (ip6_addr_isglobal(ip6addr))
110 		return IP6_MULTICAST_SCOPE_GLOBAL;
111 
112 	if (ip6_addr_islinklocal(ip6addr) || ip6_addr_isloopback(ip6addr))
113 		return IP6_MULTICAST_SCOPE_LINK_LOCAL;
114 
115 	/*
116 	 * We deliberately deviate from RFC 6724 Sec. 3.1 by considering
117 	 * Unique-Local Addresses (ULAs) to be of smaller scope than global
118 	 * addresses, to avoid that during source address selection, a
119 	 * preferred ULA is picked over a deprecated global address when given
120 	 * a global address as destination, as that would likely result in
121 	 * broken two-way communication.
122 	 */
123 	if (ip6_addr_isuniquelocal(ip6addr))
124 		return IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL;
125 
126 	if (ip6_addr_ismulticast(ip6addr))
127 		return ip6_addr_multicast_scope(ip6addr);
128 
129 	/* Site-local addresses are deprecated. */
130 	if (ip6_addr_issitelocal(ip6addr))
131 		return IP6_MULTICAST_SCOPE_SITE_LOCAL;
132 
133 	/*
134 	 * If the address is a source address, give it a scope beyond global to
135 	 * make sure that a "real" global address is picked first.  If the
136 	 * address is a destination address, give it a global scope so as to
137 	 * pick "real" global addresses over unknown-scope source addresses.
138 	 */
139 	if (is_src)
140 		return IP6_MULTICAST_SCOPE_RESERVEDF; /* greater than GLOBAL */
141 	else
142 		return IP6_MULTICAST_SCOPE_GLOBAL;
143 }
144