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