1 /*
2  *
3  *   Authors:
4  *    Lars Fenneberg		<lf@elemental.net>
5  *
6  *   This software is Copyright 1996,1997 by the above mentioned author(s),
7  *   All Rights Reserved.
8  *
9  *   The license which is distributed with this software in the file COPYRIGHT
10  *   applies to this software. If your distribution is missing this file, you
11  *   may request it from <reubenhwk@gmail.com>.
12  *
13  */
14 
15 #include "config.h"
16 #include "defaults.h"
17 #include "includes.h"
18 #include "radvd.h"
19 
20 #define IFACE_SETUP_DELAY 1
21 
iface_init_defaults(struct Interface * iface)22 void iface_init_defaults(struct Interface *iface)
23 {
24 	memset(iface, 0, sizeof(struct Interface));
25 
26 	iface->state_info.changed = 1;
27 
28 	iface->IgnoreIfMissing = DFLT_IgnoreIfMissing;
29 	iface->AdvSendAdvert = DFLT_AdvSendAdv;
30 	iface->MaxRtrAdvInterval = DFLT_MaxRtrAdvInterval;
31 	iface->AdvSourceLLAddress = DFLT_AdvSourceLLAddress;
32 	iface->MinDelayBetweenRAs = DFLT_MinDelayBetweenRAs;
33 	iface->MinRtrAdvInterval = -1;
34 	iface->UnicastOnly = DFLT_UnicastOnly;
35 	iface->AdvRASolicitedUnicast = DFLT_AdvRASolicitedUnicast;
36 
37 	iface->ra_header_info.AdvDefaultPreference = DFLT_AdvDefaultPreference;
38 	iface->ra_header_info.AdvDefaultLifetime = -1;
39 	iface->ra_header_info.AdvReachableTime = DFLT_AdvReachableTime;
40 	iface->ra_header_info.AdvRetransTimer = DFLT_AdvRetransTimer;
41 	iface->ra_header_info.AdvCurHopLimit = DFLT_AdvCurHopLimit;
42 	iface->ra_header_info.AdvHomeAgentFlag = DFLT_AdvHomeAgentFlag;
43 
44 	iface->mipv6.AdvIntervalOpt = DFLT_AdvIntervalOpt;
45 	iface->mipv6.AdvHomeAgentInfo = DFLT_AdvHomeAgentInfo;
46 	iface->mipv6.HomeAgentPreference = DFLT_HomeAgentPreference;
47 	iface->mipv6.AdvMobRtrSupportFlag = DFLT_AdvMobRtrSupportFlag;
48 	iface->mipv6.HomeAgentLifetime = -1;
49 
50 	iface->AdvLinkMTU = DFLT_AdvLinkMTU;
51 	iface->AdvRAMTU = DFLT_AdvRAMTU;
52 }
53 
touch_iface(struct Interface * iface)54 void touch_iface(struct Interface *iface)
55 {
56 	iface->state_info.changed = 1;
57 	iface->state_info.ready = 0;
58 	iface->state_info.racount = 0;
59 	reschedule_iface(iface, 0);
60 }
61 
setup_iface(int sock,struct Interface * iface)62 int setup_iface(int sock, struct Interface *iface)
63 {
64 	int was_ready = iface->state_info.ready;
65 
66 	iface->state_info.changed = 0;
67 	iface->state_info.ready = 0;
68 
69 	/* The device index must be setup first so we can search it later */
70 	if (update_device_index(iface) < 0) {
71 		return -1;
72 	}
73 
74 	/* Check IFF_UP, IFF_RUNNING and IFF_MULTICAST */
75 	if (check_device(sock, iface) < 0) {
76 		return -1;
77 	}
78 
79 	/* Set iface->max_mtu and iface hardware address */
80 	if (update_device_info(sock, iface) < 0) {
81 		return -1;
82 	}
83 
84 	/* Make sure the settings in the config file for this interface are ok (this depends
85 	 * on iface->max_mtu already being set). */
86 	if (check_iface(iface) < 0) {
87 		return -1;
88 	}
89 
90 	/* Save the first link local address seen on the specified interface to
91 	 * iface->props.if_addr and keep a list off all addrs in iface->props.if_addrs */
92 	if (setup_iface_addrs(iface) < 0) {
93 		return -1;
94 	}
95 
96 	/* Check if we a usable RA source address */
97 	if (iface->props.if_addr_rasrc == NULL) {
98 		dlog(LOG_DEBUG, 5, "no configured AdvRASrcAddress present, skipping send");
99 		return -1;
100 	}
101 
102 	iface->state_info.ready = was_ready;
103 
104 	/* join the allrouters multicast group so we get the solicitations */
105 	if (setup_allrouters_membership(sock, iface) < 0) {
106 		iface->state_info.ready = 0;
107 		return -1;
108 	}
109 
110 	iface->state_info.ready = 1;
111 
112 	dlog(LOG_DEBUG, 4, "%s is ready", iface->props.name);
113 
114 	return 0;
115 }
116 
prefix_init_defaults(struct AdvPrefix * prefix)117 void prefix_init_defaults(struct AdvPrefix *prefix)
118 {
119 	memset(prefix, 0, sizeof(struct AdvPrefix));
120 
121 	prefix->AdvOnLinkFlag = DFLT_AdvOnLinkFlag;
122 	prefix->AdvAutonomousFlag = DFLT_AdvAutonomousFlag;
123 	prefix->AdvRouterAddr = DFLT_AdvRouterAddr;
124 	prefix->AdvValidLifetime = DFLT_AdvValidLifetime;
125 	prefix->AdvPreferredLifetime = DFLT_AdvPreferredLifetime;
126 	prefix->DeprecatePrefixFlag = DFLT_DeprecatePrefixFlag;
127 	prefix->DecrementLifetimesFlag = DFLT_DecrementLifetimesFlag;
128 
129 	prefix->curr_validlft = prefix->AdvValidLifetime;
130 	prefix->curr_preferredlft = prefix->AdvPreferredLifetime;
131 }
132 
route_init_defaults(struct AdvRoute * route,struct Interface * iface)133 void route_init_defaults(struct AdvRoute *route, struct Interface *iface)
134 {
135 	memset(route, 0, sizeof(struct AdvRoute));
136 
137 	route->AdvRouteLifetime = DFLT_AdvRouteLifetime(iface);
138 	route->AdvRoutePreference = DFLT_AdvRoutePreference;
139 	route->RemoveRouteFlag = DFLT_RemoveRouteFlag;
140 }
141 
rdnss_init_defaults(struct AdvRDNSS * rdnss,struct Interface * iface)142 void rdnss_init_defaults(struct AdvRDNSS *rdnss, struct Interface *iface)
143 {
144 	memset(rdnss, 0, sizeof(struct AdvRDNSS));
145 
146 	rdnss->AdvRDNSSLifetime = DFLT_AdvRDNSSLifetime(iface);
147 	rdnss->AdvRDNSSNumber = 0;
148 	rdnss->FlushRDNSSFlag = DFLT_FlushRDNSSFlag;
149 }
150 
dnssl_init_defaults(struct AdvDNSSL * dnssl,struct Interface * iface)151 void dnssl_init_defaults(struct AdvDNSSL *dnssl, struct Interface *iface)
152 {
153 	memset(dnssl, 0, sizeof(struct AdvDNSSL));
154 
155 	dnssl->AdvDNSSLLifetime = DFLT_AdvDNSSLLifetime(iface);
156 	dnssl->FlushDNSSLFlag = DFLT_FlushDNSSLFlag;
157 }
158 
check_iface(struct Interface * iface)159 int check_iface(struct Interface *iface)
160 {
161 	int res = 0;
162 	int MIPv6 = 0;
163 	struct in6_addr zeroaddr;
164 	memset(&zeroaddr, 0, sizeof(zeroaddr));
165 
166 	/* Check if we use Mobile IPv6 extensions */
167 	if (iface->ra_header_info.AdvHomeAgentFlag || iface->mipv6.AdvHomeAgentInfo || iface->mipv6.AdvIntervalOpt) {
168 		MIPv6 = 1;
169 		flog(LOG_INFO, "using Mobile IPv6 extensions");
170 	}
171 
172 	/* Check forwarding on interface */
173 	if (check_ip6_iface_forwarding(iface->props.name) < 1) {
174 		flog(LOG_WARNING, "IPv6 forwarding on interface seems to be disabled, but continuing anyway");
175 	}
176 
177 	struct AdvPrefix *prefix = iface->AdvPrefixList;
178 	while (!MIPv6 && prefix) {
179 		if (prefix->AdvRouterAddr) {
180 			MIPv6 = 1;
181 		}
182 		prefix = prefix->next;
183 	}
184 
185 	if (iface->MinRtrAdvInterval < 0)
186 		iface->MinRtrAdvInterval = DFLT_MinRtrAdvInterval(iface);
187 
188 	if ((iface->MinRtrAdvInterval < (MIPv6 ? MIN_MinRtrAdvInterval_MIPv6 : MIN_MinRtrAdvInterval)) ||
189 	    (iface->MinRtrAdvInterval > MAX_MinRtrAdvInterval(iface))) {
190 		flog(LOG_ERR,
191 		     "MinRtrAdvInterval for %s (%.2f) must be at least %.2f but no more than 3/4 of MaxRtrAdvInterval (%.2f)",
192 		     iface->props.name, iface->MinRtrAdvInterval,
193 		     MIPv6 ? MIN_MinRtrAdvInterval_MIPv6 : (int)MIN_MinRtrAdvInterval, MAX_MinRtrAdvInterval(iface));
194 		res = -1;
195 	}
196 
197 	if ((iface->MaxRtrAdvInterval < (MIPv6 ? MIN_MaxRtrAdvInterval_MIPv6 : MIN_MaxRtrAdvInterval)) ||
198 	    (iface->MaxRtrAdvInterval > MAX_MaxRtrAdvInterval)) {
199 		flog(LOG_ERR, "MaxRtrAdvInterval for %s (%.2f) must be between %.2f and %d", iface->props.name,
200 		     iface->MaxRtrAdvInterval, MIPv6 ? MIN_MaxRtrAdvInterval_MIPv6 : (int)MIN_MaxRtrAdvInterval,
201 		     MAX_MaxRtrAdvInterval);
202 		res = -1;
203 	}
204 
205 	if (iface->MinDelayBetweenRAs < (MIPv6 ? MIN_DELAY_BETWEEN_RAS_MIPv6 : MIN_DELAY_BETWEEN_RAS)) {
206 		flog(LOG_ERR, "MinDelayBetweenRAs for %s (%.2f) must be at least %.2f", iface->props.name,
207 		     iface->MinDelayBetweenRAs, MIPv6 ? MIN_DELAY_BETWEEN_RAS_MIPv6 : MIN_DELAY_BETWEEN_RAS);
208 		res = -1;
209 	}
210 
211 	if ((iface->AdvLinkMTU != 0) && ((iface->AdvLinkMTU < MIN_AdvLinkMTU) ||
212 					 (iface->sllao.if_maxmtu != -1 && (iface->AdvLinkMTU > iface->sllao.if_maxmtu)))) {
213 		flog(LOG_ERR, "AdvLinkMTU for %s (%u) must be zero or between %u and %u", iface->props.name, iface->AdvLinkMTU,
214 		     MIN_AdvLinkMTU, iface->sllao.if_maxmtu);
215 		res = -1;
216 	}
217 
218 	if (iface->ra_header_info.AdvReachableTime > MAX_AdvReachableTime) {
219 		flog(LOG_ERR, "AdvReachableTime for %s (%u) must not be greater than %u", iface->props.name,
220 		     iface->ra_header_info.AdvReachableTime, MAX_AdvReachableTime);
221 		res = -1;
222 	}
223 
224 	if (iface->ra_header_info.AdvDefaultLifetime < 0)
225 		iface->ra_header_info.AdvDefaultLifetime = DFLT_AdvDefaultLifetime(iface);
226 
227 	if ((iface->ra_header_info.AdvDefaultLifetime != 0) &&
228 	    ((iface->ra_header_info.AdvDefaultLifetime > MAX_AdvDefaultLifetime) ||
229 	     (iface->ra_header_info.AdvDefaultLifetime < MIN_AdvDefaultLifetime(iface)))) {
230 		flog(LOG_ERR, "AdvDefaultLifetime for %s (%u) must be zero or between %u and %u", iface->props.name,
231 		     iface->ra_header_info.AdvDefaultLifetime, (int)MIN_AdvDefaultLifetime(iface), MAX_AdvDefaultLifetime);
232 		res = -1;
233 	}
234 
235 	/* Mobile IPv6 ext */
236 	if (iface->mipv6.HomeAgentLifetime < 0)
237 		iface->mipv6.HomeAgentLifetime = DFLT_HomeAgentLifetime(iface);
238 
239 	/* Mobile IPv6 ext */
240 	if (iface->mipv6.AdvHomeAgentInfo) {
241 		if ((iface->mipv6.HomeAgentLifetime > MAX_HomeAgentLifetime) ||
242 		    (iface->mipv6.HomeAgentLifetime < MIN_HomeAgentLifetime)) {
243 			flog(LOG_ERR, "HomeAgentLifetime for %s (%u) must be between %u and %u", iface->props.name,
244 			     iface->mipv6.HomeAgentLifetime, MIN_HomeAgentLifetime, MAX_HomeAgentLifetime);
245 			res = -1;
246 		}
247 	}
248 
249 	/* Mobile IPv6 ext */
250 	if (iface->mipv6.AdvHomeAgentInfo && !(iface->ra_header_info.AdvHomeAgentFlag)) {
251 		flog(LOG_ERR, "AdvHomeAgentFlag for %s must be set with HomeAgentInfo", iface->props.name);
252 		res = -1;
253 	}
254 	if (iface->mipv6.AdvMobRtrSupportFlag && !(iface->mipv6.AdvHomeAgentInfo)) {
255 		flog(LOG_ERR, "AdvHomeAgentInfo for %s must be set with AdvMobRtrSupportFlag", iface->props.name);
256 		res = -1;
257 	}
258 
259 	/* XXX: need this? prefix = iface->AdvPrefixList; */
260 
261 	while (prefix) {
262 		if (prefix->PrefixLen > MAX_PrefixLen) {
263 			flog(LOG_ERR, "invalid prefix length (%u) for %s", prefix->PrefixLen, iface->props.name);
264 			res = -1;
265 		}
266 
267 		if (prefix->AdvPreferredLifetime > prefix->AdvValidLifetime) {
268 			flog(LOG_ERR, "AdvValidLifetime for %s (%u) must be "
269 				      "greater than AdvPreferredLifetime for",
270 			     iface->props.name, prefix->AdvValidLifetime);
271 			res = -1;
272 		}
273 
274 		prefix = prefix->next;
275 	}
276 
277 	struct AdvRoute *route = iface->AdvRouteList;
278 	while (route) {
279 		if (route->PrefixLen > MAX_PrefixLen) {
280 			flog(LOG_ERR, "invalid route prefix length (%u) for %s", route->PrefixLen, iface->props.name);
281 			res = -1;
282 		}
283 
284 		/* For the default route 0::/0, we need to explicitly check the
285 		 * lifetime against the AdvDefaultLifetime value.
286 		 *
287 		 * If exactly one of the two has a zero value, then nodes processing
288 		 * the RA may have a flap in their default route.
289 		 *
290 		 * AdvDefaultLifetime == 0 && route.AdvRouteLifetime > 0:
291 		 * - default route is deleted and then re-added.
292 		 * AdvDefaultLifetime > 0 && route.AdvRouteLifetime == 0:
293 		 * - default route is added and then deleted.
294 		 */
295 		if (IN6_IS_ADDR_UNSPECIFIED(&(route->Prefix))) {
296 			int route_zerolife = (route->AdvRouteLifetime == 0);
297 			int defaultroute_zerolife = (iface->ra_header_info.AdvDefaultLifetime == 0);
298 			if (route_zerolife ^ defaultroute_zerolife) {
299 				flog(
300 				    LOG_ERR,
301 				    "route 0::/0 lifetime (%u) conflicts with AdvDefaultLifetime (%u), default routes will flap!",
302 				    route->AdvRouteLifetime, iface->ra_header_info.AdvDefaultLifetime);
303 				// res = -1; // In some future version, abort on this configuration error.
304 			}
305 		}
306 
307 		route = route->next;
308 	}
309 
310 	return res;
311 }
312 
find_iface_by_index(struct Interface * iface,int index)313 struct Interface *find_iface_by_index(struct Interface *iface, int index)
314 {
315 	for (; iface; iface = iface->next) {
316 		if (iface->props.if_index == index) {
317 			return iface;
318 		}
319 	}
320 
321 	return 0;
322 }
323 
find_iface_by_name(struct Interface * iface,const char * name)324 struct Interface *find_iface_by_name(struct Interface *iface, const char *name)
325 {
326 	if (!name) {
327 		return 0;
328 	}
329 
330 	for (; iface; iface = iface->next) {
331 		if (strcmp(iface->props.name, name) == 0) {
332 			return iface;
333 		}
334 	}
335 
336 	return 0;
337 }
338 
find_iface_by_time(struct Interface * iface)339 struct Interface *find_iface_by_time(struct Interface *iface)
340 {
341 	if (!iface) {
342 		return 0;
343 	}
344 
345 	int timeout = next_time_msec(iface);
346 	struct Interface *next = iface;
347 
348 	for (iface = iface->next; iface; iface = iface->next) {
349 		int t = next_time_msec(iface);
350 		if (timeout > t) {
351 			timeout = t;
352 			next = iface;
353 		}
354 	}
355 
356 	return next;
357 }
358 
reschedule_iface(struct Interface * iface,double next)359 void reschedule_iface(struct Interface *iface, double next)
360 {
361 #ifdef HAVE_NETLINK
362 	if (!iface->state_info.changed && !iface->state_info.ready) {
363 		next = 10 * iface->MaxRtrAdvInterval;
364 	} else if (next == 0) {
365 		next = IFACE_SETUP_DELAY;
366 	} else
367 #endif
368 	    if (iface->state_info.racount < MAX_INITIAL_RTR_ADVERTISEMENTS) {
369 		next = min(MAX_INITIAL_RTR_ADVERT_INTERVAL, iface->MaxRtrAdvInterval);
370 	}
371 
372 	dlog(LOG_DEBUG, 5, "%s next scheduled RA in %g second(s)", iface->props.name, next);
373 
374 	iface->times.next_multicast = next_timespec(next);
375 }
376 
for_each_iface(struct Interface * ifaces,void (* foo)(struct Interface *,void *),void * data)377 void for_each_iface(struct Interface *ifaces, void (*foo)(struct Interface *, void *), void *data)
378 {
379 	for (; ifaces; ifaces = ifaces->next) {
380 		foo(ifaces, data);
381 	}
382 }
383 
free_iface_list(struct Interface * iface)384 static void free_iface_list(struct Interface *iface)
385 {
386 	while (iface) {
387 		struct Interface *next_iface = iface->next;
388 
389 		dlog(LOG_DEBUG, 4, "freeing interface %s", iface->props.name);
390 
391 		struct AdvPrefix *prefix = iface->AdvPrefixList;
392 		while (prefix) {
393 			struct AdvPrefix *next_prefix = prefix->next;
394 
395 			free(prefix);
396 			prefix = next_prefix;
397 		}
398 
399 		struct AdvRoute *route = iface->AdvRouteList;
400 		while (route) {
401 			struct AdvRoute *next_route = route->next;
402 
403 			free(route);
404 			route = next_route;
405 		}
406 
407 		struct AdvRDNSS *rdnss = iface->AdvRDNSSList;
408 		while (rdnss) {
409 			struct AdvRDNSS *next_rdnss = rdnss->next;
410 
411 			free(rdnss);
412 			rdnss = next_rdnss;
413 		}
414 
415 		struct AdvDNSSL *dnssl = iface->AdvDNSSLList;
416 		while (dnssl) {
417 			struct AdvDNSSL *next_dnssl = dnssl->next;
418 
419 			for (int i = 0; i < dnssl->AdvDNSSLNumber; i++)
420 				free(dnssl->AdvDNSSLSuffixes[i]);
421 			free(dnssl->AdvDNSSLSuffixes);
422 			free(dnssl);
423 
424 			dnssl = next_dnssl;
425 		}
426 
427 		struct Clients *clients = iface->ClientList;
428 		while (clients) {
429 			struct Clients *next_client = clients->next;
430 
431 			free(clients);
432 			clients = next_client;
433 		}
434 
435 		free(iface->props.if_addrs);
436 
437 		free(iface);
438 		iface = next_iface;
439 	}
440 }
441 
free_ifaces(struct Interface * ifaces)442 void free_ifaces(struct Interface *ifaces)
443 {
444 	dlog(LOG_DEBUG, 3, "Freeing Interfaces");
445 
446 	free_iface_list(ifaces);
447 }
448