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