1 /* route.h
2  *
3  * Copyright (c) 2019-2020 Apple Computer, Inc. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #ifndef __SERVICE_REGISTRATION_ROUTE_H
19 #define __SERVICE_REGISTRATION_ROUTE_H
20 #if defined(USE_IPCONFIGURATION_SERVICE)
21 #include <SystemConfiguration/SystemConfiguration.h>
22 #include "IPConfigurationService.h"
23 #endif
24 
25 #define MIN_DELAY_BETWEEN_RAS 4000
26 #define MSEC_PER_SEC (NSEC_PER_SEC / NSEC_PER_MSEC)
27 #define MAX_ROUTER_RECEIVED_TIME_GAP_BEFORE_STALE 600 * MSEC_PER_SEC
28 
29 // Fix this
30 #ifndef IPV6_ROUTER_MODE_EXCLUSIVE
31 #define IPV6_ROUTER_MODE_DISABLED	0
32 #define IPV6_ROUTER_MODE_EXCLUSIVE	1
33 #define IPV6_ROUTER_MODE_HYBRID		2
34 #endif
35 
36 
37 typedef struct interface interface_t;
38 typedef struct icmp_message icmp_message_t;
39 typedef struct network_link network_link_t;
40 struct interface {
41     int ref_count;
42 
43     interface_t *NULLABLE next;
44     char *NONNULL name;
45 
46     // Wakeup event for next beacon.
47     wakeup_t *NULLABLE beacon_wakeup;
48 
49     // Wakeup event called after we're done sending solicits.  At this point we delete all routes more than 10 minutes
50     // old; if none are left, then we assume there's no IPv6 service on the interface.
51     wakeup_t *NULLABLE post_solicit_wakeup;
52 
53     // Wakeup event to trigger the next router solicit to be sent.
54     wakeup_t *NULLABLE router_solicit_wakeup;
55 
56     // Wakeup event to deconfigure the on-link prefix after it is no longer valid.
57     wakeup_t *NULLABLE deconfigure_wakeup;
58 
59     // Wakeup event to detect that vicarious router discovery is complete
60     wakeup_t *NULLABLE vicarious_discovery_complete;
61 
62     // Wakeup event to periodically notice whether routers we have heard previously on this interface have gone stale.
63     wakeup_t *NULLABLE stale_evaluation_wakeup;
64 
65     // List of ICMP messages from different routers.
66     icmp_message_t *NULLABLE routers;
67 
68     // The link to which this interface is connected.
69     network_link_t *NULLABLE link;
70 
71 #if defined(USE_IPCONFIGURATION_SERVICE)
72     // The service used to configure this interface with an address in the on-link prefix
73     IPConfigurationServiceRef NULLABLE ip_configuration_service;
74 
75     // SCDynamicStoreRef
76     SCDynamicStoreRef NULLABLE ip_configuration_store;
77 #endif
78 
79     struct in6_addr link_local;  // Link-local address
80     struct in6_addr ipv6_prefix; // This is the prefix we advertise, if advertise_ipv6_prefix is true.
81 
82     // Absolute time of last beacon, and of next beacon.
83     uint64_t last_beacon, next_beacon;
84 
85     // Absolute deadline for deprecating the on-link prefix we've been announcing
86     uint64_t deprecate_deadline;
87 
88     // Preferred lifetime for the on-link prefix
89     uint32_t preferred_lifetime;
90 
91     // Valid lifetime for the on-link prefix
92     uint32_t valid_lifetime;
93 
94     // When the interface becomes active, we send up to three solicits.
95     int num_solicits_sent;
96 
97     // The interface index according to the operating systme.
98     int index;
99 
100     // Number of IPv4 addresses configured on link.
101     int num_ipv4_addresses;
102 
103     // Number of beacons sent. After the first three, the inter-beacon interval goes up.
104     int num_beacons_sent;
105 
106     // The interface link layer address, if known.
107     uint8_t link_layer[6];
108 
109     // True if the interface is not usable.
110     bool inactive;
111 
112     // True if this interface can never be used for routing to the thread network (e.g., loopback, tunnels, etc.)
113     bool ineligible;
114 
115     // True if we've determined that it's the thread interface.
116     bool is_thread;
117 
118     // True if we should advertise an on-link prefix.
119     bool advertise_ipv6_prefix;
120 
121     // True if we've gotten a link-layer address.
122     bool have_link_layer_address;
123 
124     // True if the on-link prefix is configured on the interface.
125     bool on_link_prefix_configured;
126 
127     // True if we've sent our first beacon since the interface came up.
128     bool sent_first_beacon;
129 
130     // Indicates whether or not router discovery has completed for this interface.
131     bool router_discovery_complete;
132 
133     // Indicates whether we're currently doing router discovery, so that we don't
134     // restart it when we're already doing it.
135     bool router_discovery_in_progress;
136 
137     // Indicates that we've received a router discovery message from some other host,
138     // and are waiting 20 seconds to snoop for replies to that RD message that are
139     // multicast.   If we hear no replies during that time, we trigger router discovery.
140     bool vicarious_router_discovery_in_progress;
141 
142     // Indicates that we have received an interface removal event, it is useful when srp-mdns-proxy is changed to a new
143     // network where the network signature are the same and they both have no IPv6 service (so no IPv6 prefix will be
144     // removed), in such case there will be no change from srp-mdns-proxy's point of view. However, configd may still
145     // flush the IPv6 routing since changing network would cause interface up/down. When the flushing happens,
146     // srp-mdns-proxy should be able to reconfigure the IPv6 routing by reconfiguring IPv6 prefix. By setting
147     // need_reconfigure_prefix only when interface address removal happens and check it during the routing evaluation
148     // srp-mdns-proxy can reconfigure it after the routing evaluation finishes, like router discovery.
149     bool need_reconfigure_prefix;
150 };
151 
152 typedef enum icmp_option_type {
153     icmp_option_source_link_layer_address =  1,
154     icmp_option_target_link_layer_address =  2,
155     icmp_option_prefix_information        =  3,
156     icmp_option_redirected_header         =  4,
157     icmp_option_mtu                       =  5,
158     icmp_option_route_information         = 24,
159 } icmp_option_type_t;
160 
161 typedef enum icmp_type {
162     icmp_type_echo_request           = 128,
163     icmp_type_echo_reply             = 129,
164     icmp_type_router_solicitation    = 133,
165     icmp_type_router_advertisement   = 134,
166     icmp_type_neighbor_solicitation  = 135,
167     icmp_type_neighbor_advertisement = 136,
168     icmp_type_redirect               = 137,
169 } icmp_type_t;
170 
171 typedef struct link_layer_address {
172     uint16_t length;
173     uint8_t address[32];
174 } link_layer_address_t;
175 
176 typedef struct prefix_information {
177     struct in6_addr prefix;
178     uint8_t length;
179     uint8_t flags;
180     uint32_t valid_lifetime;
181     uint32_t preferred_lifetime;
182 } prefix_information_t;
183 
184 typedef struct route_information {
185     struct in6_addr prefix;
186     uint8_t length;
187     uint8_t flags;
188     uint32_t route_lifetime;
189 } route_information_t;
190 
191 typedef struct icmp_option {
192     icmp_option_type_t type;
193     union {
194         link_layer_address_t link_layer_address;
195         prefix_information_t prefix_information;
196         route_information_t route_information;
197     } option;
198 } icmp_option_t;
199 
200 struct icmp_message {
201     icmp_message_t *NULLABLE next;
202     interface_t *NULLABLE interface;
203     icmp_option_t *NULLABLE options;
204     bool new_router;                     // If this router information is a newly recevied one.
205     bool received_time_already_adjusted; // if the received time of the message is already adjusted by vicarious mode
206     struct in6_addr source;
207     struct in6_addr destination;
208 
209     uint64_t received_time;
210 
211     uint32_t reachable_time;
212     uint32_t retransmission_timer;
213     uint8_t cur_hop_limit;          // Current hop limit for Router Advertisement messages.
214     uint8_t flags;
215     uint8_t type;
216     uint8_t code;
217     uint16_t checksum;              // We hope the kernel figures this out for us.
218     uint16_t router_lifetime;
219 
220     int num_options;
221     int hop_limit;                  // Hop limit provided by the kernel, must be 255.
222 };
223 
224 void ula_generate(void);
225 bool start_route_listener(void);
226 bool start_icmp_listener(void);
227 void icmp_leave_join(int sock, int ifindex, bool join);
228 
229 #define interface_create(name, iface) interface_create_(name, iface, __FILE__, __LINE__)
230 interface_t *NULLABLE interface_create_(const char *NONNULL name, int ifindex,
231                                                       const char *NONNULL file, int line);
232 #define interface_retain(interface) interface_retain_(interface, __FILE__, __LINE__)
233 void interface_retain_(interface_t *NONNULL interface, const char *NONNULL file, int line);
234 #define interface_release(interface) interface_release_(interface, __FILE__, __LINE__)
235 void interface_release_(interface_t *NONNULL interface, const char *NONNULL file, int line);
236 bool interface_monitor_start(void);
237 void thread_network_startup(void);
238 void thread_network_shutdown(void);
239 void partition_stop_advertising_pref_id(void);
240 void partition_start_srp_listener(void);
241 #endif // __SERVICE_REGISTRATION_ROUTE_H
242 
243 // Local Variables:
244 // mode: C
245 // tab-width: 4
246 // c-file-style: "bsd"
247 // c-basic-offset: 4
248 // fill-column: 120
249 // indent-tabs-mode: nil
250 // End:
251