xref: /titanic_52/usr/src/cmd/cmd-inet/usr.lib/in.ndpd/tables.c (revision d58fda4376e4bf67072ce2e69f6f47036f9dbb68)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include "defs.h"
30 #include "tables.h"
31 
32 #include <time.h>
33 #include <inet/ip6.h>
34 
35 struct phyint *phyints = NULL;
36 
37 static void	phyint_print(struct phyint *pi);
38 static void	phyint_insert(struct phyint *pi);
39 
40 static boolean_t tmptoken_isvalid(struct in6_addr *token);
41 
42 static void	prefix_print(struct prefix *pr);
43 static void	prefix_insert(struct phyint *pi, struct prefix *pr);
44 static char	*prefix_print_state(int state, char *buf, int buflen);
45 static void	prefix_set(struct in6_addr *prefix, struct in6_addr addr,
46 		    int bits);
47 
48 static void	adv_prefix_print(struct adv_prefix *adv_pr);
49 static void	adv_prefix_insert(struct phyint *pi, struct adv_prefix *adv_pr);
50 static void	adv_prefix_delete(struct adv_prefix *adv_pr);
51 
52 static void	router_print(struct router *dr);
53 static void	router_insert(struct phyint *pi, struct router *dr);
54 static void	router_delete(struct router *dr);
55 static void	router_add_k(struct router *dr);
56 static void	router_delete_k(struct router *dr);
57 static void	router_delete_onlink(struct phyint *pi);
58 
59 static int	rtmseq;				/* rtm_seq sequence number */
60 
61 /* 1 week in ms */
62 #define	NDP_PREFIX_DEFAULT_LIFETIME	(7*24*60*60*1000)
63 struct phyint *
64 phyint_lookup(char *name)
65 {
66 	struct phyint *pi;
67 
68 	if (debug & D_PHYINT)
69 		logmsg(LOG_DEBUG, "phyint_lookup(%s)\n", name);
70 
71 	for (pi = phyints; pi != NULL; pi = pi->pi_next) {
72 		if (strcmp(pi->pi_name, name) == 0)
73 			break;
74 	}
75 	return (pi);
76 }
77 
78 struct phyint *
79 phyint_lookup_on_index(uint_t ifindex)
80 {
81 	struct phyint *pi;
82 
83 	if (debug & D_PHYINT)
84 		logmsg(LOG_DEBUG, "phyint_lookup_on_index(%d)\n", ifindex);
85 
86 	for (pi = phyints; pi != NULL; pi = pi->pi_next) {
87 		if (pi->pi_index == ifindex)
88 			break;
89 	}
90 	return (pi);
91 }
92 
93 struct phyint *
94 phyint_create(char *name)
95 {
96 	struct phyint *pi;
97 	int i;
98 
99 	if (debug & D_PHYINT)
100 		logmsg(LOG_DEBUG, "phyint_create(%s)\n", name);
101 
102 	pi = (struct phyint *)calloc(sizeof (struct phyint), 1);
103 	if (pi == NULL) {
104 		logmsg(LOG_ERR, "phyint_create: out of memory\n");
105 		return (NULL);
106 	}
107 	(void) strncpy(pi->pi_name, name, sizeof (pi->pi_name));
108 	pi->pi_name[sizeof (pi->pi_name) - 1] = '\0';
109 
110 	/*
111 	 * Copy the defaults from the defaults array.
112 	 * Do not copy the cf_notdefault fields since these have not
113 	 * been explicitly set for the phyint.
114 	 */
115 	for (i = 0; i < I_IFSIZE; i++)
116 		pi->pi_config[i].cf_value = ifdefaults[i].cf_value;
117 
118 	/*
119 	 * TmpDesyncFactor is used to desynchronize temporary token
120 	 * generation among systems; the actual preferred lifetime value
121 	 * of a temporary address will be (TmpPreferredLifetime -
122 	 * TmpDesyncFactor).  It's a random value, with a user-configurable
123 	 * maximum value.  The value is constant throughout the lifetime
124 	 * of the in.ndpd process, but can change if the daemon is restarted,
125 	 * per RFC3041.
126 	 */
127 	if (pi->pi_TmpMaxDesyncFactor != 0) {
128 		time_t seed = time(NULL);
129 		srand((uint_t)seed);
130 		pi->pi_TmpDesyncFactor = rand() % pi->pi_TmpMaxDesyncFactor;
131 		/* we actually want [1,max], not [0,(max-1)] */
132 		pi->pi_TmpDesyncFactor++;
133 	}
134 	pi->pi_TmpRegenCountdown = TIMER_INFINITY;
135 
136 	pi->pi_sock = -1;
137 	if (phyint_init_from_k(pi) == -1) {
138 		if (pi->pi_group_name != NULL)
139 			free(pi->pi_group_name);
140 		free(pi);
141 		return (NULL);
142 	}
143 	phyint_insert(pi);
144 	if (pi->pi_sock != -1) {
145 		if (poll_add(pi->pi_sock) == -1) {
146 			phyint_delete(pi);
147 			return (NULL);
148 		}
149 	}
150 	return (pi);
151 }
152 
153 /* Insert in linked list */
154 static void
155 phyint_insert(struct phyint *pi)
156 {
157 	/* Insert in list */
158 	pi->pi_next = phyints;
159 	pi->pi_prev = NULL;
160 	if (phyints)
161 		phyints->pi_prev = pi;
162 	phyints = pi;
163 }
164 
165 /*
166  * Initialize both the phyint data structure and the pi_sock for
167  * sending and receving on the interface.
168  * Extract information from the kernel (if present) and set pi_kernel_state.
169  */
170 int
171 phyint_init_from_k(struct phyint *pi)
172 {
173 	struct ipv6_mreq v6mcastr;
174 	struct lifreq lifr;
175 	int fd;
176 	boolean_t newsock;
177 	uint_t ttl;
178 	struct sockaddr_in6 *sin6;
179 
180 	if (debug & D_PHYINT)
181 		logmsg(LOG_DEBUG, "phyint_init_from_k(%s)\n", pi->pi_name);
182 
183 start_over:
184 
185 	if (pi->pi_sock < 0) {
186 		pi->pi_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
187 		if (pi->pi_sock < 0) {
188 			logperror_pi(pi, "phyint_init_from_k: socket");
189 			return (-1);
190 		}
191 		newsock = _B_TRUE;
192 	} else {
193 		newsock = _B_FALSE;
194 	}
195 	fd = pi->pi_sock;
196 
197 	(void) strncpy(lifr.lifr_name, pi->pi_name, sizeof (lifr.lifr_name));
198 	lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
199 	if (ioctl(fd, SIOCGLIFINDEX, (char *)&lifr) < 0) {
200 		if (errno == ENXIO) {
201 			if (newsock) {
202 				(void) close(pi->pi_sock);
203 				pi->pi_sock = -1;
204 			}
205 			if (debug & D_PHYINT) {
206 				logmsg(LOG_DEBUG, "phyint_init_from_k(%s): "
207 				    "not exist\n", pi->pi_name);
208 			}
209 			return (0);
210 		}
211 		logperror_pi(pi, "phyint_init_from_k: SIOCGLIFINDEX");
212 		goto error;
213 	}
214 
215 	if (!newsock && (pi->pi_index != lifr.lifr_index)) {
216 		/*
217 		 * Interface has been re-plumbed, lets open a new socket.
218 		 * This situation can occur if plumb/unplumb are happening
219 		 * quite frequently.
220 		 */
221 
222 		phyint_cleanup(pi);
223 		goto start_over;
224 	}
225 
226 	pi->pi_index = lifr.lifr_index;
227 
228 	if (ioctl(fd, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
229 		logperror_pi(pi, "phyint_init_from_k: ioctl (get flags)");
230 		goto error;
231 	}
232 	pi->pi_flags = lifr.lifr_flags;
233 
234 	/*
235 	 * If the  link local interface is not up yet or it's IFF_UP
236 	 * and the flag is set to IFF_NOLOCAL as Duplicate Address
237 	 * Detection is in progress.
238 	 * IFF_NOLOCAL is "normal" on other prefixes.
239 	 */
240 
241 	if (!(pi->pi_flags & IFF_UP) || (pi->pi_flags & IFF_NOLOCAL)) {
242 		if (newsock) {
243 			(void) close(pi->pi_sock);
244 			pi->pi_sock = -1;
245 		}
246 		if (debug & D_PHYINT) {
247 			logmsg(LOG_DEBUG, "phyint_init_from_k(%s): "
248 			    "not IFF_UP\n", pi->pi_name);
249 		}
250 		return (0);
251 	}
252 	pi->pi_kernel_state |= PI_PRESENT;
253 
254 	bzero(lifr.lifr_groupname, sizeof (lifr.lifr_groupname));
255 	if (ioctl(fd, SIOCGLIFGROUPNAME, (caddr_t)&lifr) < 0) {
256 		logperror_pi(pi, "phyint_init_from_k: ioctl (get group name)");
257 		goto error;
258 	}
259 
260 	if (lifr.lifr_groupname != NULL && strlen(lifr.lifr_groupname) != 0) {
261 		if (pi->pi_group_name == NULL) {
262 			pi->pi_group_name = malloc(
263 			    sizeof (lifr.lifr_groupname));
264 			if (pi->pi_group_name == NULL) {
265 				logperror_pi(pi, "phyint_init_from_k:"
266 				    " malloc(group name)");
267 				goto error;
268 			}
269 		}
270 		/*
271 		 * Size of the group name can only be LIFNAMESZ -1 characters
272 		 * which is ensured by kernel. Thus, we don't need strncpy.
273 		 */
274 		(void) strncpy(pi->pi_group_name, lifr.lifr_groupname,
275 		    sizeof (lifr.lifr_name));
276 		pi->pi_group_name[sizeof (pi->pi_group_name) - 1] = '\0';
277 	} else if (pi->pi_group_name != NULL) {
278 		free(pi->pi_group_name);
279 		pi->pi_group_name = NULL;
280 	}
281 
282 	if (ioctl(fd, SIOCGLIFMTU, (caddr_t)&lifr) < 0) {
283 		logperror_pi(pi, "phyint_init_from_k: ioctl (get mtu)");
284 		goto error;
285 	}
286 	pi->pi_mtu = lifr.lifr_mtu;
287 
288 	if (ioctl(fd, SIOCGLIFADDR, (char *)&lifr) < 0) {
289 		logperror_pi(pi, "phyint_init_from_k: SIOCGLIFADDR");
290 		goto error;
291 	}
292 	sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
293 	pi->pi_ifaddr = sin6->sin6_addr;
294 
295 	if (ioctl(fd, SIOCGLIFTOKEN, (char *)&lifr) < 0) {
296 		logperror_pi(pi, "phyint_init_from_k: SIOCGLIFTOKEN");
297 		goto error;
298 	}
299 	/* Ignore interface if the token is all zeros */
300 	sin6 = (struct sockaddr_in6 *)&lifr.lifr_token;
301 	if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
302 		logmsg(LOG_ERR, "ignoring interface %s: zero token\n",
303 		    pi->pi_name);
304 		goto error;
305 	}
306 	pi->pi_token = sin6->sin6_addr;
307 	pi->pi_token_length = lifr.lifr_addrlen;
308 
309 	/*
310 	 * Guess a remote token for POINTOPOINT by looking at
311 	 * the link-local destination address.
312 	 */
313 	if (pi->pi_flags & IFF_POINTOPOINT) {
314 		if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifr) < 0) {
315 			logperror_pi(pi, "phyint_init_from_k: SIOCGLIFDSTADDR");
316 			goto error;
317 		}
318 		sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
319 		if (sin6->sin6_family != AF_INET6 ||
320 		    IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
321 		    !IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
322 			pi->pi_dst_token = in6addr_any;
323 		} else {
324 			pi->pi_dst_token = sin6->sin6_addr;
325 			/* Clear link-local prefix (first 10 bits) */
326 			pi->pi_dst_token.s6_addr[0] = 0;
327 			pi->pi_dst_token.s6_addr[1] &= 0x3f;
328 		}
329 	} else {
330 		pi->pi_dst_token = in6addr_any;
331 	}
332 
333 	/* Get link-layer address */
334 	if (!(pi->pi_flags & IFF_MULTICAST) ||
335 	    (pi->pi_flags & IFF_POINTOPOINT)) {
336 		pi->pi_hdw_addr_len = 0;
337 	} else {
338 		sin6 = (struct sockaddr_in6 *)&lifr.lifr_nd.lnr_addr;
339 		bzero(sin6, sizeof (struct sockaddr_in6));
340 		sin6->sin6_family = AF_INET6;
341 		sin6->sin6_addr = pi->pi_ifaddr;
342 
343 		if (ioctl(fd, SIOCLIFGETND, (char *)&lifr) < 0) {
344 			logperror_pi(pi, "phyint_init_from_k: SIOCLIFGETND");
345 			goto error;
346 		}
347 
348 		pi->pi_hdw_addr_len = lifr.lifr_nd.lnr_hdw_len;
349 
350 		if (lifr.lifr_nd.lnr_hdw_len != 0) {
351 			bcopy((char *)lifr.lifr_nd.lnr_hdw_addr,
352 			    (char *)pi->pi_hdw_addr,
353 			    lifr.lifr_nd.lnr_hdw_len);
354 		}
355 	}
356 
357 	if (newsock) {
358 		icmp6_filter_t filter;
359 		int on = 1;
360 
361 		/* Set default values */
362 		pi->pi_LinkMTU = pi->pi_mtu;
363 		pi->pi_CurHopLimit = 0;
364 		pi->pi_BaseReachableTime = ND_REACHABLE_TIME;
365 		phyint_reach_random(pi, _B_FALSE);
366 		pi->pi_RetransTimer = ND_RETRANS_TIMER;
367 
368 		/* Setup socket for transmission and reception */
369 		if (setsockopt(fd, IPPROTO_IPV6,
370 		    IPV6_BOUND_IF, (char *)&pi->pi_index,
371 		    sizeof (pi->pi_index)) < 0) {
372 			logperror_pi(pi, "phyint_init_from_k: setsockopt "
373 			    "IPV6_BOUND_IF");
374 			goto error;
375 		}
376 
377 		ttl = IPV6_MAX_HOPS;
378 		if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
379 		    (char *)&ttl, sizeof (ttl)) < 0) {
380 			logperror_pi(pi, "phyint_init_from_k: setsockopt "
381 			    "IPV6_UNICAST_HOPS");
382 			goto error;
383 		}
384 
385 		if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
386 		    (char *)&ttl, sizeof (ttl)) < 0) {
387 			logperror_pi(pi, "phyint_init_from_k: setsockopt "
388 			    "IPV6_MULTICAST_HOPS");
389 			goto error;
390 		}
391 
392 		v6mcastr.ipv6mr_multiaddr = all_nodes_mcast;
393 		v6mcastr.ipv6mr_interface = pi->pi_index;
394 		if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
395 		    (char *)&v6mcastr, sizeof (v6mcastr)) < 0) {
396 			logperror_pi(pi, "phyint_init_from_k: "
397 			    "setsockopt IPV6_JOIN_GROUP");
398 			goto error;
399 		}
400 		pi->pi_state |= PI_JOINED_ALLNODES;
401 		pi->pi_kernel_state |= PI_JOINED_ALLNODES;
402 
403 		/*
404 		 * Filter out so that we only receive router advertisements and
405 		 * router solicitations.
406 		 */
407 		ICMP6_FILTER_SETBLOCKALL(&filter);
408 		ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
409 		ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
410 
411 		if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER,
412 		    (char *)&filter, sizeof (filter)) < 0) {
413 			logperror_pi(pi, "phyint_init_from_k: setsockopt "
414 			    "ICMP6_FILTER");
415 			goto error;
416 		}
417 
418 		/* Enable receipt of ancillary data */
419 		if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
420 		    (char *)&on, sizeof (on)) < 0) {
421 			logperror_pi(pi, "phyint_init_from_k: setsockopt "
422 			    "IPV6_RECVHOPLIMIT");
423 			goto error;
424 		}
425 		if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVRTHDR,
426 		    (char *)&on, sizeof (on)) < 0) {
427 			logperror_pi(pi, "phyint_init_from_k: setsockopt "
428 			    "IPV6_RECVRTHDR");
429 			goto error;
430 		}
431 	}
432 
433 	if (pi->pi_AdvSendAdvertisements &&
434 	    !(pi->pi_kernel_state & PI_JOINED_ALLROUTERS)) {
435 		v6mcastr.ipv6mr_multiaddr = all_routers_mcast;
436 		v6mcastr.ipv6mr_interface = pi->pi_index;
437 		if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
438 		    (char *)&v6mcastr, sizeof (v6mcastr)) < 0) {
439 			logperror_pi(pi, "phyint_init_from_k: setsockopt "
440 			    "IPV6_JOIN_GROUP");
441 			goto error;
442 		}
443 		pi->pi_state |= PI_JOINED_ALLROUTERS;
444 		pi->pi_kernel_state |= PI_JOINED_ALLROUTERS;
445 	}
446 	/*
447 	 * If not already set, set the IFF_ROUTER interface flag based on
448 	 * AdvSendAdvertisements.  Note that this will also enable IPv6
449 	 * forwarding on the interface.  We don't clear IFF_ROUTER if we're
450 	 * not advertising on an interface, because we could still be
451 	 * forwarding on those interfaces.
452 	 */
453 	(void) strncpy(lifr.lifr_name, pi->pi_name, sizeof (lifr.lifr_name));
454 	lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
455 	if (ioctl(fd, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
456 		logperror_pi(pi, "phyint_init_from_k: SIOCGLIFFLAGS");
457 		goto error;
458 	}
459 	if (!(lifr.lifr_flags & IFF_ROUTER) && pi->pi_AdvSendAdvertisements) {
460 		lifr.lifr_flags |= IFF_ROUTER;
461 
462 		if (ioctl(fd, SIOCSLIFFLAGS, (char *)&lifr) < 0) {
463 			logperror_pi(pi, "phyint_init_from_k: SIOCSLIFFLAGS");
464 			goto error;
465 		}
466 		pi->pi_flags = lifr.lifr_flags;
467 	}
468 
469 	/* Set linkinfo parameters */
470 	(void) strncpy(lifr.lifr_name, pi->pi_name, sizeof (lifr.lifr_name));
471 	lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
472 	if (ioctl(fd, SIOCGLIFLNKINFO, (char *)&lifr) < 0) {
473 		logperror_pi(pi, "phyint_init_from_k: SIOCGLIFLNKINFO");
474 		goto error;
475 	}
476 	lifr.lifr_ifinfo.lir_maxhops = pi->pi_CurHopLimit;
477 	lifr.lifr_ifinfo.lir_reachtime = pi->pi_ReachableTime;
478 	lifr.lifr_ifinfo.lir_reachretrans = pi->pi_RetransTimer;
479 	if (ioctl(fd, SIOCSLIFLNKINFO, (char *)&lifr) < 0) {
480 		logperror_pi(pi, "phyint_init_from_k: SIOCSLIFLNKINFO");
481 		goto error;
482 	}
483 	if (debug & D_PHYINT) {
484 		logmsg(LOG_DEBUG, "phyint_init_from_k(%s): done\n",
485 		    pi->pi_name);
486 	}
487 	return (0);
488 
489 error:
490 	/* Pretend the interface does not exist in the kernel */
491 	pi->pi_kernel_state &= ~PI_PRESENT;
492 	if (newsock) {
493 		(void) close(pi->pi_sock);
494 		pi->pi_sock = -1;
495 	}
496 	return (-1);
497 }
498 
499 /*
500  * Delete (unlink and free).
501  * Handles delete of things that have not yet been inserted in the list.
502  */
503 void
504 phyint_delete(struct phyint *pi)
505 {
506 	if (debug & D_PHYINT)
507 		logmsg(LOG_DEBUG, "phyint_delete(%s)\n", pi->pi_name);
508 
509 	while (pi->pi_router_list)
510 		router_delete(pi->pi_router_list);
511 	while (pi->pi_prefix_list)
512 		prefix_delete(pi->pi_prefix_list);
513 	while (pi->pi_adv_prefix_list)
514 		adv_prefix_delete(pi->pi_adv_prefix_list);
515 
516 	if (pi->pi_sock != -1) {
517 		(void) poll_remove(pi->pi_sock);
518 		if (close(pi->pi_sock) < 0) {
519 			logperror_pi(pi, "phyint_delete: close");
520 		}
521 		pi->pi_sock = -1;
522 	}
523 
524 	if (pi->pi_prev == NULL) {
525 		if (phyints == pi)
526 			phyints = pi->pi_next;
527 	} else {
528 		pi->pi_prev->pi_next = pi->pi_next;
529 	}
530 	if (pi->pi_next != NULL)
531 		pi->pi_next->pi_prev = pi->pi_prev;
532 	pi->pi_next = pi->pi_prev = NULL;
533 	if (pi->pi_group_name != NULL)
534 		free(pi->pi_group_name);
535 	free(pi);
536 }
537 
538 /*
539  * Called with the number of millseconds elapsed since the last call.
540  * Determines if any timeout event has occurred and
541  * returns the number of milliseconds until the next timeout event
542  * for the phyint iself (excluding prefixes and routers).
543  * Returns TIMER_INFINITY for "never".
544  */
545 uint_t
546 phyint_timer(struct phyint *pi, uint_t elapsed)
547 {
548 	uint_t next = TIMER_INFINITY;
549 
550 	if (pi->pi_AdvSendAdvertisements) {
551 		if (pi->pi_adv_state != NO_ADV) {
552 			int old_state = pi->pi_adv_state;
553 
554 			if (debug & (D_STATE|D_PHYINT)) {
555 				logmsg(LOG_DEBUG, "phyint_timer ADV(%s) "
556 				    "state %d\n", pi->pi_name, (int)old_state);
557 			}
558 			next = advertise_event(pi, ADV_TIMER, elapsed);
559 			if (debug & D_STATE) {
560 				logmsg(LOG_DEBUG, "phyint_timer ADV(%s) "
561 				    "state %d -> %d\n",
562 				    pi->pi_name, (int)old_state,
563 				    (int)pi->pi_adv_state);
564 			}
565 		}
566 	} else {
567 		if (pi->pi_sol_state != NO_SOLICIT) {
568 			int old_state = pi->pi_sol_state;
569 
570 			if (debug & (D_STATE|D_PHYINT)) {
571 				logmsg(LOG_DEBUG, "phyint_timer SOL(%s) "
572 				    "state %d\n", pi->pi_name, (int)old_state);
573 			}
574 			next = solicit_event(pi, SOL_TIMER, elapsed);
575 			if (debug & D_STATE) {
576 				logmsg(LOG_DEBUG, "phyint_timer SOL(%s) "
577 				    "state %d -> %d\n",
578 				    pi->pi_name, (int)old_state,
579 				    (int)pi->pi_sol_state);
580 			}
581 		}
582 	}
583 
584 	/*
585 	 * If the phyint has been unplumbed, we don't want to call
586 	 * phyint_reach_random. We will be in the NO_ADV or NO_SOLICIT state.
587 	 */
588 	if ((pi->pi_AdvSendAdvertisements && (pi->pi_adv_state != NO_ADV)) ||
589 	    (!pi->pi_AdvSendAdvertisements &&
590 	    (pi->pi_sol_state != NO_SOLICIT))) {
591 		pi->pi_reach_time_since_random += elapsed;
592 		if (pi->pi_reach_time_since_random >= MAX_REACH_RANDOM_INTERVAL)
593 			phyint_reach_random(pi, _B_TRUE);
594 	}
595 
596 	return (next);
597 }
598 
599 static void
600 phyint_print(struct phyint *pi)
601 {
602 	struct prefix *pr;
603 	struct adv_prefix *adv_pr;
604 	struct router *dr;
605 	char abuf[INET6_ADDRSTRLEN];
606 	char llabuf[BUFSIZ];
607 
608 	logmsg(LOG_DEBUG, "Phyint %s index %d state %x, kernel %x, "
609 	    "onlink_def %d num routers %d\n",
610 	    pi->pi_name, pi->pi_index,
611 	    pi->pi_state, pi->pi_kernel_state,
612 	    pi->pi_onlink_default ? 1 : 0,
613 	    pi->pi_num_k_routers);
614 	logmsg(LOG_DEBUG, "\taddress: %s flags %x\n",
615 	    inet_ntop(AF_INET6, (void *)&pi->pi_ifaddr,
616 	    abuf, sizeof (abuf)), pi->pi_flags);
617 	logmsg(LOG_DEBUG, "\tsock %d mtu %d hdw_addr len %d <%s>\n",
618 	    pi->pi_sock, pi->pi_mtu, pi->pi_hdw_addr_len,
619 	    ((pi->pi_hdw_addr_len != 0) ?
620 	    fmt_lla(llabuf, sizeof (llabuf), pi->pi_hdw_addr,
621 	    pi->pi_hdw_addr_len) : "none"));
622 	logmsg(LOG_DEBUG, "\ttoken: len %d %s\n",
623 	    pi->pi_token_length,
624 	    inet_ntop(AF_INET6, (void *)&pi->pi_token,
625 	    abuf, sizeof (abuf)));
626 	if (pi->pi_TmpAddrsEnabled) {
627 		logmsg(LOG_DEBUG, "\ttmp_token: %s\n",
628 		    inet_ntop(AF_INET6, (void *)&pi->pi_tmp_token,
629 			abuf, sizeof (abuf)));
630 		logmsg(LOG_DEBUG, "\ttmp config: pref %d valid %d "
631 		    "maxdesync %d desync %d regen %d\n",
632 		    pi->pi_TmpPreferredLifetime, pi->pi_TmpValidLifetime,
633 		    pi->pi_TmpMaxDesyncFactor, pi->pi_TmpDesyncFactor,
634 		    pi->pi_TmpRegenAdvance);
635 	}
636 	if (pi->pi_flags & IFF_POINTOPOINT) {
637 		logmsg(LOG_DEBUG, "\tdst_token: %s\n",
638 		    inet_ntop(AF_INET6, (void *)&pi->pi_dst_token,
639 			abuf, sizeof (abuf)));
640 	}
641 	logmsg(LOG_DEBUG, "\tLinkMTU %d CurHopLimit %d "
642 	    "BaseReachableTime %d\n\tReachableTime %d RetransTimer %d\n",
643 	    pi->pi_LinkMTU, pi->pi_CurHopLimit, pi->pi_BaseReachableTime,
644 	    pi->pi_ReachableTime, pi->pi_RetransTimer);
645 	if (!pi->pi_AdvSendAdvertisements) {
646 		/* Solicit state */
647 		logmsg(LOG_DEBUG, "\tSOLICIT: time_left %d state %d count %d\n",
648 		    pi->pi_sol_time_left, pi->pi_sol_state, pi->pi_sol_count);
649 	} else {
650 		/* Advertise state */
651 		logmsg(LOG_DEBUG, "\tADVERT: time_left %d state %d count %d "
652 		    "since last %d\n",
653 		    pi->pi_adv_time_left, pi->pi_adv_state, pi->pi_adv_count,
654 		    pi->pi_adv_time_since_sent);
655 		print_iflist(pi->pi_config);
656 	}
657 	for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next)
658 		prefix_print(pr);
659 
660 	for (adv_pr = pi->pi_adv_prefix_list; adv_pr != NULL;
661 	    adv_pr = adv_pr->adv_pr_next) {
662 		adv_prefix_print(adv_pr);
663 	}
664 
665 	for (dr = pi->pi_router_list; dr != NULL; dr = dr->dr_next)
666 		router_print(dr);
667 
668 	logmsg(LOG_DEBUG, "\n");
669 }
670 
671 /*
672  * Randomize pi->pi_ReachableTime.
673  * Done periodically when there are no RAs and at a maximum frequency when
674  * RA's arrive.
675  * Assumes that caller has determined that it is time to generate
676  * a new random ReachableTime.
677  */
678 void
679 phyint_reach_random(struct phyint *pi, boolean_t set_needed)
680 {
681 	pi->pi_ReachableTime = GET_RANDOM(
682 	    (int)(ND_MIN_RANDOM_FACTOR * pi->pi_BaseReachableTime),
683 	    (int)(ND_MAX_RANDOM_FACTOR * pi->pi_BaseReachableTime));
684 	if (set_needed) {
685 		struct lifreq lifr;
686 
687 		(void) strncpy(lifr.lifr_name, pi->pi_name,
688 		    sizeof (lifr.lifr_name));
689 		pi->pi_name[sizeof (pi->pi_name) - 1] = '\0';
690 		if (ioctl(pi->pi_sock, SIOCGLIFLNKINFO, (char *)&lifr) < 0) {
691 			logperror_pi(pi,
692 			    "phyint_reach_random: SIOCGLIFLNKINFO");
693 			return;
694 		}
695 		lifr.lifr_ifinfo.lir_reachtime = pi->pi_ReachableTime;
696 		if (ioctl(pi->pi_sock, SIOCSLIFLNKINFO, (char *)&lifr) < 0) {
697 			logperror_pi(pi,
698 			    "phyint_reach_random: SIOCSLIFLNKINFO");
699 			return;
700 		}
701 	}
702 	pi->pi_reach_time_since_random = 0;
703 }
704 
705 /*
706  * Validate a temporary token against a list of known bad values.
707  * Currently assumes that token is 8 bytes long!  Current known
708  * bad values include 0, reserved anycast tokens (RFC 2526), tokens
709  * used by ISATAP (draft-ietf-ngtrans-isatap-N), any token already
710  * assigned to this interface, or any token for which the global
711  * bit is set.
712  *
713  * Called by tmptoken_create().
714  *
715  * Return _B_TRUE if token is valid (no match), _B_FALSE if not.
716  */
717 static boolean_t
718 tmptoken_isvalid(struct in6_addr *token)
719 {
720 	struct phyint *pi;
721 	struct in6_addr mask;
722 	struct in6_addr isatap = { 0, 0, 0, 0, 0, 0, 0, 0, \
723 				    0, 0, 0x5e, 0xfe, 0, 0, 0, 0 };
724 	struct in6_addr anycast = { 0, 0, 0, 0, \
725 				    0, 0, 0, 0, \
726 				    0xfd, 0xff, 0xff, 0xff, \
727 				    0xff, 0xff, 0xff, 0x80 };
728 
729 	if (IN6_IS_ADDR_UNSPECIFIED(token))
730 		return (_B_FALSE);
731 
732 	if (token->s6_addr[8] & 0x2)
733 		return (_B_FALSE);
734 
735 	(void) memcpy(&mask, token, sizeof (mask));
736 	mask._S6_un._S6_u32[3] = 0;
737 	if (IN6_ARE_ADDR_EQUAL(&isatap, token))
738 		return (_B_FALSE);
739 
740 	mask._S6_un._S6_u32[3] = token->_S6_un._S6_u32[3] & 0xffffff80;
741 	if (IN6_ARE_ADDR_EQUAL(&anycast, token))
742 		return (_B_FALSE);
743 
744 	for (pi = phyints; pi != NULL; pi = pi->pi_next) {
745 		if (((pi->pi_token_length == TMP_TOKEN_BITS) &&
746 		    IN6_ARE_ADDR_EQUAL(&pi->pi_token, token)) ||
747 		    IN6_ARE_ADDR_EQUAL(&pi->pi_tmp_token, token))
748 			return (_B_FALSE);
749 	}
750 
751 	/* none of our tests failed, must be a good one! */
752 	return (_B_TRUE);
753 }
754 
755 /*
756  * Generate a temporary token and set up its timer
757  *
758  * Called from incoming_prefix_addrconf_process() (when token is first
759  * needed) and from tmptoken_timer() (when current token expires).
760  *
761  * Returns _B_TRUE if a token was successfully generated, _B_FALSE if not.
762  */
763 boolean_t
764 tmptoken_create(struct phyint *pi)
765 {
766 	int fd, i = 0, max_tries = 15;
767 	struct in6_addr token;
768 	uint32_t *tokenp = &(token._S6_un._S6_u32[2]);
769 	char buf[INET6_ADDRSTRLEN];
770 
771 	if ((fd = open("/dev/urandom", O_RDONLY)) == -1) {
772 		perror("open /dev/urandom");
773 		goto no_token;
774 	}
775 
776 	bzero((char *)&token, sizeof (token));
777 	do {
778 		if (read(fd, (void *)tokenp, TMP_TOKEN_BYTES) == -1) {
779 			perror("read /dev/urandom");
780 			(void) close(fd);
781 			goto no_token;
782 		}
783 
784 		/*
785 		 * Assume EUI-64 formatting, and thus 64-bit
786 		 * token len; need to clear global bit.
787 		 */
788 		token.s6_addr[8] &= 0xfd;
789 
790 		i++;
791 
792 	} while (!tmptoken_isvalid(&token) && i < max_tries);
793 
794 	(void) close(fd);
795 
796 	if (i == max_tries) {
797 no_token:
798 		logmsg(LOG_WARNING, "tmptoken_create(%s): failed to create "
799 		    "token; disabling temporary addresses on %s\n",
800 		    pi->pi_name, pi->pi_name);
801 		pi->pi_TmpAddrsEnabled = 0;
802 		return (_B_FALSE);
803 	}
804 
805 	pi->pi_tmp_token = token;
806 
807 	if (debug & D_TMP)
808 		logmsg(LOG_DEBUG, "tmptoken_create(%s): created temporary "
809 		    "token %s\n", pi->pi_name,
810 		    inet_ntop(AF_INET6, &pi->pi_tmp_token, buf, sizeof (buf)));
811 
812 	pi->pi_TmpRegenCountdown = (pi->pi_TmpPreferredLifetime -
813 	    pi->pi_TmpDesyncFactor - pi->pi_TmpRegenAdvance) * MILLISEC;
814 	if (pi->pi_TmpRegenCountdown != 0)
815 		timer_schedule(pi->pi_TmpRegenCountdown);
816 
817 	return (_B_TRUE);
818 }
819 
820 /*
821  * Delete a temporary token.  This is outside the normal timeout process,
822  * so mark any existing addresses based on this token DEPRECATED and set
823  * their preferred lifetime to 0.  Don't tamper with valid lifetime, that
824  * will be used to eventually remove the address.  Also reset the current
825  * pi_tmp_token value to 0.
826  *
827  * Called from incoming_prefix_addrconf_process() if DAD fails on a temp
828  * addr.
829  */
830 void
831 tmptoken_delete(struct phyint *pi)
832 {
833 	struct prefix *pr;
834 
835 	for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) {
836 		if (!(pr->pr_flags & IFF_TEMPORARY) ||
837 		    (pr->pr_flags & IFF_DEPRECATED) ||
838 		    (!token_equal(pr->pr_address, pi->pi_tmp_token,
839 		    TMP_TOKEN_BITS))) {
840 			continue;
841 		}
842 		pr->pr_PreferredLifetime = 0;
843 		pr->pr_state |= PR_DEPRECATED;
844 		prefix_update_k(pr);
845 	}
846 
847 	(void) memset(&pi->pi_tmp_token, 0, sizeof (pi->pi_tmp_token));
848 }
849 
850 /*
851  * Called from run_timeouts() with the number of milliseconds elapsed
852  * since the last call.  Determines if any timeout event has occurred
853  * and returns the number of milliseconds until the next timeout event
854  * for the tmp token.  Returns TIMER_INFINITY for "never".
855  */
856 uint_t
857 tmptoken_timer(struct phyint *pi, uint_t elapsed)
858 {
859 	struct nd_opt_prefix_info opt;
860 	struct sockaddr_in6 sin6;
861 	struct prefix *pr, *newpr;
862 
863 	if (debug & D_TMP) {
864 		logmsg(LOG_DEBUG, "tmptoken_timer(%s, %d) regencountdown %d\n",
865 		    pi->pi_name, (int)elapsed, pi->pi_TmpRegenCountdown);
866 	}
867 	if (!pi->pi_TmpAddrsEnabled ||
868 	    (pi->pi_TmpRegenCountdown == TIMER_INFINITY))
869 		return (TIMER_INFINITY);
870 
871 	if (pi->pi_TmpRegenCountdown > elapsed) {
872 		pi->pi_TmpRegenCountdown -= elapsed;
873 		return (pi->pi_TmpRegenCountdown);
874 	}
875 
876 	/*
877 	 * Tmp token timer has expired.  Start by generating a new token.
878 	 * If we can't get a new token, tmp addrs are disabled on this
879 	 * interface, so there's no need to continue, or to set a timer.
880 	 */
881 	if (!tmptoken_create(pi))
882 		return (TIMER_INFINITY);
883 
884 	/*
885 	 * Now that we have a new token, walk the list of prefixes to
886 	 * find which ones need a corresponding tmp addr generated.
887 	 */
888 	for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) {
889 
890 		if (!(pr->pr_state & PR_AUTO) || pr->pr_state & PR_STATIC ||
891 		    pr->pr_state & PR_DEPRECATED ||
892 		    pr->pr_flags & IFF_TEMPORARY)
893 			continue;
894 
895 		newpr = prefix_create(pi, pr->pr_prefix, pr->pr_prefix_len,
896 		    IFF_TEMPORARY);
897 		if (newpr == NULL) {
898 			char pbuf[INET6_ADDRSTRLEN];
899 			char tbuf[INET6_ADDRSTRLEN];
900 			(void) inet_ntop(AF_INET6, &pr->pr_prefix, pbuf,
901 			    sizeof (pbuf));
902 			(void) inet_ntop(AF_INET6, &pi->pi_tmp_token, tbuf,
903 			    sizeof (tbuf));
904 			logmsg(LOG_ERR, "can't create new tmp addr "
905 			    "(%s, %s, %s)\n", pi->pi_name, pbuf, tbuf);
906 			continue;
907 		}
908 
909 		/*
910 		 * We want to use incoming_prefix_*_process() functions to
911 		 * set up the new tmp addr, so cobble together a prefix
912 		 * info option struct based on the existing prefix to pass
913 		 * in.  The lifetimes will be based on the current time
914 		 * remaining.
915 		 *
916 		 * The "from" param is only used for messages; pass in
917 		 * ::0 for that.
918 		 */
919 		opt.nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
920 		opt.nd_opt_pi_len = sizeof (opt) / 8;
921 		opt.nd_opt_pi_prefix_len = pr->pr_prefix_len;
922 		opt.nd_opt_pi_flags_reserved = ND_OPT_PI_FLAG_AUTO;
923 		opt.nd_opt_pi_valid_time =
924 		    htonl(pr->pr_ValidLifetime / 1000);
925 		opt.nd_opt_pi_preferred_time =
926 		    htonl(pr->pr_PreferredLifetime / 1000);
927 		if (pr->pr_state & PR_ONLINK)
928 			opt.nd_opt_pi_flags_reserved &= ND_OPT_PI_FLAG_ONLINK;
929 		opt.nd_opt_pi_prefix = pr->pr_prefix;
930 
931 		(void) memset(&sin6, 0, sizeof (sin6));
932 
933 		if (!incoming_prefix_addrconf_process(pi, newpr,
934 		    (uchar_t *)&opt, &sin6, _B_FALSE, _B_TRUE)) {
935 			char pbuf[INET6_ADDRSTRLEN];
936 			char tbuf[INET6_ADDRSTRLEN];
937 			(void) inet_ntop(AF_INET6, &pr->pr_prefix, pbuf,
938 			    sizeof (pbuf));
939 			(void) inet_ntop(AF_INET6, &pi->pi_tmp_token, tbuf,
940 			    sizeof (tbuf));
941 			logmsg(LOG_ERR, "can't create new tmp addr "
942 			    "(%s, %s, %s)\n", pi->pi_name, pbuf, tbuf);
943 			continue;
944 		}
945 
946 		if (pr->pr_state & PR_ONLINK) {
947 			incoming_prefix_onlink_process(newpr, (uchar_t *)&opt);
948 		}
949 	}
950 
951 	/*
952 	 * appropriate timers were scheduled when
953 	 * the token and addresses were created.
954 	 */
955 	return (TIMER_INFINITY);
956 }
957 
958 /*
959  * tlen specifies the token length in bits.  Compares the lower
960  * tlen bits of the two addresses provided and returns _B_TRUE if
961  * they match, _B_FALSE if not.  Also returns _B_FALSE for invalid
962  * values of tlen.
963  */
964 boolean_t
965 token_equal(struct in6_addr t1, struct in6_addr t2, int tlen)
966 {
967 	uchar_t mask;
968 	int j, abytes, tbytes, tbits;
969 
970 	if (tlen < 0 || tlen > IPV6_ABITS)
971 		return (_B_FALSE);
972 
973 	abytes = IPV6_ABITS >> 3;
974 	tbytes = tlen >> 3;
975 	tbits = tlen & 7;
976 
977 	for (j = abytes - 1; j >= abytes - tbytes; j--)
978 		if (t1.s6_addr[j] != t2.s6_addr[j])
979 			return (_B_FALSE);
980 
981 	if (tbits == 0)
982 		return (_B_TRUE);
983 
984 	/* We only care about the tbits rightmost bits */
985 	mask = 0xff >> (8 - tbits);
986 	if ((t1.s6_addr[j] & mask) != (t2.s6_addr[j] & mask))
987 		return (_B_FALSE);
988 
989 	return (_B_TRUE);
990 }
991 
992 /*
993  * Lookup prefix structure that matches the prefix and prefix length.
994  * Assumes that the bits after prefixlen might not be zero.
995  */
996 static struct prefix *
997 prefix_lookup(struct phyint *pi, struct in6_addr prefix, int prefixlen)
998 {
999 	struct prefix *pr;
1000 	char abuf[INET6_ADDRSTRLEN];
1001 
1002 	if (debug & D_PREFIX) {
1003 		logmsg(LOG_DEBUG, "prefix_lookup(%s, %s/%u)\n", pi->pi_name,
1004 		    inet_ntop(AF_INET6, (void *)&prefix,
1005 		    abuf, sizeof (abuf)), prefixlen);
1006 	}
1007 
1008 	for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) {
1009 		if (pr->pr_prefix_len == prefixlen &&
1010 		    prefix_equal(prefix, pr->pr_prefix, prefixlen))
1011 			return (pr);
1012 	}
1013 	return (NULL);
1014 }
1015 
1016 /*
1017  * Compare two prefixes that have the same prefix length.
1018  * Fails if the prefix length is unreasonable.
1019  */
1020 boolean_t
1021 prefix_equal(struct in6_addr p1, struct in6_addr p2, int plen)
1022 {
1023 	uchar_t mask;
1024 	int j, pbytes, pbits;
1025 
1026 	if (plen < 0 || plen > IPV6_ABITS)
1027 		return (_B_FALSE);
1028 
1029 	pbytes = plen >> 3;
1030 	pbits = plen & 7;
1031 
1032 	for (j = 0; j < pbytes; j++)
1033 		if (p1.s6_addr[j] != p2.s6_addr[j])
1034 			return (_B_FALSE);
1035 
1036 	if (pbits == 0)
1037 		return (_B_TRUE);
1038 
1039 	/* Make the N leftmost bits one */
1040 	mask = 0xff << (8 - pbits);
1041 	if ((p1.s6_addr[j] & mask) != (p2.s6_addr[j] & mask))
1042 		return (_B_FALSE);
1043 
1044 	return (_B_TRUE);
1045 }
1046 
1047 /*
1048  * Set a prefix from an address and a prefix length.
1049  * Force all the bits after the prefix length to be zero.
1050  */
1051 void
1052 prefix_set(struct in6_addr *prefix, struct in6_addr addr, int prefix_len)
1053 {
1054 	uchar_t mask;
1055 	int j;
1056 
1057 	if (prefix_len < 0 || prefix_len > IPV6_ABITS)
1058 		return;
1059 
1060 	bzero((char *)prefix, sizeof (*prefix));
1061 
1062 	for (j = 0; prefix_len > 8; prefix_len -= 8, j++)
1063 		prefix->s6_addr[j] = addr.s6_addr[j];
1064 
1065 	/* Make the N leftmost bits one */
1066 	mask = 0xff << (8 - prefix_len);
1067 	prefix->s6_addr[j] = addr.s6_addr[j] & mask;
1068 }
1069 
1070 /*
1071  * Lookup a prefix based on the kernel's interface name.
1072  */
1073 struct prefix *
1074 prefix_lookup_name(struct phyint *pi, char *name)
1075 {
1076 	struct prefix *pr;
1077 
1078 	if (debug & D_PREFIX) {
1079 		logmsg(LOG_DEBUG, "prefix_lookup_name(%s, %s)\n",
1080 		    pi->pi_name, name);
1081 	}
1082 	if (name[0] == '\0')
1083 		return (NULL);
1084 
1085 	for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) {
1086 		if (strcmp(name, pr->pr_name) == 0)
1087 			return (pr);
1088 	}
1089 	return (NULL);
1090 }
1091 
1092 /*
1093  * Search the phyints list to make sure that this new prefix does
1094  * not already exist in any  other physical interfaces that have
1095  * the same address as this one
1096  */
1097 struct prefix *
1098 prefix_lookup_addr_match(struct prefix *pr)
1099 {
1100 	char abuf[INET6_ADDRSTRLEN];
1101 	struct phyint *pi;
1102 	struct prefix *otherpr = NULL;
1103 	struct in6_addr prefix;
1104 	int	prefixlen;
1105 
1106 	if (debug & D_PREFIX) {
1107 		logmsg(LOG_DEBUG, "prefix_lookup_addr_match(%s/%u)\n",
1108 		    inet_ntop(AF_INET6, (void *)&pr->pr_address,
1109 		    abuf, sizeof (abuf)), pr->pr_prefix_len);
1110 	}
1111 	prefix = pr->pr_prefix;
1112 	prefixlen = pr->pr_prefix_len;
1113 	for (pi = phyints; pi != NULL; pi = pi->pi_next) {
1114 		otherpr = prefix_lookup(pi, prefix, prefixlen);
1115 		if (otherpr == pr)
1116 			continue;
1117 		if (otherpr != NULL && (otherpr->pr_state & PR_AUTO) &&
1118 		    IN6_ARE_ADDR_EQUAL(&pr->pr_address,
1119 		    &otherpr->pr_address))
1120 			return (otherpr);
1121 	}
1122 	return (NULL);
1123 }
1124 
1125 /*
1126  * Initialize a new prefix without setting lifetimes etc.
1127  */
1128 struct prefix *
1129 prefix_create(struct phyint *pi, struct in6_addr prefix, int prefixlen,
1130     uint64_t flags)
1131 {
1132 	struct prefix *pr;
1133 	char abuf[INET6_ADDRSTRLEN];
1134 
1135 	if (debug & D_PREFIX) {
1136 		logmsg(LOG_DEBUG, "prefix_create(%s, %s/%u, 0x%llx)\n",
1137 		    pi->pi_name, inet_ntop(AF_INET6, (void *)&prefix,
1138 		    abuf, sizeof (abuf)), prefixlen, flags);
1139 	}
1140 	pr = (struct prefix *)calloc(sizeof (struct prefix), 1);
1141 	if (pr == NULL) {
1142 		logmsg(LOG_ERR, "prefix_create: out of memory\n");
1143 		return (NULL);
1144 	}
1145 	/*
1146 	 * The prefix might have non-zero bits after the prefix len bits.
1147 	 * Force them to be zero.
1148 	 */
1149 	prefix_set(&pr->pr_prefix, prefix, prefixlen);
1150 	pr->pr_prefix_len = prefixlen;
1151 	pr->pr_PreferredLifetime = PREFIX_INFINITY;
1152 	pr->pr_ValidLifetime = PREFIX_INFINITY;
1153 	pr->pr_OnLinkLifetime = PREFIX_INFINITY;
1154 	pr->pr_kernel_state = 0;
1155 	pr->pr_flags |= flags;
1156 	prefix_insert(pi, pr);
1157 	return (pr);
1158 }
1159 
1160 /*
1161  * Create a new named prefix. Caller should use prefix_init_from_k
1162  * to initialize the content.
1163  */
1164 struct prefix *
1165 prefix_create_name(struct phyint *pi, char *name)
1166 {
1167 	struct prefix *pr;
1168 
1169 	if (debug & D_PREFIX) {
1170 		logmsg(LOG_DEBUG, "prefix_create_name(%s, %s)\n",
1171 		    pi->pi_name, name);
1172 	}
1173 	pr = (struct prefix *)calloc(sizeof (struct prefix), 1);
1174 	if (pr == NULL) {
1175 		logmsg(LOG_ERR, "prefix_create_name: out of memory\n");
1176 		return (NULL);
1177 	}
1178 	(void) strncpy(pr->pr_name, name, sizeof (pr->pr_name));
1179 	pr->pr_name[sizeof (pr->pr_name) - 1] = '\0';
1180 	prefix_insert(pi, pr);
1181 	return (pr);
1182 }
1183 
1184 /* Insert in linked list */
1185 static void
1186 prefix_insert(struct phyint *pi, struct prefix *pr)
1187 {
1188 	pr->pr_next = pi->pi_prefix_list;
1189 	pr->pr_prev = NULL;
1190 	if (pi->pi_prefix_list != NULL)
1191 		pi->pi_prefix_list->pr_prev = pr;
1192 	pi->pi_prefix_list = pr;
1193 	pr->pr_physical = pi;
1194 }
1195 
1196 /*
1197  * Initialize the prefix from the content of the kernel.
1198  * If IFF_ADDRCONF is set we treat it as PR_AUTO (i.e. an addrconf
1199  * prefix). However, we not derive the lifetimes from
1200  * the kernel thus they are set to 1 week.
1201  * Ignore the prefix if the interface is not IFF_UP.
1202  */
1203 int
1204 prefix_init_from_k(struct prefix *pr)
1205 {
1206 	struct lifreq lifr;
1207 	struct sockaddr_in6 *sin6;
1208 	int sock = pr->pr_physical->pi_sock;
1209 
1210 	(void) strncpy(lifr.lifr_name, pr->pr_name, sizeof (lifr.lifr_name));
1211 	lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
1212 	if (ioctl(sock, SIOCGLIFADDR, (char *)&lifr) < 0) {
1213 		logperror_pr(pr, "prefix_init_from_k: ioctl (get addr)");
1214 		goto error;
1215 	}
1216 	if (lifr.lifr_addr.ss_family != AF_INET6) {
1217 		logmsg(LOG_ERR, "ignoring interface %s: not AF_INET6\n",
1218 		    pr->pr_name);
1219 		goto error;
1220 	}
1221 	sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
1222 	pr->pr_address = sin6->sin6_addr;
1223 
1224 	if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
1225 		logperror_pr(pr, "prefix_init_from_k: ioctl (get flags)");
1226 		goto error;
1227 	}
1228 	pr->pr_flags = lifr.lifr_flags;
1229 
1230 	if (ioctl(sock, SIOCGLIFSUBNET, (char *)&lifr) < 0) {
1231 		logperror_pr(pr, "prefix_init_from_k: ioctl (get subnet)");
1232 		goto error;
1233 	}
1234 	if (lifr.lifr_subnet.ss_family != AF_INET6) {
1235 		logmsg(LOG_ERR, "ignoring interface %s: not AF_INET6\n",
1236 		    pr->pr_name);
1237 		goto error;
1238 	}
1239 	/*
1240 	 * Guard against the prefix having non-zero bits after the prefix
1241 	 * len bits.
1242 	 */
1243 	sin6 = (struct sockaddr_in6 *)&lifr.lifr_subnet;
1244 	pr->pr_prefix_len = lifr.lifr_addrlen;
1245 	prefix_set(&pr->pr_prefix, sin6->sin6_addr, pr->pr_prefix_len);
1246 
1247 	if (pr->pr_prefix_len != IPV6_ABITS && (pr->pr_flags & IFF_UP) &&
1248 	    IN6_ARE_ADDR_EQUAL(&pr->pr_address, &pr->pr_prefix)) {
1249 		char abuf[INET6_ADDRSTRLEN];
1250 
1251 		logmsg(LOG_ERR, "ingoring interface %s: it appears to be "
1252 		    "configured with an invalid interface id (%s/%u)\n",
1253 		    pr->pr_name,
1254 		    inet_ntop(AF_INET6, (void *)&pr->pr_address,
1255 			abuf, sizeof (abuf)), pr->pr_prefix_len);
1256 		goto error;
1257 	}
1258 	pr->pr_kernel_state = 0;
1259 	if (pr->pr_prefix_len != IPV6_ABITS)
1260 		pr->pr_kernel_state |= PR_ONLINK;
1261 	if (!(pr->pr_flags & IFF_NOLOCAL))
1262 		pr->pr_kernel_state |= PR_AUTO;
1263 	if ((pr->pr_flags & IFF_DEPRECATED) && (pr->pr_kernel_state & PR_AUTO))
1264 		pr->pr_kernel_state |= PR_DEPRECATED;
1265 	if (!(pr->pr_flags & IFF_ADDRCONF)) {
1266 		/* Prevent ndpd from stepping on this prefix */
1267 		pr->pr_kernel_state |= PR_STATIC;
1268 	}
1269 	pr->pr_state = pr->pr_kernel_state;
1270 	/* Adjust pr_prefix_len based if PR_AUTO is set */
1271 	if (pr->pr_state & PR_AUTO) {
1272 		pr->pr_prefix_len =
1273 		    IPV6_ABITS - pr->pr_physical->pi_token_length;
1274 		prefix_set(&pr->pr_prefix, pr->pr_prefix, pr->pr_prefix_len);
1275 	}
1276 
1277 	/* Can't extract lifetimes from the kernel - use 1 week */
1278 	pr->pr_ValidLifetime = NDP_PREFIX_DEFAULT_LIFETIME;
1279 	pr->pr_PreferredLifetime = NDP_PREFIX_DEFAULT_LIFETIME;
1280 	pr->pr_OnLinkLifetime = NDP_PREFIX_DEFAULT_LIFETIME;
1281 
1282 	/*
1283 	 * If this is a temp addr, the creation time needs to be set.
1284 	 * Though it won't be entirely accurate, the current time is
1285 	 * an okay approximation.
1286 	 */
1287 	if (pr->pr_flags & IFF_TEMPORARY)
1288 		pr->pr_CreateTime = getcurrenttime() / MILLISEC;
1289 
1290 	if (pr->pr_kernel_state == 0)
1291 		pr->pr_name[0] = '\0';
1292 	return (0);
1293 
1294 error:
1295 	/* Pretend that the prefix does not exist in the kernel */
1296 	pr->pr_kernel_state = 0;
1297 	pr->pr_name[0] = '\0';
1298 	return (-1);
1299 }
1300 
1301 /*
1302  * Delete (unlink and free) and remove from kernel if the prefix
1303  * was added by in.ndpd (i.e. PR_STATIC is not set).
1304  * Handles delete of things that have not yet been inserted in the list
1305  * i.e. pr_physical is NULL.
1306  */
1307 void
1308 prefix_delete(struct prefix *pr)
1309 {
1310 	struct phyint *pi;
1311 	char abuf[INET6_ADDRSTRLEN];
1312 
1313 	if (debug & D_PREFIX) {
1314 		logmsg(LOG_DEBUG, "prefix_delete(%s, %s, %s/%u)\n",
1315 		    pr->pr_physical->pi_name, pr->pr_name,
1316 		    inet_ntop(AF_INET6, (void *)&pr->pr_prefix,
1317 		    abuf, sizeof (abuf)), pr->pr_prefix_len);
1318 	}
1319 	/* Remove non-static prefixes from the kernel. */
1320 	pr->pr_state &= PR_STATIC;
1321 	pi = pr->pr_physical;
1322 	if (pr->pr_kernel_state != pr->pr_state)
1323 		prefix_update_k(pr);
1324 
1325 	if (pr->pr_prev == NULL) {
1326 		if (pi != NULL)
1327 			pi->pi_prefix_list = pr->pr_next;
1328 	} else {
1329 		pr->pr_prev->pr_next = pr->pr_next;
1330 	}
1331 	if (pr->pr_next != NULL)
1332 		pr->pr_next->pr_prev = pr->pr_prev;
1333 	pr->pr_next = pr->pr_prev = NULL;
1334 	free(pr);
1335 }
1336 
1337 /*
1338  * Toggle one or more IFF_ flags for a prefix. Turn on 'onflags' and
1339  * turn off 'offflags'.
1340  */
1341 static int
1342 prefix_modify_flags(struct prefix *pr, uint64_t onflags, uint64_t offflags)
1343 {
1344 	struct lifreq lifr;
1345 	struct phyint *pi = pr->pr_physical;
1346 	uint64_t old_flags;
1347 	char abuf[INET6_ADDRSTRLEN];
1348 
1349 	if (debug & D_PREFIX) {
1350 		logmsg(LOG_DEBUG, "prefix_modify_flags(%s, %s, %s/%u) "
1351 		    "flags %llx on %llx off %llx\n",
1352 		    pr->pr_physical->pi_name,
1353 		    pr->pr_name,
1354 		    inet_ntop(AF_INET6, (void *)&pr->pr_prefix,
1355 		    abuf, sizeof (abuf)), pr->pr_prefix_len,
1356 		    pr->pr_flags, onflags, offflags);
1357 	}
1358 	/* Assumes that only the PR_STATIC link-local matches the pi_name */
1359 	if (!(pr->pr_state & PR_STATIC) &&
1360 	    strcmp(pr->pr_name, pi->pi_name) == 0) {
1361 		logmsg(LOG_ERR, "prefix_modify_flags(%s, on %llx, off %llx): "
1362 		    "name matches interface name\n",
1363 		    pi->pi_name, onflags, offflags);
1364 		return (-1);
1365 	}
1366 
1367 	(void) strncpy(lifr.lifr_name, pr->pr_name, sizeof (lifr.lifr_name));
1368 	lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
1369 	if (ioctl(pi->pi_sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
1370 		logperror_pr(pr, "prefix_modify_flags: SIOCGLIFFLAGS");
1371 		logmsg(LOG_ERR, "prefix_modify_flags(%s, %s) old 0x%llx "
1372 		    "on 0x%llx off 0x%llx\n",
1373 		    pr->pr_physical->pi_name,
1374 		    pr->pr_name,
1375 		    pr->pr_flags, onflags, offflags);
1376 		return (-1);
1377 	}
1378 	old_flags = lifr.lifr_flags;
1379 	lifr.lifr_flags |= onflags;
1380 	lifr.lifr_flags &= ~offflags;
1381 	pr->pr_flags = lifr.lifr_flags;
1382 	if (ioctl(pi->pi_sock, SIOCSLIFFLAGS, (char *)&lifr) < 0) {
1383 		logperror_pr(pr, "prefix_modify_flags: SIOCSLIFFLAGS");
1384 		logmsg(LOG_ERR, "prefix_modify_flags(%s, %s) old 0x%llx "
1385 		    "new 0x%llx on 0x%llx off 0x%llx\n",
1386 		    pr->pr_physical->pi_name,
1387 		    pr->pr_name,
1388 		    old_flags, lifr.lifr_flags, onflags, offflags);
1389 		return (-1);
1390 	}
1391 	return (0);
1392 }
1393 
1394 /*
1395  * Make the kernel state match what is in the prefix structure.
1396  * This includes creating the prefix (allocating a new interface name)
1397  * as well as setting the local address and on-link subnet prefix
1398  * and controlling the IFF_ADDRCONF and IFF_DEPRECATED flags.
1399  */
1400 void
1401 prefix_update_k(struct prefix *pr)
1402 {
1403 	struct lifreq lifr;
1404 	char abuf[INET6_ADDRSTRLEN];
1405 	char buf1[PREFIX_STATESTRLEN], buf2[PREFIX_STATESTRLEN];
1406 	struct phyint *pi = pr->pr_physical;
1407 	struct sockaddr_in6 *sin6;
1408 
1409 	if (debug & D_PREFIX) {
1410 		logmsg(LOG_DEBUG, "prefix_update_k(%s, %s, %s/%u) "
1411 		    "from %s to %s\n", pr->pr_physical->pi_name, pr->pr_name,
1412 		    inet_ntop(AF_INET6, (void *)&pr->pr_prefix,
1413 		    abuf, sizeof (abuf)), pr->pr_prefix_len,
1414 		    prefix_print_state(pr->pr_kernel_state, buf1,
1415 		    sizeof (buf1)),
1416 		    prefix_print_state(pr->pr_state, buf2, sizeof (buf2)));
1417 	}
1418 
1419 	if (pr->pr_kernel_state == pr->pr_state)
1420 		return;		/* No changes */
1421 
1422 	/* Skip static prefixes */
1423 	if (pr->pr_state & PR_STATIC)
1424 		return;
1425 
1426 	if (pr->pr_kernel_state == 0) {
1427 		uint64_t onflags;
1428 		/*
1429 		 * Create a new logical interface name and store in pr_name.
1430 		 * Set IFF_ADDRCONF. Do not set an address (yet).
1431 		 */
1432 		if (pr->pr_name[0] != '\0') {
1433 			/* Name already set! */
1434 			logmsg(LOG_ERR, "prefix_update_k(%s, %s, %s/%u) "
1435 			    "from %s to %s name is already allocated\n",
1436 			    pr->pr_physical->pi_name, pr->pr_name,
1437 			    inet_ntop(AF_INET6, (void *)&pr->pr_prefix,
1438 			    abuf, sizeof (abuf)), pr->pr_prefix_len,
1439 			    prefix_print_state(pr->pr_kernel_state, buf1,
1440 			    sizeof (buf1)),
1441 			    prefix_print_state(pr->pr_state, buf2,
1442 			    sizeof (buf2)));
1443 			return;
1444 		}
1445 
1446 		(void) strncpy(lifr.lifr_name, pi->pi_name,
1447 		    sizeof (lifr.lifr_name));
1448 		lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
1449 		lifr.lifr_addr.ss_family = AF_UNSPEC;
1450 		if (ioctl(pi->pi_sock, SIOCLIFADDIF, (char *)&lifr) < 0) {
1451 			logperror_pr(pr, "prefix_update_k: SIOCLIFADDIF");
1452 			return;
1453 		}
1454 		(void) strncpy(pr->pr_name, lifr.lifr_name,
1455 		    sizeof (pr->pr_name));
1456 		pr->pr_name[sizeof (pr->pr_name) - 1] = '\0';
1457 		if (debug & D_PREFIX) {
1458 			logmsg(LOG_DEBUG, "prefix_update_k: new name %s\n",
1459 			    pr->pr_name);
1460 		}
1461 		/*
1462 		 * The IFF_TEMPORARY flag might have already been set; if
1463 		 * so, it needs to be or'd into the flags we're turning on.
1464 		 * But be careful, we might be re-creating a manually
1465 		 * removed interface, in which case we don't want to try
1466 		 * to set *all* the flags we might have in our copy of the
1467 		 * flags yet.
1468 		 */
1469 		onflags = IFF_ADDRCONF;
1470 		if (pr->pr_flags & IFF_TEMPORARY)
1471 			onflags |= IFF_TEMPORARY;
1472 		if (prefix_modify_flags(pr, onflags, 0) == -1)
1473 			return;
1474 	}
1475 	if ((pr->pr_state & (PR_ONLINK|PR_AUTO)) == 0) {
1476 		/* Remove the interface */
1477 		if (prefix_modify_flags(pr, 0, IFF_UP|IFF_DEPRECATED) == -1)
1478 			return;
1479 		(void) strncpy(lifr.lifr_name, pr->pr_name,
1480 		    sizeof (lifr.lifr_name));
1481 		lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
1482 
1483 		if (debug & D_PREFIX) {
1484 			logmsg(LOG_DEBUG, "prefix_update_k: remove name %s\n",
1485 			    pr->pr_name);
1486 		}
1487 
1488 		/*
1489 		 * Assumes that only the PR_STATIC link-local matches
1490 		 * the pi_name
1491 		 */
1492 		if (!(pr->pr_state & PR_STATIC) &&
1493 		    strcmp(pr->pr_name, pi->pi_name) == 0) {
1494 			logmsg(LOG_ERR, "prefix_update_k(%s): "
1495 			    "name matches if\n", pi->pi_name);
1496 			return;
1497 		}
1498 
1499 		/* Remove logical interface based on pr_name */
1500 		lifr.lifr_addr.ss_family = AF_UNSPEC;
1501 		if (ioctl(pi->pi_sock, SIOCLIFREMOVEIF, (char *)&lifr) < 0) {
1502 			logperror_pr(pr, "prefix_update_k: SIOCLIFREMOVEIF");
1503 		}
1504 		pr->pr_kernel_state = 0;
1505 		pr->pr_name[0] = '\0';
1506 		return;
1507 	}
1508 	if ((pr->pr_state & PR_AUTO) && !(pr->pr_kernel_state & PR_AUTO)) {
1509 		/*
1510 		 * Set local address and set the prefix length to 128.
1511 		 * Turn off IFF_NOLOCAL in case it was set.
1512 		 * Turn on IFF_UP.
1513 		 */
1514 		(void) strncpy(lifr.lifr_name, pr->pr_name,
1515 		    sizeof (lifr.lifr_name));
1516 		lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
1517 		sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
1518 		bzero(sin6, sizeof (struct sockaddr_in6));
1519 		sin6->sin6_family = AF_INET6;
1520 		sin6->sin6_addr = pr->pr_address;
1521 		if (debug & D_PREFIX) {
1522 			logmsg(LOG_DEBUG, "prefix_update_k(%s) set addr %s "
1523 			    "for PR_AUTO on\n",
1524 			    pr->pr_name,
1525 			    inet_ntop(AF_INET6, (void *)&pr->pr_address,
1526 				abuf, sizeof (abuf)));
1527 		}
1528 		if (ioctl(pi->pi_sock, SIOCSLIFADDR, (char *)&lifr) < 0) {
1529 			logperror_pr(pr, "prefix_update_k: SIOCSLIFADDR");
1530 			return;
1531 		}
1532 		if (pr->pr_state & PR_ONLINK) {
1533 			sin6->sin6_addr = pr->pr_prefix;
1534 			lifr.lifr_addrlen = pr->pr_prefix_len;
1535 		} else {
1536 			sin6->sin6_addr = pr->pr_address;
1537 			lifr.lifr_addrlen = IPV6_ABITS;
1538 		}
1539 		if (debug & D_PREFIX) {
1540 			logmsg(LOG_DEBUG, "prefix_update_k(%s) set subnet "
1541 			    "%s/%u for PR_AUTO on\n", pr->pr_name,
1542 			    inet_ntop(AF_INET6, (void *)&sin6->sin6_addr,
1543 				abuf, sizeof (abuf)), lifr.lifr_addrlen);
1544 		}
1545 		if (ioctl(pi->pi_sock, SIOCSLIFSUBNET, (char *)&lifr) < 0) {
1546 			logperror_pr(pr, "prefix_update_k: SIOCSLIFSUBNET");
1547 			return;
1548 		}
1549 		/*
1550 		 * For ptp interfaces, create a destination based on
1551 		 * prefix and prefix len together with the remote token
1552 		 * extracted from the remote pt-pt address.  This is used by
1553 		 * ip to choose a proper source for outgoing packets.
1554 		 */
1555 		if (pi->pi_flags & IFF_POINTOPOINT) {
1556 			int i;
1557 
1558 			sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
1559 			bzero(sin6, sizeof (struct sockaddr_in6));
1560 			sin6->sin6_family = AF_INET6;
1561 			sin6->sin6_addr = pr->pr_prefix;
1562 			for (i = 0; i < 16; i++) {
1563 				sin6->sin6_addr.s6_addr[i] |=
1564 				    pi->pi_dst_token.s6_addr[i];
1565 			}
1566 			if (debug & D_PREFIX) {
1567 				logmsg(LOG_DEBUG, "prefix_update_k(%s) "
1568 				    "set dstaddr %s for PR_AUTO on\n",
1569 				    pr->pr_name, inet_ntop(AF_INET6,
1570 				    (void *)&sin6->sin6_addr,
1571 				    abuf, sizeof (abuf)));
1572 			}
1573 			if (ioctl(pi->pi_sock, SIOCSLIFDSTADDR,
1574 			    (char *)&lifr) < 0) {
1575 				logperror_pr(pr,
1576 				    "prefix_update_k: SIOCSLIFDSTADDR");
1577 				return;
1578 			}
1579 		}
1580 		if (prefix_modify_flags(pr, IFF_UP, IFF_NOLOCAL) == -1)
1581 			return;
1582 		pr->pr_kernel_state |= PR_AUTO;
1583 		if (pr->pr_state & PR_ONLINK)
1584 			pr->pr_kernel_state |= PR_ONLINK;
1585 		else
1586 			pr->pr_kernel_state &= ~PR_ONLINK;
1587 	}
1588 	if (!(pr->pr_state & PR_AUTO) && (pr->pr_kernel_state & PR_AUTO)) {
1589 		/* Turn on IFF_NOLOCAL and set the local address to all zero */
1590 		if (prefix_modify_flags(pr, IFF_NOLOCAL, 0) == -1)
1591 			return;
1592 		(void) strncpy(lifr.lifr_name, pr->pr_name,
1593 		    sizeof (lifr.lifr_name));
1594 		lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
1595 		sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
1596 		bzero(sin6, sizeof (struct sockaddr_in6));
1597 		sin6->sin6_family = AF_INET6;
1598 		if (debug & D_PREFIX) {
1599 			logmsg(LOG_DEBUG, "prefix_update_k(%s) set addr %s "
1600 			    "for PR_AUTO off\n", pr->pr_name,
1601 			    inet_ntop(AF_INET6, (void *)&sin6->sin6_addr,
1602 				abuf, sizeof (abuf)));
1603 		}
1604 		if (ioctl(pi->pi_sock, SIOCSLIFADDR, (char *)&lifr) < 0) {
1605 			logperror_pr(pr, "prefix_update_k: SIOCSLIFADDR");
1606 			return;
1607 		}
1608 		pr->pr_kernel_state &= ~PR_AUTO;
1609 	}
1610 	if ((pr->pr_state & PR_DEPRECATED) &&
1611 	    !(pr->pr_kernel_state & PR_DEPRECATED) &&
1612 	    (pr->pr_kernel_state & PR_AUTO)) {
1613 		/* Only applies if PR_AUTO */
1614 		if (prefix_modify_flags(pr, IFF_DEPRECATED, 0) == -1)
1615 			return;
1616 		pr->pr_kernel_state |= PR_DEPRECATED;
1617 	}
1618 	if (!(pr->pr_state & PR_DEPRECATED) &&
1619 	    (pr->pr_kernel_state & PR_DEPRECATED)) {
1620 		if (prefix_modify_flags(pr, 0, IFF_DEPRECATED) == -1)
1621 			return;
1622 		pr->pr_kernel_state &= ~PR_DEPRECATED;
1623 	}
1624 	if ((pr->pr_state & PR_ONLINK) && !(pr->pr_kernel_state & PR_ONLINK)) {
1625 		/* Set the subnet and set IFF_UP */
1626 		(void) strncpy(lifr.lifr_name, pr->pr_name,
1627 		    sizeof (lifr.lifr_name));
1628 		lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
1629 		sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
1630 		bzero(sin6, sizeof (struct sockaddr_in6));
1631 		sin6->sin6_family = AF_INET6;
1632 		sin6->sin6_addr = pr->pr_prefix;
1633 		lifr.lifr_addrlen = pr->pr_prefix_len;
1634 		if (debug & D_PREFIX) {
1635 			logmsg(LOG_DEBUG, "prefix_update_k(%s) set subnet "
1636 			    "%s/%d for PR_ONLINK on\n", pr->pr_name,
1637 			    inet_ntop(AF_INET6, (void *)&sin6->sin6_addr,
1638 				abuf, sizeof (abuf)), lifr.lifr_addrlen);
1639 		}
1640 		if (ioctl(pi->pi_sock, SIOCSLIFSUBNET, (char *)&lifr) < 0) {
1641 			logperror_pr(pr, "prefix_update_k: SIOCSLIFSUBNET");
1642 			return;
1643 		}
1644 		if (!(pr->pr_state & PR_AUTO)) {
1645 			if (prefix_modify_flags(pr, IFF_NOLOCAL, 0) == -1)
1646 				return;
1647 		}
1648 		if (prefix_modify_flags(pr, IFF_UP, 0) == -1)
1649 			return;
1650 		pr->pr_kernel_state |= PR_ONLINK;
1651 	}
1652 	if (!(pr->pr_state & PR_ONLINK) && (pr->pr_kernel_state & PR_ONLINK)) {
1653 		/* Set the prefixlen to 128 */
1654 		(void) strncpy(lifr.lifr_name, pr->pr_name,
1655 		    sizeof (lifr.lifr_name));
1656 		lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
1657 		sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
1658 		bzero(sin6, sizeof (struct sockaddr_in6));
1659 		sin6->sin6_family = AF_INET6;
1660 		sin6->sin6_addr = pr->pr_address;
1661 		lifr.lifr_addrlen = IPV6_ABITS;
1662 		if (debug & D_PREFIX) {
1663 			logmsg(LOG_DEBUG, "prefix_update_k(%s) set subnet "
1664 			    "%s/%d for PR_ONLINK off\n", pr->pr_name,
1665 			    inet_ntop(AF_INET6, (void *)&sin6->sin6_addr,
1666 				abuf, sizeof (abuf)), lifr.lifr_addrlen);
1667 		}
1668 		if (ioctl(pi->pi_sock, SIOCSLIFSUBNET, (char *)&lifr) < 0) {
1669 			logperror_pr(pr, "prefix_update_k: SIOCSLIFSUBNET");
1670 			return;
1671 		}
1672 		pr->pr_kernel_state &= ~PR_ONLINK;
1673 	}
1674 }
1675 
1676 /*
1677  * Called with the number of millseconds elapsed since the last call.
1678  * Determines if any timeout event has occurred and
1679  * returns the number of milliseconds until the next timeout event.
1680  * Returns TIMER_INFINITY for "never".
1681  */
1682 uint_t
1683 prefix_timer(struct prefix *pr, uint_t elapsed)
1684 {
1685 	uint_t next = TIMER_INFINITY;
1686 	char abuf[INET6_ADDRSTRLEN];
1687 
1688 	if (debug & (D_PREFIX|D_TMP)) {
1689 		logmsg(LOG_DEBUG, "prefix_timer(%s, %s/%u, %d) "
1690 		    "valid %d pref %d onlink %d\n",
1691 		    pr->pr_name,
1692 		    inet_ntop(AF_INET6, (void *)&pr->pr_prefix,
1693 		    abuf, sizeof (abuf)), pr->pr_prefix_len,
1694 		    elapsed, pr->pr_ValidLifetime, pr->pr_PreferredLifetime,
1695 		    pr->pr_OnLinkLifetime);
1696 	}
1697 
1698 	/* Exclude static prefixes */
1699 	if (pr->pr_state & PR_STATIC)
1700 		return (next);
1701 
1702 	if (pr->pr_AutonomousFlag &&
1703 	    (pr->pr_PreferredLifetime != PREFIX_INFINITY)) {
1704 		if (pr->pr_PreferredLifetime <= elapsed) {
1705 			pr->pr_PreferredLifetime = 0;
1706 		} else {
1707 			pr->pr_PreferredLifetime -= elapsed;
1708 			if (pr->pr_PreferredLifetime < next)
1709 				next = pr->pr_PreferredLifetime;
1710 		}
1711 	}
1712 	if (pr->pr_AutonomousFlag &&
1713 	    (pr->pr_ValidLifetime != PREFIX_INFINITY)) {
1714 		if (pr->pr_ValidLifetime <= elapsed) {
1715 			pr->pr_ValidLifetime = 0;
1716 		} else {
1717 			pr->pr_ValidLifetime -= elapsed;
1718 			if (pr->pr_ValidLifetime < next)
1719 				next = pr->pr_ValidLifetime;
1720 		}
1721 	}
1722 	if (pr->pr_OnLinkFlag &&
1723 	    (pr->pr_OnLinkLifetime != PREFIX_INFINITY)) {
1724 		if (pr->pr_OnLinkLifetime <= elapsed) {
1725 			pr->pr_OnLinkLifetime = 0;
1726 		} else {
1727 			pr->pr_OnLinkLifetime -= elapsed;
1728 			if (pr->pr_OnLinkLifetime < next)
1729 				next = pr->pr_OnLinkLifetime;
1730 		}
1731 	}
1732 	if (pr->pr_AutonomousFlag && pr->pr_ValidLifetime == 0)
1733 		pr->pr_state &= ~(PR_AUTO|PR_DEPRECATED);
1734 	if (pr->pr_AutonomousFlag && pr->pr_PreferredLifetime == 0 &&
1735 	    (pr->pr_state & PR_AUTO)) {
1736 		pr->pr_state |= PR_DEPRECATED;
1737 		if (debug & D_TMP)
1738 			logmsg(LOG_WARNING, "prefix_timer: deprecated "
1739 			    "prefix(%s)\n", pr->pr_name);
1740 	}
1741 	if (pr->pr_OnLinkFlag && pr->pr_OnLinkLifetime == 0)
1742 		pr->pr_state &= ~PR_ONLINK;
1743 
1744 	if (pr->pr_state != pr->pr_kernel_state) {
1745 		/* Might cause prefix to be deleted! */
1746 
1747 		/* Log a message when an addrconf prefix goes away */
1748 		if ((pr->pr_kernel_state & PR_AUTO) &&
1749 		    !(pr->pr_state & PR_AUTO)) {
1750 			char abuf[INET6_ADDRSTRLEN];
1751 
1752 			logmsg(LOG_WARNING,
1753 			    "Address removed due to timeout %s\n",
1754 			    inet_ntop(AF_INET6, (void *)&pr->pr_address,
1755 			    abuf, sizeof (abuf)));
1756 		}
1757 		prefix_update_k(pr);
1758 	}
1759 
1760 	return (next);
1761 }
1762 
1763 static char *
1764 prefix_print_state(int state, char *buf, int buflen)
1765 {
1766 	char *cp;
1767 	int cplen = buflen;
1768 
1769 	cp = buf;
1770 	cp[0] = '\0';
1771 
1772 	if (state & PR_ONLINK) {
1773 		if (strlcat(cp, "ONLINK ", cplen) >= cplen)
1774 			return (buf);
1775 		cp += strlen(cp);
1776 		cplen = buflen - (cp - buf);
1777 	}
1778 	if (state & PR_AUTO) {
1779 		if (strlcat(cp, "AUTO ", cplen) >= cplen)
1780 			return (buf);
1781 		cp += strlen(cp);
1782 		cplen = buflen - (cp - buf);
1783 	}
1784 	if (state & PR_DEPRECATED) {
1785 		if (strlcat(cp, "DEPRECATED ", cplen) >= cplen)
1786 			return (buf);
1787 		cp += strlen(cp);
1788 		cplen = buflen - (cp - buf);
1789 	}
1790 	if (state & PR_STATIC) {
1791 		if (strlcat(cp, "STATIC ", cplen) >= cplen)
1792 			return (buf);
1793 		cp += strlen(cp);
1794 		cplen = buflen - (cp - buf);
1795 	}
1796 	return (buf);
1797 }
1798 
1799 static void
1800 prefix_print(struct prefix *pr)
1801 {
1802 	char abuf[INET6_ADDRSTRLEN];
1803 	char buf1[PREFIX_STATESTRLEN], buf2[PREFIX_STATESTRLEN];
1804 
1805 	logmsg(LOG_DEBUG, "Prefix name: %s prefix %s/%u state %s "
1806 	    "kernel_state %s\n", pr->pr_name,
1807 	    inet_ntop(AF_INET6, (void *)&pr->pr_prefix, abuf, sizeof (abuf)),
1808 	    pr->pr_prefix_len,
1809 	    prefix_print_state(pr->pr_state, buf2, sizeof (buf2)),
1810 	    prefix_print_state(pr->pr_kernel_state, buf1, sizeof (buf1)));
1811 	logmsg(LOG_DEBUG, "\tAddress: %s flags %llx in_use %d\n",
1812 	    inet_ntop(AF_INET6, (void *)&pr->pr_address, abuf, sizeof (abuf)),
1813 	    pr->pr_flags, pr->pr_in_use);
1814 	logmsg(LOG_DEBUG, "\tValidLifetime %u PreferredLifetime %u "
1815 	    "OnLinkLifetime %u\n", pr->pr_ValidLifetime,
1816 	    pr->pr_PreferredLifetime, pr->pr_OnLinkLifetime);
1817 	logmsg(LOG_DEBUG, "\tOnLink %d Auto %d\n",
1818 	    pr->pr_OnLinkFlag, pr->pr_AutonomousFlag);
1819 	logmsg(LOG_DEBUG, "\n");
1820 }
1821 
1822 /*
1823  * Does the address formed by pr->pr_prefix and pi->pi_token match
1824  * pr->pr_address. It does not match if a failover has happened
1825  * earlier (done by in.mpathd) from a different pi. Should not
1826  * be called for onlink prefixes.
1827  */
1828 boolean_t
1829 prefix_token_match(struct phyint *pi, struct prefix *pr, uint64_t flags)
1830 {
1831 	int i;
1832 	in6_addr_t addr, *token;
1833 
1834 	if (flags & IFF_TEMPORARY)
1835 		token = &pi->pi_tmp_token;
1836 	else
1837 		token = &pi->pi_token;
1838 	for (i = 0; i < 16; i++) {
1839 		/*
1840 		 * prefix_create ensures that pr_prefix has all-zero
1841 		 * bits after prefixlen.
1842 		 */
1843 		addr.s6_addr[i] = pr->pr_prefix.s6_addr[i] | token->s6_addr[i];
1844 	}
1845 	if (IN6_ARE_ADDR_EQUAL(&pr->pr_address, &addr)) {
1846 		return (_B_TRUE);
1847 	} else {
1848 		return (_B_FALSE);
1849 	}
1850 }
1851 
1852 /*
1853  * Lookup advertisement prefix structure that matches the prefix and
1854  * prefix length.
1855  * Assumes that the bits after prefixlen might not be zero.
1856  */
1857 struct adv_prefix *
1858 adv_prefix_lookup(struct phyint *pi, struct in6_addr prefix, int prefixlen)
1859 {
1860 	struct adv_prefix *adv_pr;
1861 	char abuf[INET6_ADDRSTRLEN];
1862 
1863 	if (debug & D_PREFIX) {
1864 		logmsg(LOG_DEBUG, "adv_prefix_lookup(%s, %s/%u)\n",
1865 		    pi->pi_name, inet_ntop(AF_INET6, (void *)&prefix,
1866 		    abuf, sizeof (abuf)), prefixlen);
1867 	}
1868 
1869 	for (adv_pr = pi->pi_adv_prefix_list; adv_pr != NULL;
1870 	    adv_pr = adv_pr->adv_pr_next) {
1871 		if (adv_pr->adv_pr_prefix_len == prefixlen &&
1872 		    prefix_equal(prefix, adv_pr->adv_pr_prefix, prefixlen))
1873 			return (adv_pr);
1874 	}
1875 	return (NULL);
1876 }
1877 
1878 /*
1879  * Initialize a new advertisement prefix.
1880  */
1881 struct adv_prefix *
1882 adv_prefix_create(struct phyint *pi, struct in6_addr prefix, int prefixlen)
1883 {
1884 	struct adv_prefix *adv_pr;
1885 	char abuf[INET6_ADDRSTRLEN];
1886 
1887 	if (debug & D_PREFIX) {
1888 		logmsg(LOG_DEBUG, "adv_prefix_create(%s, %s/%u)\n",
1889 		    pi->pi_name, inet_ntop(AF_INET6, (void *)&prefix,
1890 		    abuf, sizeof (abuf)), prefixlen);
1891 	}
1892 	adv_pr = (struct adv_prefix *)calloc(sizeof (struct adv_prefix), 1);
1893 	if (adv_pr == NULL) {
1894 		logmsg(LOG_ERR, "adv_prefix_create: calloc\n");
1895 		return (NULL);
1896 	}
1897 	/*
1898 	 * The prefix might have non-zero bits after the prefix len bits.
1899 	 * Force them to be zero.
1900 	 */
1901 	prefix_set(&adv_pr->adv_pr_prefix, prefix, prefixlen);
1902 	adv_pr->adv_pr_prefix_len = prefixlen;
1903 	adv_prefix_insert(pi, adv_pr);
1904 	return (adv_pr);
1905 }
1906 
1907 /* Insert in linked list */
1908 static void
1909 adv_prefix_insert(struct phyint *pi, struct adv_prefix *adv_pr)
1910 {
1911 	adv_pr->adv_pr_next = pi->pi_adv_prefix_list;
1912 	adv_pr->adv_pr_prev = NULL;
1913 	if (pi->pi_adv_prefix_list != NULL)
1914 		pi->pi_adv_prefix_list->adv_pr_prev = adv_pr;
1915 	pi->pi_adv_prefix_list = adv_pr;
1916 	adv_pr->adv_pr_physical = pi;
1917 }
1918 
1919 /*
1920  * Delete (unlink and free) from our tables. There should be
1921  * a corresponding "struct prefix *" which will clean up the kernel
1922  * if necessary. adv_prefix is just used for sending out advertisements.
1923  */
1924 static void
1925 adv_prefix_delete(struct adv_prefix *adv_pr)
1926 {
1927 	struct phyint *pi;
1928 	char abuf[INET6_ADDRSTRLEN];
1929 
1930 	if (debug & D_PREFIX) {
1931 		logmsg(LOG_DEBUG, "adv_prefix_delete(%s, %s/%u)\n",
1932 		    adv_pr->adv_pr_physical->pi_name,
1933 		    inet_ntop(AF_INET6, (void *)&adv_pr->adv_pr_prefix,
1934 		    abuf, sizeof (abuf)), adv_pr->adv_pr_prefix_len);
1935 	}
1936 	pi = adv_pr->adv_pr_physical;
1937 
1938 	if (adv_pr->adv_pr_prev == NULL) {
1939 		if (pi != NULL)
1940 			pi->pi_adv_prefix_list = adv_pr->adv_pr_next;
1941 	} else {
1942 		adv_pr->adv_pr_prev->adv_pr_next = adv_pr->adv_pr_next;
1943 	}
1944 	if (adv_pr->adv_pr_next != NULL)
1945 		adv_pr->adv_pr_next->adv_pr_prev = adv_pr->adv_pr_prev;
1946 	adv_pr->adv_pr_next = adv_pr->adv_pr_prev = NULL;
1947 	free(adv_pr);
1948 }
1949 
1950 /*
1951  * Called with the number of millseconds elapsed since the last call.
1952  * Determines if any timeout event has occurred and
1953  * returns the number of milliseconds until the next timeout event.
1954  * Returns TIMER_INFINITY for "never".
1955  */
1956 uint_t
1957 adv_prefix_timer(struct adv_prefix *adv_pr, uint_t elapsed)
1958 {
1959 	int seconds_elapsed = (elapsed + 500) / 1000;	/* Rounded */
1960 	char abuf[INET6_ADDRSTRLEN];
1961 
1962 	if (debug & D_PREFIX) {
1963 		logmsg(LOG_DEBUG, "adv_prefix_timer(%s, %s/%u, %d)\n",
1964 		    adv_pr->adv_pr_physical->pi_name,
1965 		    inet_ntop(AF_INET6, (void *)&adv_pr->adv_pr_prefix,
1966 		    abuf, sizeof (abuf)), adv_pr->adv_pr_prefix_len,
1967 		    elapsed);
1968 	}
1969 
1970 	/* Decrement Expire time left for real-time lifetimes */
1971 	if (adv_pr->adv_pr_AdvValidRealTime) {
1972 		if (adv_pr->adv_pr_AdvValidExpiration > seconds_elapsed)
1973 			adv_pr->adv_pr_AdvValidExpiration -= seconds_elapsed;
1974 		else
1975 			adv_pr->adv_pr_AdvValidExpiration = 0;
1976 	}
1977 	if (adv_pr->adv_pr_AdvPreferredRealTime) {
1978 		if (adv_pr->adv_pr_AdvPreferredExpiration > seconds_elapsed) {
1979 			adv_pr->adv_pr_AdvPreferredExpiration -=
1980 			    seconds_elapsed;
1981 		} else {
1982 			adv_pr->adv_pr_AdvPreferredExpiration = 0;
1983 		}
1984 	}
1985 	return (TIMER_INFINITY);
1986 }
1987 
1988 static void
1989 adv_prefix_print(struct adv_prefix *adv_pr)
1990 {
1991 	print_prefixlist(adv_pr->adv_pr_config);
1992 }
1993 
1994 /* Lookup router on its link-local IPv6 address */
1995 struct router *
1996 router_lookup(struct phyint *pi, struct in6_addr addr)
1997 {
1998 	struct router *dr;
1999 	char abuf[INET6_ADDRSTRLEN];
2000 
2001 	if (debug & D_ROUTER) {
2002 		logmsg(LOG_DEBUG, "router_lookup(%s, %s)\n", pi->pi_name,
2003 		    inet_ntop(AF_INET6, (void *)&addr,
2004 		    abuf, sizeof (abuf)));
2005 	}
2006 
2007 	for (dr = pi->pi_router_list; dr != NULL; dr = dr->dr_next) {
2008 		if (bcmp((char *)&addr, (char *)&dr->dr_address,
2009 		    sizeof (addr)) == 0)
2010 			return (dr);
2011 	}
2012 	return (NULL);
2013 }
2014 
2015 /*
2016  * Create a default router entry.
2017  * The lifetime parameter is in seconds.
2018  */
2019 struct router *
2020 router_create(struct phyint *pi, struct in6_addr addr, uint_t lifetime)
2021 {
2022 	struct router *dr;
2023 	char abuf[INET6_ADDRSTRLEN];
2024 
2025 	if (debug & D_ROUTER) {
2026 		logmsg(LOG_DEBUG, "router_create(%s, %s, %u)\n", pi->pi_name,
2027 		    inet_ntop(AF_INET6, (void *)&addr,
2028 		    abuf, sizeof (abuf)), lifetime);
2029 	}
2030 
2031 	dr = (struct router *)calloc(sizeof (struct router), 1);
2032 	if (dr == NULL) {
2033 		logmsg(LOG_ERR, "router_create: out of memory\n");
2034 		return (NULL);
2035 	}
2036 	dr->dr_address = addr;
2037 	dr->dr_lifetime = lifetime;
2038 	router_insert(pi, dr);
2039 	if (dr->dr_lifetime != 0) {
2040 		/*
2041 		 * Delete an onlink default if it exists since we now have
2042 		 * at least one default router.
2043 		 */
2044 		if (pi->pi_onlink_default)
2045 			router_delete_onlink(dr->dr_physical);
2046 		router_add_k(dr);
2047 	}
2048 	return (dr);
2049 }
2050 
2051 /* Insert in linked list */
2052 static void
2053 router_insert(struct phyint *pi, struct router *dr)
2054 {
2055 	dr->dr_next = pi->pi_router_list;
2056 	dr->dr_prev = NULL;
2057 	if (pi->pi_router_list != NULL)
2058 		pi->pi_router_list->dr_prev = dr;
2059 	pi->pi_router_list = dr;
2060 	dr->dr_physical = pi;
2061 }
2062 
2063 /*
2064  * Delete (unlink and free).
2065  * Handles delete of things that have not yet been inserted in the list
2066  * i.e. dr_physical is NULL.
2067  */
2068 static void
2069 router_delete(struct router *dr)
2070 {
2071 	struct phyint *pi;
2072 	char abuf[INET6_ADDRSTRLEN];
2073 
2074 	if (debug & D_ROUTER) {
2075 		logmsg(LOG_DEBUG, "router_delete(%s, %s, %u)\n",
2076 		    dr->dr_physical->pi_name,
2077 		    inet_ntop(AF_INET6, (void *)&dr->dr_address,
2078 		    abuf, sizeof (abuf)), dr->dr_lifetime);
2079 	}
2080 	pi = dr->dr_physical;
2081 	if (dr->dr_inkernel) {
2082 		/*
2083 		 * Create a on-link default route only if the interface
2084 		 * is present in the kernel. This function is called
2085 		 * to clean up the routes when the interface is
2086 		 * unplumbed. In that case, don't try to create one
2087 		 * in the kernel.
2088 		 */
2089 		if (pi->pi_kernel_state & PI_PRESENT) {
2090 			if (!dr->dr_onlink &&
2091 			    dr->dr_physical->pi_num_k_routers == 1) {
2092 				(void) router_create_onlink(dr->dr_physical);
2093 			}
2094 			router_delete_k(dr);
2095 		}
2096 	}
2097 	if (dr->dr_onlink)
2098 		pi->pi_onlink_default = _B_FALSE;
2099 
2100 	if (dr->dr_prev == NULL) {
2101 		if (pi != NULL)
2102 			pi->pi_router_list = dr->dr_next;
2103 	} else {
2104 		dr->dr_prev->dr_next = dr->dr_next;
2105 	}
2106 	if (dr->dr_next != NULL)
2107 		dr->dr_next->dr_prev = dr->dr_prev;
2108 	dr->dr_next = dr->dr_prev = NULL;
2109 	free(dr);
2110 }
2111 
2112 
2113 /* Create an onlink default route */
2114 struct router *
2115 router_create_onlink(struct phyint *pi)
2116 {
2117 	struct router *dr;
2118 	struct prefix *pr;
2119 
2120 	if (debug & D_ROUTER) {
2121 		logmsg(LOG_DEBUG, "router_create_onlink(%s)\n", pi->pi_name);
2122 	}
2123 
2124 	if (pi->pi_onlink_default) {
2125 		logmsg(LOG_ERR, "router_create_onlink: already an onlink "
2126 		    "default: %s\n", pi->pi_name);
2127 		return (NULL);
2128 	}
2129 
2130 	/*
2131 	 * Find the interface address to use for the route gateway.
2132 	 * We need to use the link-local since the others ones might be
2133 	 * deleted when the prefixes get invalidated.
2134 	 */
2135 	for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) {
2136 		if ((pr->pr_state & PR_AUTO) &&
2137 		    IN6_IS_ADDR_LINKLOCAL(&pr->pr_address))
2138 			break;
2139 	}
2140 	if (pr == NULL) {
2141 		logmsg(LOG_ERR, "router_create_onlink: no source address\n");
2142 		return (NULL);
2143 	}
2144 	dr = (struct router *)calloc(sizeof (struct router), 1);
2145 	if (dr == NULL) {
2146 		logmsg(LOG_ERR, "router_create_onlink: out of memory\n");
2147 		return (NULL);
2148 	}
2149 	dr->dr_address = pr->pr_address;
2150 	dr->dr_lifetime = 1;	/* Not used */
2151 	dr->dr_onlink = _B_TRUE;
2152 	router_insert(pi, dr);
2153 
2154 	router_add_k(dr);
2155 	pi->pi_onlink_default = _B_TRUE;
2156 	return (dr);
2157 }
2158 
2159 /* Remove an onlink default route */
2160 static void
2161 router_delete_onlink(struct phyint *pi)
2162 {
2163 	struct router *dr, *next_dr;
2164 
2165 	if (debug & D_ROUTER) {
2166 		logmsg(LOG_DEBUG, "router_delete_onlink(%s)\n", pi->pi_name);
2167 	}
2168 
2169 	if (!pi->pi_onlink_default) {
2170 		logmsg(LOG_ERR, "router_delete_onlink: no onlink default: "
2171 		    "%s\n", pi->pi_name);
2172 		return;
2173 	}
2174 	/* Find all onlink routes */
2175 	for (dr = pi->pi_router_list; dr != NULL; dr = next_dr) {
2176 		next_dr = dr->dr_next;
2177 		if (dr->dr_onlink)
2178 			router_delete(dr);
2179 	}
2180 }
2181 
2182 /*
2183  * Update the kernel to match dr_lifetime
2184  */
2185 void
2186 router_update_k(struct router *dr)
2187 {
2188 	char abuf[INET6_ADDRSTRLEN];
2189 
2190 	if (debug & D_ROUTER) {
2191 		logmsg(LOG_DEBUG, "router_update_k(%s, %s, %u)\n",
2192 		    dr->dr_physical->pi_name,
2193 		    inet_ntop(AF_INET6, (void *)&dr->dr_address,
2194 		    abuf, sizeof (abuf)), dr->dr_lifetime);
2195 	}
2196 
2197 	if (dr->dr_lifetime == 0 && dr->dr_inkernel) {
2198 		/* Log a message when last router goes away */
2199 		if (dr->dr_physical->pi_num_k_routers == 1) {
2200 			logmsg(LOG_WARNING,
2201 			    "Last default router (%s) removed on %s\n",
2202 			    inet_ntop(AF_INET6, (void *)&dr->dr_address,
2203 			    abuf, sizeof (abuf)), dr->dr_physical->pi_name);
2204 		}
2205 		router_delete(dr);
2206 	} else if (dr->dr_lifetime != 0 && !dr->dr_inkernel) {
2207 		/*
2208 		 * Delete an onlink default if it exists since we now have
2209 		 * at least one default router.
2210 		 */
2211 		if (dr->dr_physical->pi_onlink_default)
2212 			router_delete_onlink(dr->dr_physical);
2213 		router_add_k(dr);
2214 	}
2215 }
2216 
2217 
2218 /*
2219  * Called with the number of millseconds elapsed since the last call.
2220  * Determines if any timeout event has occurred and
2221  * returns the number of milliseconds until the next timeout event.
2222  * Returns TIMER_INFINITY for "never".
2223  */
2224 uint_t
2225 router_timer(struct router *dr, uint_t elapsed)
2226 {
2227 	uint_t next = TIMER_INFINITY;
2228 	char abuf[INET6_ADDRSTRLEN];
2229 
2230 	if (debug & D_ROUTER) {
2231 		logmsg(LOG_DEBUG, "router_timer(%s, %s, %u, %d)\n",
2232 		    dr->dr_physical->pi_name,
2233 		    inet_ntop(AF_INET6, (void *)&dr->dr_address,
2234 		    abuf, sizeof (abuf)), dr->dr_lifetime, elapsed);
2235 	}
2236 	if (dr->dr_onlink) {
2237 		/* No timeout */
2238 		return (next);
2239 	}
2240 	if (dr->dr_lifetime <= elapsed) {
2241 		dr->dr_lifetime = 0;
2242 	} else {
2243 		dr->dr_lifetime -= elapsed;
2244 		if (dr->dr_lifetime < next)
2245 			next = dr->dr_lifetime;
2246 	}
2247 
2248 	if (dr->dr_lifetime == 0) {
2249 		/* Log a message when last router goes away */
2250 		if (dr->dr_physical->pi_num_k_routers == 1) {
2251 			logmsg(LOG_WARNING,
2252 			    "Last default router (%s) timed out on %s\n",
2253 			    inet_ntop(AF_INET6, (void *)&dr->dr_address,
2254 			    abuf, sizeof (abuf)), dr->dr_physical->pi_name);
2255 		}
2256 		router_delete(dr);
2257 	}
2258 	return (next);
2259 }
2260 
2261 /*
2262  * Add a default route to the kernel (unless the lifetime is zero)
2263  * Handles onlink default routes.
2264  */
2265 static void
2266 router_add_k(struct router *dr)
2267 {
2268 	struct phyint *pi = dr->dr_physical;
2269 	char abuf[INET6_ADDRSTRLEN];
2270 	int rlen;
2271 
2272 	if (debug & D_ROUTER) {
2273 		logmsg(LOG_DEBUG, "router_add_k(%s, %s, %u)\n",
2274 		    dr->dr_physical->pi_name,
2275 		    inet_ntop(AF_INET6, (void *)&dr->dr_address,
2276 		    abuf, sizeof (abuf)), dr->dr_lifetime);
2277 	}
2278 
2279 	if (dr->dr_onlink)
2280 		rt_msg->rtm_flags = 0;
2281 	else
2282 		rt_msg->rtm_flags = RTF_GATEWAY;
2283 
2284 	rta_gateway->sin6_addr = dr->dr_address;
2285 
2286 	rta_ifp->sdl_index = if_nametoindex(pi->pi_name);
2287 	if (rta_ifp->sdl_index == 0) {
2288 		logperror_pi(pi, "router_add_k: if_nametoindex");
2289 		return;
2290 	}
2291 
2292 	rt_msg->rtm_type = RTM_ADD;
2293 	rt_msg->rtm_seq = ++rtmseq;
2294 	rlen = write(rtsock, rt_msg, rt_msg->rtm_msglen);
2295 	if (rlen < 0) {
2296 		if (errno != EEXIST) {
2297 			logperror_pi(pi, "router_add_k: RTM_ADD");
2298 			return;
2299 		}
2300 	} else if (rlen < rt_msg->rtm_msglen) {
2301 		logmsg(LOG_ERR, "router_add_k: write to routing socket got "
2302 		    "only %d for rlen (interface %s)\n", rlen, pi->pi_name);
2303 		return;
2304 	}
2305 	dr->dr_inkernel = _B_TRUE;
2306 	if (!dr->dr_onlink)
2307 		pi->pi_num_k_routers++;
2308 }
2309 
2310 /*
2311  * Delete a route from the kernel.
2312  * Handles onlink default routes.
2313  */
2314 static void
2315 router_delete_k(struct router *dr)
2316 {
2317 	struct phyint *pi = dr->dr_physical;
2318 	char abuf[INET6_ADDRSTRLEN];
2319 	int rlen;
2320 
2321 	if (debug & D_ROUTER) {
2322 		logmsg(LOG_DEBUG, "router_delete_k(%s, %s, %u)\n",
2323 		    dr->dr_physical->pi_name,
2324 		    inet_ntop(AF_INET6, (void *)&dr->dr_address,
2325 		    abuf, sizeof (abuf)), dr->dr_lifetime);
2326 	}
2327 
2328 	if (dr->dr_onlink)
2329 		rt_msg->rtm_flags = 0;
2330 	else
2331 		rt_msg->rtm_flags = RTF_GATEWAY;
2332 
2333 	rta_gateway->sin6_addr = dr->dr_address;
2334 
2335 	rta_ifp->sdl_index = if_nametoindex(pi->pi_name);
2336 	if (rta_ifp->sdl_index == 0) {
2337 		logperror_pi(pi, "router_delete_k: if_nametoindex");
2338 		return;
2339 	}
2340 
2341 	rt_msg->rtm_type = RTM_DELETE;
2342 	rt_msg->rtm_seq = ++rtmseq;
2343 	rlen = write(rtsock, rt_msg, rt_msg->rtm_msglen);
2344 	if (rlen < 0) {
2345 		if (errno != ESRCH) {
2346 			logperror_pi(pi, "router_delete_k: RTM_DELETE");
2347 		}
2348 	} else if (rlen < rt_msg->rtm_msglen) {
2349 		logmsg(LOG_ERR, "router_delete_k: write to routing socket got "
2350 		    "only %d for rlen (interface %s)\n", rlen, pi->pi_name);
2351 	}
2352 	dr->dr_inkernel = _B_FALSE;
2353 	if (!dr->dr_onlink)
2354 		pi->pi_num_k_routers--;
2355 }
2356 
2357 
2358 static void
2359 router_print(struct router *dr)
2360 {
2361 	char abuf[INET6_ADDRSTRLEN];
2362 
2363 	logmsg(LOG_DEBUG, "Router %s on %s inkernel %d onlink %d lifetime %u\n",
2364 	    inet_ntop(AF_INET6, (void *)&dr->dr_address,
2365 	    abuf, sizeof (abuf)),
2366 	    dr->dr_physical->pi_name,
2367 	    dr->dr_inkernel, dr->dr_onlink, dr->dr_lifetime);
2368 }
2369 
2370 
2371 void
2372 phyint_print_all(void)
2373 {
2374 	struct phyint *pi;
2375 
2376 	for (pi = phyints; pi != NULL; pi = pi->pi_next) {
2377 		phyint_print(pi);
2378 	}
2379 }
2380 
2381 void
2382 phyint_cleanup(pi)
2383 	struct phyint *pi;
2384 {
2385 	pi->pi_state = 0;
2386 	pi->pi_kernel_state = 0;
2387 
2388 	if (pi->pi_AdvSendAdvertisements) {
2389 		check_to_advertise(pi, ADV_OFF);
2390 	} else {
2391 		check_to_solicit(pi, SOLICIT_OFF);
2392 	}
2393 
2394 	while (pi->pi_router_list)
2395 		router_delete(pi->pi_router_list);
2396 	(void) poll_remove(pi->pi_sock);
2397 	(void) close(pi->pi_sock);
2398 	pi->pi_sock = -1;
2399 }
2400