xref: /illumos-gate/usr/src/cmd/cmd-inet/usr.lib/in.ndpd/main.c (revision 20a7641f9918de8574b8b3b47dbe35c4bfc78df1)
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  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
22  * Copyright 2022 Oxide Computer Company
23  */
24 
25 #include "defs.h"
26 #include "tables.h"
27 #include <fcntl.h>
28 #include <sys/un.h>
29 
30 static void	initlog(void);
31 static void	run_timeouts(void);
32 
33 static void	advertise(struct sockaddr_in6 *sin6, struct phyint *pi,
34 		    boolean_t no_prefixes);
35 static void	solicit(struct sockaddr_in6 *sin6, struct phyint *pi);
36 static void	initifs(boolean_t first);
37 static void	check_if_removed(struct phyint *pi);
38 static void	loopback_ra_enqueue(struct phyint *pi,
39 		    struct nd_router_advert *ra, int len);
40 static void	loopback_ra_dequeue(void);
41 static void	check_daemonize(void);
42 
43 struct in6_addr all_nodes_mcast = { { 0xff, 0x2, 0x0, 0x0,
44 				    0x0, 0x0, 0x0, 0x0,
45 				    0x0, 0x0, 0x0, 0x0,
46 				    0x0, 0x0, 0x0, 0x1 } };
47 
48 struct in6_addr all_routers_mcast = { { 0xff, 0x2, 0x0, 0x0,
49 				    0x0, 0x0, 0x0, 0x0,
50 				    0x0, 0x0, 0x0, 0x0,
51 				    0x0, 0x0, 0x0, 0x2 } };
52 
53 static struct sockaddr_in6 v6allnodes = { AF_INET6, 0, 0,
54 				    { 0xff, 0x2, 0x0, 0x0,
55 				    0x0, 0x0, 0x0, 0x0,
56 				    0x0, 0x0, 0x0, 0x0,
57 				    0x0, 0x0, 0x0, 0x1 } };
58 
59 static struct sockaddr_in6 v6allrouters = { AF_INET6, 0, 0,
60 				    { 0xff, 0x2, 0x0, 0x0,
61 				    0x0, 0x0, 0x0, 0x0,
62 				    0x0, 0x0, 0x0, 0x0,
63 				    0x0, 0x0, 0x0, 0x2 } };
64 
65 static char **argv0;		/* Saved for re-exec on SIGHUP */
66 
67 static uint64_t packet[(IP_MAXPACKET + 1)/8];
68 
69 static int	show_ifs = 0;
70 static boolean_t	already_daemonized = _B_FALSE;
71 int		debug = 0;
72 int		no_loopback = 0; /* Do not send RA packets to ourselves */
73 
74 /*
75  * Size of routing socket message used by in.ndpd which includes the header,
76  * space for the RTA_DST, RTA_GATEWAY and RTA_NETMASK (each a sockaddr_in6)
77  * plus space for the RTA_IFP (a sockaddr_dl).
78  */
79 #define	NDP_RTM_MSGLEN	sizeof (struct rt_msghdr) +	\
80 			sizeof (struct sockaddr_in6) +	\
81 			sizeof (struct sockaddr_in6) +	\
82 			sizeof (struct sockaddr_in6) +	\
83 			sizeof (struct sockaddr_dl)
84 
85 /*
86  * These are referenced externally in tables.c in order to fill in the
87  * dynamic portions of the routing socket message and then to send the message
88  * itself.
89  */
90 int	rtsock = -1;			/* Routing socket */
91 struct	rt_msghdr	*rt_msg;	/* Routing socket message */
92 struct	sockaddr_in6	*rta_gateway;	/* RTA_GATEWAY sockaddr */
93 struct	sockaddr_dl	*rta_ifp;	/* RTA_IFP sockaddr */
94 
95 /*
96  * These sockets are used internally in this file.
97  */
98 static int	mibsock = -1;			/* mib request socket */
99 static int	cmdsock = -1;			/* command socket */
100 
101 static	int	ndpd_setup_cmd_listener(void);
102 static	void	ndpd_cmd_handler(int);
103 static	int	ndpd_process_cmd(int, ipadm_ndpd_msg_t *);
104 static	int	ndpd_send_error(int, int);
105 static	int	ndpd_set_autoconf(const char *, boolean_t);
106 static	int	ndpd_create_addrs(const char *, struct sockaddr_in6, int,
107     boolean_t, boolean_t, char *);
108 static	int	ndpd_delete_addrs(const char *);
109 static	int	phyint_check_ipadm_intfid(struct phyint *);
110 
111 /*
112  * Return the current time in milliseconds truncated to
113  * fit in an integer.
114  */
115 uint_t
116 getcurrenttime(void)
117 {
118 	struct timeval tp;
119 
120 	if (gettimeofday(&tp, NULL) < 0) {
121 		logperror("getcurrenttime: gettimeofday failed");
122 		exit(1);
123 	}
124 	return (tp.tv_sec * 1000 + tp.tv_usec / 1000);
125 }
126 
127 /*
128  * Output a preformated packet from the packet[] buffer.
129  */
130 static void
131 sendpacket(struct sockaddr_in6 *sin6, int sock, int size, int flags)
132 {
133 	int cc;
134 	char abuf[INET6_ADDRSTRLEN];
135 
136 	cc = sendto(sock, (char *)packet, size, flags,
137 	    (struct sockaddr *)sin6, sizeof (*sin6));
138 	if (cc < 0 || cc != size) {
139 		if (cc < 0) {
140 			logperror("sendpacket: sendto");
141 		}
142 		logmsg(LOG_ERR, "sendpacket: wrote %s %d chars, ret=%d\n",
143 		    inet_ntop(sin6->sin6_family,
144 		    (void *)&sin6->sin6_addr,
145 		    abuf, sizeof (abuf)),
146 		    size, cc);
147 	}
148 }
149 
150 /*
151  * If possible, place an ND_OPT_SOURCE_LINKADDR option at `optp'.
152  * Return the number of bytes placed in the option.
153  */
154 static uint_t
155 add_opt_lla(struct phyint *pi, struct nd_opt_lla *optp)
156 {
157 	uint_t optlen;
158 	uint_t hwaddrlen;
159 	struct lifreq lifr;
160 
161 	/* If this phyint doesn't have a link-layer address, bail */
162 	if (phyint_get_lla(pi, &lifr) == -1)
163 		return (0);
164 
165 	hwaddrlen = lifr.lifr_nd.lnr_hdw_len;
166 	/* roundup to multiple of 8 and make padding zero */
167 	optlen = ((sizeof (struct nd_opt_hdr) + hwaddrlen + 7) / 8) * 8;
168 	bzero(optp, optlen);
169 	optp->nd_opt_lla_type = ND_OPT_SOURCE_LINKADDR;
170 	optp->nd_opt_lla_len = optlen / 8;
171 	bcopy(lifr.lifr_nd.lnr_hdw_addr, optp->nd_opt_lla_hdw_addr, hwaddrlen);
172 
173 	return (optlen);
174 }
175 
176 /* Send a Router Solicitation */
177 static void
178 solicit(struct sockaddr_in6 *sin6, struct phyint *pi)
179 {
180 	int packetlen = 0;
181 	struct	nd_router_solicit *rs = (struct nd_router_solicit *)packet;
182 	char *pptr = (char *)packet;
183 
184 	rs->nd_rs_type = ND_ROUTER_SOLICIT;
185 	rs->nd_rs_code = 0;
186 	rs->nd_rs_cksum = htons(0);
187 	rs->nd_rs_reserved = htonl(0);
188 
189 	packetlen += sizeof (*rs);
190 	pptr += sizeof (*rs);
191 
192 	/* add options */
193 	packetlen += add_opt_lla(pi, (struct nd_opt_lla *)pptr);
194 
195 	if (debug & D_PKTOUT) {
196 		print_route_sol("Sending solicitation to ", pi, rs, packetlen,
197 		    sin6);
198 	}
199 	sendpacket(sin6, pi->pi_sock, packetlen, 0);
200 }
201 
202 /*
203  * Send a (set of) Router Advertisements and feed them back to ourselves
204  * for processing. Unless no_prefixes is set all prefixes are included.
205  * If there are too many prefix options to fit in one packet multiple
206  * packets will be sent - each containing a subset of the prefix options.
207  */
208 static void
209 advertise(struct sockaddr_in6 *sin6, struct phyint *pi, boolean_t no_prefixes)
210 {
211 	struct	nd_opt_prefix_info *po;
212 	char *pptr = (char *)packet;
213 	struct nd_router_advert *ra;
214 	struct adv_prefix *adv_pr;
215 	int packetlen = 0;
216 
217 	ra = (struct nd_router_advert *)pptr;
218 	ra->nd_ra_type = ND_ROUTER_ADVERT;
219 	ra->nd_ra_code = 0;
220 	ra->nd_ra_cksum = htons(0);
221 	ra->nd_ra_curhoplimit = pi->pi_AdvCurHopLimit;
222 	ra->nd_ra_flags_reserved = 0;
223 	if (pi->pi_AdvManagedFlag)
224 		ra->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
225 	if (pi->pi_AdvOtherConfigFlag)
226 		ra->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
227 
228 	if (pi->pi_adv_state == FINAL_ADV)
229 		ra->nd_ra_router_lifetime = htons(0);
230 	else
231 		ra->nd_ra_router_lifetime = htons(pi->pi_AdvDefaultLifetime);
232 	ra->nd_ra_reachable = htonl(pi->pi_AdvReachableTime);
233 	ra->nd_ra_retransmit = htonl(pi->pi_AdvRetransTimer);
234 
235 	packetlen = sizeof (*ra);
236 	pptr += sizeof (*ra);
237 
238 	if (pi->pi_adv_state == FINAL_ADV) {
239 		if (debug & D_PKTOUT) {
240 			print_route_adv("Sending advert (FINAL) to ", pi,
241 			    ra, packetlen, sin6);
242 		}
243 		sendpacket(sin6, pi->pi_sock, packetlen, 0);
244 		/* Feed packet back in for router operation */
245 		loopback_ra_enqueue(pi, ra, packetlen);
246 		return;
247 	}
248 
249 	/* add options */
250 	packetlen += add_opt_lla(pi, (struct nd_opt_lla *)pptr);
251 	pptr = (char *)packet + packetlen;
252 
253 	if (pi->pi_AdvLinkMTU != 0) {
254 		struct nd_opt_mtu *mo = (struct nd_opt_mtu *)pptr;
255 
256 		mo->nd_opt_mtu_type = ND_OPT_MTU;
257 		mo->nd_opt_mtu_len = sizeof (struct nd_opt_mtu) / 8;
258 		mo->nd_opt_mtu_reserved = 0;
259 		mo->nd_opt_mtu_mtu = htonl(pi->pi_AdvLinkMTU);
260 
261 		packetlen += sizeof (struct nd_opt_mtu);
262 		pptr += sizeof (struct nd_opt_mtu);
263 	}
264 
265 	if (no_prefixes) {
266 		if (debug & D_PKTOUT) {
267 			print_route_adv("Sending advert to ", pi,
268 			    ra, packetlen, sin6);
269 		}
270 		sendpacket(sin6, pi->pi_sock, packetlen, 0);
271 		/* Feed packet back in for router operation */
272 		loopback_ra_enqueue(pi, ra, packetlen);
273 		return;
274 	}
275 
276 	po = (struct nd_opt_prefix_info *)pptr;
277 	for (adv_pr = pi->pi_adv_prefix_list; adv_pr != NULL;
278 	    adv_pr = adv_pr->adv_pr_next) {
279 		if (!adv_pr->adv_pr_AdvOnLinkFlag &&
280 		    !adv_pr->adv_pr_AdvAutonomousFlag) {
281 			continue;
282 		}
283 
284 		/*
285 		 * If the prefix doesn't fit in packet send
286 		 * what we have so far and start with new packet.
287 		 */
288 		if (packetlen + sizeof (*po) >
289 		    pi->pi_LinkMTU - sizeof (struct ip6_hdr)) {
290 			if (debug & D_PKTOUT) {
291 				print_route_adv("Sending advert "
292 				    "(FRAG) to ",
293 				    pi, ra, packetlen, sin6);
294 			}
295 			sendpacket(sin6, pi->pi_sock, packetlen, 0);
296 			/* Feed packet back in for router operation */
297 			loopback_ra_enqueue(pi, ra, packetlen);
298 			packetlen = sizeof (*ra);
299 			pptr = (char *)packet + sizeof (*ra);
300 			po = (struct nd_opt_prefix_info *)pptr;
301 		}
302 		po->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
303 		po->nd_opt_pi_len = sizeof (*po)/8;
304 		po->nd_opt_pi_flags_reserved = 0;
305 		if (adv_pr->adv_pr_AdvOnLinkFlag) {
306 			po->nd_opt_pi_flags_reserved |=
307 			    ND_OPT_PI_FLAG_ONLINK;
308 		}
309 		if (adv_pr->adv_pr_AdvAutonomousFlag) {
310 			po->nd_opt_pi_flags_reserved |=
311 			    ND_OPT_PI_FLAG_AUTO;
312 		}
313 		po->nd_opt_pi_prefix_len = adv_pr->adv_pr_prefix_len;
314 		/*
315 		 * If both Adv*Expiration and Adv*Lifetime are
316 		 * set we prefer the former and make the lifetime
317 		 * decrement in real time.
318 		 */
319 		if (adv_pr->adv_pr_AdvValidRealTime) {
320 			po->nd_opt_pi_valid_time =
321 			    htonl(adv_pr->adv_pr_AdvValidExpiration);
322 		} else {
323 			po->nd_opt_pi_valid_time =
324 			    htonl(adv_pr->adv_pr_AdvValidLifetime);
325 		}
326 		if (adv_pr->adv_pr_AdvPreferredRealTime) {
327 			po->nd_opt_pi_preferred_time =
328 			    htonl(adv_pr->adv_pr_AdvPreferredExpiration);
329 		} else {
330 			po->nd_opt_pi_preferred_time =
331 			    htonl(adv_pr->adv_pr_AdvPreferredLifetime);
332 		}
333 		po->nd_opt_pi_reserved2 = htonl(0);
334 		po->nd_opt_pi_prefix = adv_pr->adv_pr_prefix;
335 
336 		po++;
337 		packetlen += sizeof (*po);
338 	}
339 	if (debug & D_PKTOUT) {
340 		print_route_adv("Sending advert to ", pi,
341 		    ra, packetlen, sin6);
342 	}
343 	sendpacket(sin6, pi->pi_sock, packetlen, 0);
344 	/* Feed packet back in for router operation */
345 	loopback_ra_enqueue(pi, ra, packetlen);
346 }
347 
348 /* Poll support */
349 static int		pollfd_num = 0;	/* Allocated and initialized */
350 static struct pollfd	*pollfds = NULL;
351 
352 /*
353  * Add fd to the set being polled. Returns 0 if ok; -1 if failed.
354  */
355 int
356 poll_add(int fd)
357 {
358 	int i;
359 	int new_num;
360 	struct pollfd *newfds;
361 
362 	/* Check if already present */
363 	for (i = 0; i < pollfd_num; i++) {
364 		if (pollfds[i].fd == fd)
365 			return (0);
366 	}
367 	/* Check for empty spot already present */
368 	for (i = 0; i < pollfd_num; i++) {
369 		if (pollfds[i].fd == -1) {
370 			pollfds[i].fd = fd;
371 			return (0);
372 		}
373 	}
374 
375 	/* Allocate space for 32 more fds and initialize to -1 */
376 	new_num = pollfd_num + 32;
377 	newfds = realloc(pollfds, new_num * sizeof (struct pollfd));
378 	if (newfds == NULL) {
379 		logperror("realloc");
380 		return (-1);
381 	}
382 
383 	newfds[pollfd_num].fd = fd;
384 	newfds[pollfd_num++].events = POLLIN;
385 
386 	for (i = pollfd_num; i < new_num; i++) {
387 		newfds[i].fd = -1;
388 		newfds[i].events = POLLIN;
389 	}
390 	pollfd_num = new_num;
391 	pollfds = newfds;
392 	return (0);
393 }
394 
395 /*
396  * Remove fd from the set being polled. Returns 0 if ok; -1 if failed.
397  */
398 int
399 poll_remove(int fd)
400 {
401 	int i;
402 
403 	/* Check if already present */
404 	for (i = 0; i < pollfd_num; i++) {
405 		if (pollfds[i].fd == fd) {
406 			pollfds[i].fd = -1;
407 			return (0);
408 		}
409 	}
410 	return (-1);
411 }
412 
413 /*
414  * Extract information about the ifname (either a physical interface and
415  * the ":0" logical interface or just a logical interface).
416  * If the interface (still) exists in kernel set pr_in_use
417  * for caller to be able to detect interfaces that are removed.
418  * Starts sending advertisements/solicitations when new physical interfaces
419  * are detected.
420  */
421 static void
422 if_process(int s, char *ifname, boolean_t first)
423 {
424 	struct lifreq lifr;
425 	struct phyint *pi;
426 	struct prefix *pr;
427 	char *cp;
428 	char phyintname[LIFNAMSIZ + 1];
429 
430 	if (debug & D_IFSCAN)
431 		logmsg(LOG_DEBUG, "if_process(%s)\n", ifname);
432 
433 	(void) strncpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
434 	lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
435 	if (ioctl(s, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
436 		if (errno == ENXIO) {
437 			/*
438 			 * Interface has disappeared
439 			 */
440 			return;
441 		}
442 		logperror("if_process: ioctl (get interface flags)");
443 		return;
444 	}
445 
446 	/*
447 	 * Ignore loopback, point-to-multipoint and VRRP interfaces.
448 	 * The IP addresses over VRRP interfaces cannot be auto-configured.
449 	 * Point-to-point interfaces always have IFF_MULTICAST set.
450 	 */
451 	if (!(lifr.lifr_flags & IFF_MULTICAST) ||
452 	    (lifr.lifr_flags & (IFF_LOOPBACK|IFF_VRRP))) {
453 		return;
454 	}
455 
456 	if (!(lifr.lifr_flags & IFF_IPV6))
457 		return;
458 
459 	(void) strncpy(phyintname, ifname, sizeof (phyintname));
460 	phyintname[sizeof (phyintname) - 1] = '\0';
461 	if ((cp = strchr(phyintname, IF_SEPARATOR)) != NULL) {
462 		*cp = '\0';
463 	}
464 
465 	pi = phyint_lookup(phyintname);
466 	if (pi == NULL) {
467 		pi = phyint_create(phyintname);
468 		if (pi == NULL) {
469 			logmsg(LOG_ERR, "if_process: out of memory\n");
470 			return;
471 		}
472 		/*
473 		 * if in.ndpd is restarted, check with ipmgmtd if there is any
474 		 * interface id to be configured for this interface.
475 		 */
476 		if (first) {
477 			if (phyint_check_ipadm_intfid(pi) == -1)
478 				logmsg(LOG_ERR, "Could not get ipadm info\n");
479 		}
480 	} else {
481 		/*
482 		 * if the phyint already exists, synchronize it with
483 		 * the kernel state. For a newly created phyint, phyint_create
484 		 * calls phyint_init_from_k().
485 		 */
486 		(void) phyint_init_from_k(pi);
487 	}
488 	if (pi->pi_sock == -1 && !(pi->pi_kernel_state & PI_PRESENT)) {
489 		/* Interface is not yet present */
490 		if (debug & D_PHYINT) {
491 			logmsg(LOG_DEBUG, "if_process: interface not yet "
492 			    "present %s\n", pi->pi_name);
493 		}
494 		return;
495 	}
496 
497 	if (pi->pi_sock != -1) {
498 		if (poll_add(pi->pi_sock) == -1) {
499 			/*
500 			 * reset state.
501 			 */
502 			phyint_cleanup(pi);
503 		}
504 	}
505 
506 	/*
507 	 * Check if IFF_ROUTER has been turned off in kernel in which
508 	 * case we have to turn off AdvSendAdvertisements.
509 	 * The kernel will automatically turn off IFF_ROUTER if
510 	 * ip6_forwarding is turned off.
511 	 * Note that we do not switch back should IFF_ROUTER be turned on.
512 	 */
513 	if (!first &&
514 	    pi->pi_AdvSendAdvertisements && !(pi->pi_flags & IFF_ROUTER)) {
515 		logmsg(LOG_INFO, "No longer a router on %s\n", pi->pi_name);
516 		check_to_advertise(pi, START_FINAL_ADV);
517 
518 		pi->pi_AdvSendAdvertisements = 0;
519 		pi->pi_sol_state = NO_SOLICIT;
520 	}
521 
522 	/*
523 	 * Send advertisments and solicitation only if the interface is
524 	 * present in the kernel.
525 	 */
526 	if (pi->pi_kernel_state & PI_PRESENT) {
527 
528 		if (pi->pi_AdvSendAdvertisements) {
529 			if (pi->pi_adv_state == NO_ADV)
530 				check_to_advertise(pi, START_INIT_ADV);
531 		} else {
532 			if (pi->pi_sol_state == NO_SOLICIT)
533 				check_to_solicit(pi, START_INIT_SOLICIT);
534 		}
535 	}
536 
537 	/*
538 	 * Track static kernel prefixes to prevent in.ndpd from clobbering
539 	 * them by creating a struct prefix for each prefix detected in the
540 	 * kernel.
541 	 */
542 	pr = prefix_lookup_name(pi, ifname);
543 	if (pr == NULL) {
544 		pr = prefix_create_name(pi, ifname);
545 		if (pr == NULL) {
546 			logmsg(LOG_ERR, "if_process: out of memory\n");
547 			return;
548 		}
549 		if (prefix_init_from_k(pr) == -1) {
550 			prefix_delete(pr);
551 			return;
552 		}
553 	}
554 	/* Detect prefixes which are removed */
555 	if (pr->pr_kernel_state != 0)
556 		pr->pr_in_use = _B_TRUE;
557 
558 	if ((lifr.lifr_flags & IFF_DUPLICATE) &&
559 	    !(lifr.lifr_flags & IFF_DHCPRUNNING) &&
560 	    (pr->pr_flags & IFF_TEMPORARY)) {
561 		in6_addr_t *token;
562 		int i;
563 		char abuf[INET6_ADDRSTRLEN];
564 
565 		if (++pr->pr_attempts >= MAX_DAD_FAILURES) {
566 			logmsg(LOG_ERR, "%s: token %s is duplicate after %d "
567 			    "attempts; disabling temporary addresses on %s",
568 			    pr->pr_name, inet_ntop(AF_INET6,
569 			    (void *)&pi->pi_tmp_token, abuf, sizeof (abuf)),
570 			    pr->pr_attempts, pi->pi_name);
571 			pi->pi_TmpAddrsEnabled = 0;
572 			tmptoken_delete(pi);
573 			prefix_delete(pr);
574 			return;
575 		}
576 		logmsg(LOG_WARNING, "%s: token %s is duplicate; trying again",
577 		    pr->pr_name, inet_ntop(AF_INET6, (void *)&pi->pi_tmp_token,
578 		    abuf, sizeof (abuf)));
579 		if (!tmptoken_create(pi)) {
580 			prefix_delete(pr);
581 			return;
582 		}
583 		token = &pi->pi_tmp_token;
584 		for (i = 0; i < 16; i++) {
585 			/*
586 			 * prefix_create ensures that pr_prefix has all-zero
587 			 * bits after prefixlen.
588 			 */
589 			pr->pr_address.s6_addr[i] = pr->pr_prefix.s6_addr[i] |
590 			    token->s6_addr[i];
591 		}
592 		if (prefix_lookup_addr_match(pr) != NULL) {
593 			prefix_delete(pr);
594 			return;
595 		}
596 		pr->pr_CreateTime = getcurrenttime() / MILLISEC;
597 		/*
598 		 * We've got a new token.  Clearing PR_AUTO causes
599 		 * prefix_update_k to bring the interface up and set the
600 		 * address.
601 		 */
602 		pr->pr_kernel_state &= ~PR_AUTO;
603 		prefix_update_k(pr);
604 	}
605 }
606 
607 static int ifsock = -1;
608 
609 /*
610  * Scan all interfaces to detect changes as well as new and deleted intefaces
611  * 'first' is set for the initial call only. Do not effect anything.
612  */
613 static void
614 initifs(boolean_t first)
615 {
616 	char *buf;
617 	int bufsize;
618 	int numifs;
619 	int n;
620 	struct lifnum lifn;
621 	struct lifconf lifc;
622 	struct lifreq *lifr;
623 	struct phyint *pi;
624 	struct phyint *next_pi;
625 	struct prefix *pr;
626 
627 	if (debug & D_IFSCAN)
628 		logmsg(LOG_DEBUG, "Reading interface configuration\n");
629 	if (ifsock < 0) {
630 		ifsock = socket(AF_INET6, SOCK_DGRAM, 0);
631 		if (ifsock < 0) {
632 			logperror("initifs: socket");
633 			return;
634 		}
635 	}
636 	lifn.lifn_family = AF_INET6;
637 	lifn.lifn_flags = LIFC_NOXMIT | LIFC_TEMPORARY;
638 	if (ioctl(ifsock, SIOCGLIFNUM, (char *)&lifn) < 0) {
639 		logperror("initifs: ioctl (get interface numbers)");
640 		return;
641 	}
642 	numifs = lifn.lifn_count;
643 	bufsize = numifs * sizeof (struct lifreq);
644 
645 	buf = (char *)malloc(bufsize);
646 	if (buf == NULL) {
647 		logmsg(LOG_ERR, "initifs: out of memory\n");
648 		return;
649 	}
650 
651 	/*
652 	 * Mark the interfaces so that we can find phyints and prefixes
653 	 * which have disappeared from the kernel.
654 	 * if_process will set pr_in_use when it finds the interface
655 	 * in the kernel.
656 	 */
657 	for (pi = phyints; pi != NULL; pi = pi->pi_next) {
658 		/*
659 		 * Before re-examining the state of the interfaces,
660 		 * PI_PRESENT should be cleared from pi_kernel_state.
661 		 */
662 		pi->pi_kernel_state &= ~PI_PRESENT;
663 		for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) {
664 			pr->pr_in_use = _B_FALSE;
665 		}
666 	}
667 
668 	lifc.lifc_family = AF_INET6;
669 	lifc.lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY;
670 	lifc.lifc_len = bufsize;
671 	lifc.lifc_buf = buf;
672 
673 	if (ioctl(ifsock, SIOCGLIFCONF, (char *)&lifc) < 0) {
674 		logperror("initifs: ioctl (get interface configuration)");
675 		free(buf);
676 		return;
677 	}
678 
679 	lifr = (struct lifreq *)lifc.lifc_req;
680 	for (n = lifc.lifc_len / sizeof (struct lifreq); n > 0; n--, lifr++)
681 		if_process(ifsock, lifr->lifr_name, first);
682 	free(buf);
683 
684 	/*
685 	 * Detect phyints that have been removed from the kernel.
686 	 * Since we can't recreate it here (would require ifconfig plumb
687 	 * logic) we just terminate use of that phyint.
688 	 */
689 	for (pi = phyints; pi != NULL; pi = next_pi) {
690 		next_pi = pi->pi_next;
691 		/*
692 		 * If interface (still) exists in kernel, set
693 		 * pi_state to indicate that.
694 		 */
695 		if (pi->pi_kernel_state & PI_PRESENT) {
696 			pi->pi_state |= PI_PRESENT;
697 		}
698 
699 		check_if_removed(pi);
700 	}
701 	if (show_ifs)
702 		phyint_print_all();
703 }
704 
705 
706 /*
707  * Router advertisement state machine. Used for everything but timer
708  * events which use advertise_event directly.
709  */
710 void
711 check_to_advertise(struct phyint *pi, enum adv_events event)
712 {
713 	uint_t delay;
714 	enum adv_states old_state = pi->pi_adv_state;
715 
716 	if (debug & D_STATE) {
717 		logmsg(LOG_DEBUG, "check_to_advertise(%s, %d) state %d\n",
718 		    pi->pi_name, (int)event, (int)old_state);
719 	}
720 	delay = advertise_event(pi, event, 0);
721 	if (delay != TIMER_INFINITY) {
722 		/* Make sure the global next event is updated */
723 		timer_schedule(delay);
724 	}
725 
726 	if (debug & D_STATE) {
727 		logmsg(LOG_DEBUG, "check_to_advertise(%s, %d) state %d -> %d\n",
728 		    pi->pi_name, (int)event, (int)old_state,
729 		    (int)pi->pi_adv_state);
730 	}
731 }
732 
733 /*
734  * Router advertisement state machine.
735  * Return the number of milliseconds until next timeout (TIMER_INFINITY
736  * if never).
737  * For the ADV_TIMER event the caller passes in the number of milliseconds
738  * since the last timer event in the 'elapsed' parameter.
739  */
740 uint_t
741 advertise_event(struct phyint *pi, enum adv_events event, uint_t elapsed)
742 {
743 	uint_t delay;
744 
745 	if (debug & D_STATE) {
746 		logmsg(LOG_DEBUG, "advertise_event(%s, %d, %d) state %d\n",
747 		    pi->pi_name, (int)event, elapsed, (int)pi->pi_adv_state);
748 	}
749 	check_daemonize();
750 	if (!pi->pi_AdvSendAdvertisements)
751 		return (TIMER_INFINITY);
752 	if (pi->pi_flags & IFF_NORTEXCH) {
753 		if (debug & D_PKTOUT) {
754 			logmsg(LOG_DEBUG, "Suppress sending RA packet on %s "
755 			    "(no route exchange on interface)\n",
756 			    pi->pi_name);
757 		}
758 		return (TIMER_INFINITY);
759 	}
760 
761 	switch (event) {
762 	case ADV_OFF:
763 		pi->pi_adv_state = NO_ADV;
764 		return (TIMER_INFINITY);
765 
766 	case START_INIT_ADV:
767 		if (pi->pi_adv_state == INIT_ADV)
768 			return (pi->pi_adv_time_left);
769 		pi->pi_adv_count = ND_MAX_INITIAL_RTR_ADVERTISEMENTS;
770 		pi->pi_adv_time_left = 0;
771 		pi->pi_adv_state = INIT_ADV;
772 		break;	/* send advertisement */
773 
774 	case START_FINAL_ADV:
775 		if (pi->pi_adv_state == NO_ADV)
776 			return (TIMER_INFINITY);
777 		if (pi->pi_adv_state == FINAL_ADV)
778 			return (pi->pi_adv_time_left);
779 		pi->pi_adv_count = ND_MAX_FINAL_RTR_ADVERTISEMENTS;
780 		pi->pi_adv_time_left = 0;
781 		pi->pi_adv_state = FINAL_ADV;
782 		break;	/* send advertisement */
783 
784 	case RECEIVED_SOLICIT:
785 		if (pi->pi_adv_state == NO_ADV)
786 			return (TIMER_INFINITY);
787 		if (pi->pi_adv_state == SOLICIT_ADV) {
788 			if (pi->pi_adv_time_left != 0)
789 				return (pi->pi_adv_time_left);
790 			break;
791 		}
792 		delay = GET_RANDOM(0, ND_MAX_RA_DELAY_TIME);
793 		if (delay < pi->pi_adv_time_left)
794 			pi->pi_adv_time_left = delay;
795 		if (pi->pi_adv_time_since_sent < ND_MIN_DELAY_BETWEEN_RAS) {
796 			/*
797 			 * Send an advertisement (ND_MIN_DELAY_BETWEEN_RAS
798 			 * plus random delay) after the previous
799 			 * advertisement was sent.
800 			 */
801 			pi->pi_adv_time_left = delay +
802 			    ND_MIN_DELAY_BETWEEN_RAS -
803 			    pi->pi_adv_time_since_sent;
804 		}
805 		pi->pi_adv_state = SOLICIT_ADV;
806 		break;
807 
808 	case ADV_TIMER:
809 		if (pi->pi_adv_state == NO_ADV)
810 			return (TIMER_INFINITY);
811 		/* Decrease time left */
812 		if (pi->pi_adv_time_left >= elapsed)
813 			pi->pi_adv_time_left -= elapsed;
814 		else
815 			pi->pi_adv_time_left = 0;
816 
817 		/* Increase time since last advertisement was sent */
818 		pi->pi_adv_time_since_sent += elapsed;
819 		break;
820 	default:
821 		logmsg(LOG_ERR, "advertise_event: Unknown event %d\n",
822 		    (int)event);
823 		return (TIMER_INFINITY);
824 	}
825 
826 	if (pi->pi_adv_time_left != 0)
827 		return (pi->pi_adv_time_left);
828 
829 	/* Send advertisement and calculate next time to send */
830 	if (pi->pi_adv_state == FINAL_ADV) {
831 		/* Omit the prefixes */
832 		advertise(&v6allnodes, pi, _B_TRUE);
833 	} else {
834 		advertise(&v6allnodes, pi, _B_FALSE);
835 	}
836 	pi->pi_adv_time_since_sent = 0;
837 
838 	switch (pi->pi_adv_state) {
839 	case SOLICIT_ADV:
840 		/*
841 		 * The solicited advertisement has been sent.
842 		 * Revert to periodic advertisements.
843 		 */
844 		pi->pi_adv_state = REG_ADV;
845 		/* FALLTHRU */
846 	case REG_ADV:
847 		pi->pi_adv_time_left =
848 		    GET_RANDOM(1000 * pi->pi_MinRtrAdvInterval,
849 		    1000 * pi->pi_MaxRtrAdvInterval);
850 		break;
851 
852 	case INIT_ADV:
853 		if (--pi->pi_adv_count > 0) {
854 			delay = GET_RANDOM(1000 * pi->pi_MinRtrAdvInterval,
855 			    1000 * pi->pi_MaxRtrAdvInterval);
856 			if (delay > ND_MAX_INITIAL_RTR_ADVERT_INTERVAL)
857 				delay = ND_MAX_INITIAL_RTR_ADVERT_INTERVAL;
858 			pi->pi_adv_time_left = delay;
859 		} else {
860 			pi->pi_adv_time_left =
861 			    GET_RANDOM(1000 * pi->pi_MinRtrAdvInterval,
862 			    1000 * pi->pi_MaxRtrAdvInterval);
863 			pi->pi_adv_state = REG_ADV;
864 		}
865 		break;
866 
867 	case FINAL_ADV:
868 		if (--pi->pi_adv_count > 0) {
869 			pi->pi_adv_time_left =
870 			    ND_MAX_INITIAL_RTR_ADVERT_INTERVAL;
871 		} else {
872 			pi->pi_adv_state = NO_ADV;
873 		}
874 		break;
875 	}
876 	if (pi->pi_adv_state != NO_ADV)
877 		return (pi->pi_adv_time_left);
878 	else
879 		return (TIMER_INFINITY);
880 }
881 
882 /*
883  * Router solicitation state machine. Used for everything but timer
884  * events which use solicit_event directly.
885  */
886 void
887 check_to_solicit(struct phyint *pi, enum solicit_events event)
888 {
889 	uint_t delay;
890 	enum solicit_states old_state = pi->pi_sol_state;
891 
892 	if (debug & D_STATE) {
893 		logmsg(LOG_DEBUG, "check_to_solicit(%s, %d) state %d\n",
894 		    pi->pi_name, (int)event, (int)old_state);
895 	}
896 	delay = solicit_event(pi, event, 0);
897 	if (delay != TIMER_INFINITY) {
898 		/* Make sure the global next event is updated */
899 		timer_schedule(delay);
900 	}
901 
902 	if (debug & D_STATE) {
903 		logmsg(LOG_DEBUG, "check_to_solicit(%s, %d) state %d -> %d\n",
904 		    pi->pi_name, (int)event, (int)old_state,
905 		    (int)pi->pi_sol_state);
906 	}
907 }
908 
909 static void
910 daemonize_ndpd(void)
911 {
912 	struct itimerval it;
913 	boolean_t timerval = _B_TRUE;
914 
915 	/*
916 	 * Need to get current timer settings so they can be restored
917 	 * after the fork(), as the it_value and it_interval values for
918 	 * the ITIMER_REAL timer are reset to 0 in the child process.
919 	 */
920 	if (getitimer(ITIMER_REAL, &it) < 0) {
921 		if (debug & D_TIMER)
922 			logmsg(LOG_DEBUG,
923 			    "daemonize_ndpd: failed to get itimerval\n");
924 		timerval = _B_FALSE;
925 	}
926 
927 	/* Daemonize. */
928 	if (daemon(0, 0) == -1) {
929 		logperror("fork");
930 		exit(1);
931 	}
932 
933 	already_daemonized = _B_TRUE;
934 
935 	/*
936 	 * Restore timer values, if we were able to save them; if not,
937 	 * check and set the right value by calling run_timeouts().
938 	 */
939 	if (timerval) {
940 		if (setitimer(ITIMER_REAL, &it, NULL) < 0) {
941 			logperror("daemonize_ndpd: setitimer");
942 			exit(2);
943 		}
944 	} else {
945 		run_timeouts();
946 	}
947 }
948 
949 /*
950  * Check to see if the time is right to daemonize.  The right time is when:
951  *
952  * 1.  We haven't already daemonized.
953  * 2.  We are not in debug mode.
954  * 3.  All interfaces are marked IFF_NOXMIT.
955  * 4.  All non-router interfaces have their prefixes set up and we're
956  *     done sending router solicitations on those interfaces without
957  *     prefixes.
958  */
959 static void
960 check_daemonize(void)
961 {
962 	struct phyint		*pi;
963 
964 	if (already_daemonized || debug != 0)
965 		return;
966 
967 	for (pi = phyints; pi != NULL; pi = pi->pi_next) {
968 		if (!(pi->pi_flags & IFF_NOXMIT))
969 			break;
970 	}
971 
972 	/*
973 	 * If we can't transmit on any of the interfaces there is no reason
974 	 * to hold up progress.
975 	 */
976 	if (pi == NULL) {
977 		daemonize_ndpd();
978 		return;
979 	}
980 
981 	/* Check all interfaces.  If any are still soliciting, just return. */
982 	for (pi = phyints; pi != NULL; pi = pi->pi_next) {
983 		if (pi->pi_AdvSendAdvertisements ||
984 		    !(pi->pi_kernel_state & PI_PRESENT))
985 			continue;
986 
987 		if (pi->pi_sol_state == INIT_SOLICIT)
988 			return;
989 	}
990 
991 	daemonize_ndpd();
992 }
993 
994 /*
995  * Router solicitation state machine.
996  * Return the number of milliseconds until next timeout (TIMER_INFINITY
997  * if never).
998  * For the SOL_TIMER event the caller passes in the number of milliseconds
999  * since the last timer event in the 'elapsed' parameter.
1000  */
1001 uint_t
1002 solicit_event(struct phyint *pi, enum solicit_events event, uint_t elapsed)
1003 {
1004 	if (debug & D_STATE) {
1005 		logmsg(LOG_DEBUG, "solicit_event(%s, %d, %d) state %d\n",
1006 		    pi->pi_name, (int)event, elapsed, (int)pi->pi_sol_state);
1007 	}
1008 
1009 	if (pi->pi_AdvSendAdvertisements)
1010 		return (TIMER_INFINITY);
1011 	if (pi->pi_flags & IFF_NORTEXCH) {
1012 		if (debug & D_PKTOUT) {
1013 			logmsg(LOG_DEBUG, "Suppress sending RS packet on %s "
1014 			    "(no route exchange on interface)\n",
1015 			    pi->pi_name);
1016 		}
1017 		return (TIMER_INFINITY);
1018 	}
1019 
1020 	switch (event) {
1021 	case SOLICIT_OFF:
1022 		pi->pi_sol_state = NO_SOLICIT;
1023 		check_daemonize();
1024 		return (TIMER_INFINITY);
1025 
1026 	case SOLICIT_DONE:
1027 		pi->pi_sol_state = DONE_SOLICIT;
1028 		check_daemonize();
1029 		return (TIMER_INFINITY);
1030 
1031 	case RESTART_INIT_SOLICIT:
1032 		/*
1033 		 * This event allows us to start solicitation over again
1034 		 * without losing the RA flags.  We start solicitation over
1035 		 * when we are missing an interface prefix for a newly-
1036 		 * encountered DHCP interface.
1037 		 */
1038 		if (pi->pi_sol_state == INIT_SOLICIT)
1039 			return (pi->pi_sol_time_left);
1040 		pi->pi_sol_count = ND_MAX_RTR_SOLICITATIONS;
1041 		pi->pi_sol_time_left =
1042 		    GET_RANDOM(0, ND_MAX_RTR_SOLICITATION_DELAY);
1043 		pi->pi_sol_state = INIT_SOLICIT;
1044 		break;
1045 
1046 	case START_INIT_SOLICIT:
1047 		if (pi->pi_sol_state == INIT_SOLICIT)
1048 			return (pi->pi_sol_time_left);
1049 		pi->pi_ra_flags = 0;
1050 		pi->pi_sol_count = ND_MAX_RTR_SOLICITATIONS;
1051 		pi->pi_sol_time_left =
1052 		    GET_RANDOM(0, ND_MAX_RTR_SOLICITATION_DELAY);
1053 		pi->pi_sol_state = INIT_SOLICIT;
1054 		break;
1055 
1056 	case SOL_TIMER:
1057 		if (pi->pi_sol_state == NO_SOLICIT)
1058 			return (TIMER_INFINITY);
1059 		/* Decrease time left */
1060 		if (pi->pi_sol_time_left >= elapsed)
1061 			pi->pi_sol_time_left -= elapsed;
1062 		else
1063 			pi->pi_sol_time_left = 0;
1064 		break;
1065 	default:
1066 		logmsg(LOG_ERR, "solicit_event: Unknown event %d\n",
1067 		    (int)event);
1068 		return (TIMER_INFINITY);
1069 	}
1070 
1071 	if (pi->pi_sol_time_left != 0)
1072 		return (pi->pi_sol_time_left);
1073 
1074 	/* Send solicitation and calculate next time */
1075 	switch (pi->pi_sol_state) {
1076 	case INIT_SOLICIT:
1077 		solicit(&v6allrouters, pi);
1078 		if (--pi->pi_sol_count == 0) {
1079 			if (debug & D_STATE) {
1080 				logmsg(LOG_DEBUG, "solicit_event: no routers "
1081 				    "found on %s; assuming default flags\n",
1082 				    pi->pi_name);
1083 			}
1084 			if (pi->pi_autoconf && pi->pi_StatefulAddrConf) {
1085 				pi->pi_ra_flags |= ND_RA_FLAG_MANAGED |
1086 				    ND_RA_FLAG_OTHER;
1087 				start_dhcp(pi);
1088 			}
1089 			pi->pi_sol_state = DONE_SOLICIT;
1090 			check_daemonize();
1091 			return (TIMER_INFINITY);
1092 		}
1093 		pi->pi_sol_time_left = ND_RTR_SOLICITATION_INTERVAL;
1094 		return (pi->pi_sol_time_left);
1095 	case NO_SOLICIT:
1096 	case DONE_SOLICIT:
1097 		return (TIMER_INFINITY);
1098 	default:
1099 		return (pi->pi_sol_time_left);
1100 	}
1101 }
1102 
1103 /*
1104  * Timer mechanism using relative time (in milliseconds) from the
1105  * previous timer event. Timers exceeding TIMER_INFINITY milliseconds
1106  * will fire after TIMER_INFINITY milliseconds.
1107  */
1108 static uint_t timer_previous;	/* When last SIGALRM occurred */
1109 static uint_t timer_next;	/* Currently scheduled timeout */
1110 
1111 static void
1112 timer_init(void)
1113 {
1114 	timer_previous = getcurrenttime();
1115 	timer_next = TIMER_INFINITY;
1116 	run_timeouts();
1117 }
1118 
1119 /*
1120  * Make sure the next SIGALRM occurs delay milliseconds from the current
1121  * time if not earlier.
1122  * Handles getcurrenttime (32 bit integer holding milliseconds) wraparound
1123  * by treating differences greater than 0x80000000 as negative.
1124  */
1125 void
1126 timer_schedule(uint_t delay)
1127 {
1128 	uint_t now;
1129 	struct itimerval itimerval;
1130 
1131 	now = getcurrenttime();
1132 	if (debug & D_TIMER) {
1133 		logmsg(LOG_DEBUG, "timer_schedule(%u): now %u next %u\n",
1134 		    delay, now, timer_next);
1135 	}
1136 	/* Will this timer occur before the currently scheduled SIGALRM? */
1137 	if (delay >= timer_next - now) {
1138 		if (debug & D_TIMER) {
1139 			logmsg(LOG_DEBUG, "timer_schedule(%u): no action - "
1140 			    "next in %u ms\n",
1141 			    delay, timer_next - now);
1142 		}
1143 		return;
1144 	}
1145 	if (delay == 0) {
1146 		/* Minimum allowed delay */
1147 		delay = 1;
1148 	}
1149 	timer_next = now + delay;
1150 
1151 	itimerval.it_value.tv_sec = delay / 1000;
1152 	itimerval.it_value.tv_usec = (delay % 1000) * 1000;
1153 	itimerval.it_interval.tv_sec = 0;
1154 	itimerval.it_interval.tv_usec = 0;
1155 	if (debug & D_TIMER) {
1156 		logmsg(LOG_DEBUG, "timer_schedule(%u): sec %lu usec %lu\n",
1157 		    delay,
1158 		    itimerval.it_value.tv_sec, itimerval.it_value.tv_usec);
1159 	}
1160 	if (setitimer(ITIMER_REAL, &itimerval, NULL) < 0) {
1161 		logperror("timer_schedule: setitimer");
1162 		exit(2);
1163 	}
1164 }
1165 
1166 /*
1167  * Conditional running of timer. If more than 'minimal_time' millseconds
1168  * since the timer routines were last run we run them.
1169  * Used when packets arrive.
1170  */
1171 static void
1172 conditional_run_timeouts(uint_t minimal_time)
1173 {
1174 	uint_t now;
1175 	uint_t elapsed;
1176 
1177 	now = getcurrenttime();
1178 	elapsed = now - timer_previous;
1179 	if (elapsed > minimal_time) {
1180 		if (debug & D_TIMER) {
1181 			logmsg(LOG_DEBUG, "conditional_run_timeouts: "
1182 			    "elapsed %d\n", elapsed);
1183 		}
1184 		run_timeouts();
1185 	}
1186 }
1187 
1188 /*
1189  * Timer has fired.
1190  * Determine when the next timer event will occur by asking all
1191  * the timer routines.
1192  * Should not be called from a timer routine but in some cases this is
1193  * done because the code doesn't know that e.g. it was called from
1194  * ifconfig_timer(). In this case the nested run_timeouts will just return but
1195  * the running run_timeouts will ensure to call all the timer functions by
1196  * looping once more.
1197  */
1198 static void
1199 run_timeouts(void)
1200 {
1201 	uint_t now;
1202 	uint_t elapsed;
1203 	uint_t next;
1204 	uint_t nexti;
1205 	struct phyint *pi;
1206 	struct phyint *next_pi;
1207 	struct prefix *pr;
1208 	struct prefix *next_pr;
1209 	struct adv_prefix *adv_pr;
1210 	struct adv_prefix *next_adv_pr;
1211 	struct router *dr;
1212 	struct router *next_dr;
1213 	static boolean_t timeout_running;
1214 	static boolean_t do_retry;
1215 
1216 	if (timeout_running) {
1217 		if (debug & D_TIMER)
1218 			logmsg(LOG_DEBUG, "run_timeouts: nested call\n");
1219 		do_retry = _B_TRUE;
1220 		return;
1221 	}
1222 	timeout_running = _B_TRUE;
1223 retry:
1224 	/* How much time since the last time we were called? */
1225 	now = getcurrenttime();
1226 	elapsed = now - timer_previous;
1227 	timer_previous = now;
1228 
1229 	if (debug & D_TIMER)
1230 		logmsg(LOG_DEBUG, "run_timeouts: elapsed %d\n", elapsed);
1231 
1232 	next = TIMER_INFINITY;
1233 	for (pi = phyints; pi != NULL; pi = next_pi) {
1234 		next_pi = pi->pi_next;
1235 		nexti = phyint_timer(pi, elapsed);
1236 		if (nexti != TIMER_INFINITY && nexti < next)
1237 			next = nexti;
1238 		if (debug & D_TIMER) {
1239 			logmsg(LOG_DEBUG, "run_timeouts (pi %s): %d -> %u ms\n",
1240 			    pi->pi_name, nexti, next);
1241 		}
1242 		for (pr = pi->pi_prefix_list; pr != NULL; pr = next_pr) {
1243 			next_pr = pr->pr_next;
1244 			nexti = prefix_timer(pr, elapsed);
1245 			if (nexti != TIMER_INFINITY && nexti < next)
1246 				next = nexti;
1247 			if (debug & D_TIMER) {
1248 				logmsg(LOG_DEBUG, "run_timeouts (pr %s): "
1249 				    "%d -> %u ms\n", pr->pr_name, nexti, next);
1250 			}
1251 		}
1252 		for (adv_pr = pi->pi_adv_prefix_list; adv_pr != NULL;
1253 		    adv_pr = next_adv_pr) {
1254 			next_adv_pr = adv_pr->adv_pr_next;
1255 			nexti = adv_prefix_timer(adv_pr, elapsed);
1256 			if (nexti != TIMER_INFINITY && nexti < next)
1257 				next = nexti;
1258 			if (debug & D_TIMER) {
1259 				logmsg(LOG_DEBUG, "run_timeouts "
1260 				    "(adv pr on %s): %d -> %u ms\n",
1261 				    adv_pr->adv_pr_physical->pi_name,
1262 				    nexti, next);
1263 			}
1264 		}
1265 		for (dr = pi->pi_router_list; dr != NULL; dr = next_dr) {
1266 			next_dr = dr->dr_next;
1267 			nexti = router_timer(dr, elapsed);
1268 			if (nexti != TIMER_INFINITY && nexti < next)
1269 				next = nexti;
1270 			if (debug & D_TIMER) {
1271 				logmsg(LOG_DEBUG, "run_timeouts (dr): "
1272 				    "%d -> %u ms\n", nexti, next);
1273 			}
1274 		}
1275 		if (pi->pi_TmpAddrsEnabled) {
1276 			nexti = tmptoken_timer(pi, elapsed);
1277 			if (nexti != TIMER_INFINITY && nexti < next)
1278 				next = nexti;
1279 			if (debug & D_TIMER) {
1280 				logmsg(LOG_DEBUG, "run_timeouts (tmp on %s): "
1281 				    "%d -> %u ms\n", pi->pi_name, nexti, next);
1282 			}
1283 		}
1284 	}
1285 	/*
1286 	 * Make sure the timer functions are run at least once
1287 	 * an hour.
1288 	 */
1289 	if (next == TIMER_INFINITY)
1290 		next = 3600 * 1000;	/* 1 hour */
1291 
1292 	if (debug & D_TIMER)
1293 		logmsg(LOG_DEBUG, "run_timeouts: %u ms\n", next);
1294 	timer_schedule(next);
1295 	if (do_retry) {
1296 		if (debug & D_TIMER)
1297 			logmsg(LOG_DEBUG, "run_timeouts: retry\n");
1298 		do_retry = _B_FALSE;
1299 		goto retry;
1300 	}
1301 	timeout_running = _B_FALSE;
1302 }
1303 
1304 static int eventpipe_read = -1;	/* Used for synchronous signal delivery */
1305 static int eventpipe_write = -1;
1306 
1307 /*
1308  * Ensure that signals are processed synchronously with the rest of
1309  * the code by just writing a one character signal number on the pipe.
1310  * The poll loop will pick this up and process the signal event.
1311  */
1312 static void
1313 sig_handler(int signo)
1314 {
1315 	uchar_t buf = (uchar_t)signo;
1316 
1317 	if (eventpipe_write == -1) {
1318 		logmsg(LOG_ERR, "sig_handler: no pipe\n");
1319 		return;
1320 	}
1321 	if (write(eventpipe_write, &buf, sizeof (buf)) < 0)
1322 		logperror("sig_handler: write");
1323 }
1324 
1325 /*
1326  * Pick up a signal "byte" from the pipe and process it.
1327  */
1328 static void
1329 in_signal(int fd)
1330 {
1331 	uchar_t buf;
1332 	struct phyint *pi;
1333 	struct phyint *next_pi;
1334 
1335 	switch (read(fd, &buf, sizeof (buf))) {
1336 	case -1:
1337 		logperror("in_signal: read");
1338 		exit(1);
1339 		/* NOTREACHED */
1340 	case 1:
1341 		break;
1342 	case 0:
1343 		logmsg(LOG_ERR, "in_signal: read eof\n");
1344 		exit(1);
1345 		/* NOTREACHED */
1346 	default:
1347 		logmsg(LOG_ERR, "in_signal: read > 1\n");
1348 		exit(1);
1349 	}
1350 
1351 	if (debug & D_TIMER)
1352 		logmsg(LOG_DEBUG, "in_signal() got %d\n", buf);
1353 
1354 	switch (buf) {
1355 	case SIGALRM:
1356 		if (debug & D_TIMER) {
1357 			uint_t now = getcurrenttime();
1358 
1359 			logmsg(LOG_DEBUG, "in_signal(SIGALRM) delta %u\n",
1360 			    now - timer_next);
1361 		}
1362 		timer_next = TIMER_INFINITY;
1363 		run_timeouts();
1364 		break;
1365 	case SIGHUP:
1366 		/* Re-read config file by exec'ing ourselves */
1367 		for (pi = phyints; pi != NULL; pi = next_pi) {
1368 			next_pi = pi->pi_next;
1369 			if (pi->pi_AdvSendAdvertisements)
1370 				check_to_advertise(pi, START_FINAL_ADV);
1371 
1372 			/*
1373 			 * Remove all the configured addresses.
1374 			 * Remove the addrobj names created with ipmgmtd.
1375 			 * Release the dhcpv6 addresses if any.
1376 			 * Cleanup the phyints.
1377 			 */
1378 			phyint_delete(pi);
1379 		}
1380 
1381 		/*
1382 		 * Prevent fd leaks.  Everything gets re-opened at start-up
1383 		 * time.  0, 1, and 2 are closed and re-opened as
1384 		 * /dev/null, so we'll leave those open.
1385 		 */
1386 		closefrom(3);
1387 
1388 		logmsg(LOG_ERR, "SIGHUP: restart and reread config file\n");
1389 		(void) execv(argv0[0], argv0);
1390 		_exit(0177);
1391 		/* NOTREACHED */
1392 	case SIGUSR1:
1393 		logmsg(LOG_DEBUG, "Printing configuration:\n");
1394 		phyint_print_all();
1395 		break;
1396 	case SIGINT:
1397 	case SIGTERM:
1398 	case SIGQUIT:
1399 		for (pi = phyints; pi != NULL; pi = next_pi) {
1400 			next_pi = pi->pi_next;
1401 			if (pi->pi_AdvSendAdvertisements)
1402 				check_to_advertise(pi, START_FINAL_ADV);
1403 
1404 			phyint_delete(pi);
1405 		}
1406 		(void) unlink(NDPD_SNMP_SOCKET);
1407 		exit(0);
1408 		/* NOTREACHED */
1409 	case 255:
1410 		/*
1411 		 * Special "signal" from loopback_ra_enqueue.
1412 		 * Handle any queued loopback router advertisements.
1413 		 */
1414 		loopback_ra_dequeue();
1415 		break;
1416 	default:
1417 		logmsg(LOG_ERR, "in_signal: unknown signal: %d\n", buf);
1418 	}
1419 }
1420 
1421 /*
1422  * Create pipe for signal delivery and set up signal handlers.
1423  */
1424 static void
1425 setup_eventpipe(void)
1426 {
1427 	int fds[2];
1428 	struct sigaction act;
1429 
1430 	if ((pipe(fds)) < 0) {
1431 		logperror("setup_eventpipe: pipe");
1432 		exit(1);
1433 	}
1434 	eventpipe_read = fds[0];
1435 	eventpipe_write = fds[1];
1436 	if (poll_add(eventpipe_read) == -1) {
1437 		exit(1);
1438 	}
1439 	act.sa_handler = sig_handler;
1440 	act.sa_flags = SA_RESTART;
1441 	(void) sigaction(SIGALRM, &act, NULL);
1442 
1443 	(void) sigset(SIGHUP, sig_handler);
1444 	(void) sigset(SIGUSR1, sig_handler);
1445 	(void) sigset(SIGTERM, sig_handler);
1446 	(void) sigset(SIGINT, sig_handler);
1447 	(void) sigset(SIGQUIT, sig_handler);
1448 }
1449 
1450 /*
1451  * Create a routing socket for receiving RTM_IFINFO messages and initialize
1452  * the routing socket message header and as much of the sockaddrs as possible.
1453  */
1454 static int
1455 setup_rtsock(void)
1456 {
1457 	int s;
1458 	int ret;
1459 	char *cp;
1460 	struct sockaddr_in6 *sin6;
1461 
1462 	s = socket(PF_ROUTE, SOCK_RAW, AF_INET6);
1463 	if (s == -1) {
1464 		logperror("socket(PF_ROUTE)");
1465 		exit(1);
1466 	}
1467 	ret = fcntl(s, F_SETFL, O_NDELAY|O_NONBLOCK);
1468 	if (ret < 0) {
1469 		logperror("fcntl(O_NDELAY)");
1470 		exit(1);
1471 	}
1472 	if (poll_add(s) == -1) {
1473 		exit(1);
1474 	}
1475 
1476 	/*
1477 	 * Allocate storage for the routing socket message.
1478 	 */
1479 	rt_msg = (struct rt_msghdr *)malloc(NDP_RTM_MSGLEN);
1480 	if (rt_msg == NULL) {
1481 		logperror("malloc");
1482 		exit(1);
1483 	}
1484 
1485 	/*
1486 	 * Initialize the routing socket message by zero-filling it and then
1487 	 * setting the fields where are constant through the lifetime of the
1488 	 * process.
1489 	 */
1490 	bzero(rt_msg, NDP_RTM_MSGLEN);
1491 	rt_msg->rtm_msglen = NDP_RTM_MSGLEN;
1492 	rt_msg->rtm_version = RTM_VERSION;
1493 	rt_msg->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_IFP;
1494 	rt_msg->rtm_pid = getpid();
1495 	if (rt_msg->rtm_pid < 0) {
1496 		logperror("getpid");
1497 		exit(1);
1498 	}
1499 
1500 	/*
1501 	 * The RTA_DST sockaddr does not change during the lifetime of the
1502 	 * process so it can be completely initialized at this time.
1503 	 */
1504 	cp = (char *)rt_msg + sizeof (struct rt_msghdr);
1505 	sin6 = (struct sockaddr_in6 *)cp;
1506 	sin6->sin6_family = AF_INET6;
1507 	sin6->sin6_addr = in6addr_any;
1508 
1509 	/*
1510 	 * Initialize the constant portion of the RTA_GATEWAY sockaddr.
1511 	 */
1512 	cp += sizeof (struct sockaddr_in6);
1513 	rta_gateway = (struct sockaddr_in6 *)cp;
1514 	rta_gateway->sin6_family = AF_INET6;
1515 
1516 	/*
1517 	 * The RTA_NETMASK sockaddr does not change during the lifetime of the
1518 	 * process so it can be completely initialized at this time.
1519 	 */
1520 	cp += sizeof (struct sockaddr_in6);
1521 	sin6 = (struct sockaddr_in6 *)cp;
1522 	sin6->sin6_family = AF_INET6;
1523 	sin6->sin6_addr = in6addr_any;
1524 
1525 	/*
1526 	 * Initialize the constant portion of the RTA_IFP sockaddr.
1527 	 */
1528 	cp += sizeof (struct sockaddr_in6);
1529 	rta_ifp = (struct sockaddr_dl *)cp;
1530 	rta_ifp->sdl_family = AF_LINK;
1531 
1532 	return (s);
1533 }
1534 
1535 static int
1536 setup_mibsock(void)
1537 {
1538 	int sock;
1539 	int ret;
1540 	int len;
1541 	struct sockaddr_un laddr;
1542 
1543 	sock = socket(AF_UNIX, SOCK_DGRAM, 0);
1544 	if (sock == -1) {
1545 		logperror("setup_mibsock: socket(AF_UNIX)");
1546 		exit(1);
1547 	}
1548 
1549 	bzero(&laddr, sizeof (laddr));
1550 	laddr.sun_family = AF_UNIX;
1551 
1552 	(void) strncpy(laddr.sun_path, NDPD_SNMP_SOCKET,
1553 	    sizeof (laddr.sun_path));
1554 	len = sizeof (struct sockaddr_un);
1555 
1556 	(void) unlink(NDPD_SNMP_SOCKET);
1557 	ret = bind(sock, (struct sockaddr *)&laddr, len);
1558 	if (ret < 0) {
1559 		logperror("setup_mibsock: bind\n");
1560 		exit(1);
1561 	}
1562 
1563 	ret = fcntl(sock, F_SETFL, O_NONBLOCK);
1564 	if (ret < 0) {
1565 		logperror("fcntl(O_NONBLOCK)");
1566 		exit(1);
1567 	}
1568 	if (poll_add(sock) == -1) {
1569 		exit(1);
1570 	}
1571 	return (sock);
1572 }
1573 
1574 /*
1575  * Retrieve one routing socket message. If RTM_IFINFO indicates
1576  * new phyint do a full scan of the interfaces. If RTM_IFINFO
1577  * indicates an existing phyint, only scan that phyint and associated
1578  * prefixes.
1579  */
1580 static void
1581 process_rtsock(int rtsock)
1582 {
1583 	int n;
1584 #define	MSG_SIZE	2048/8
1585 	int64_t msg[MSG_SIZE];
1586 	struct rt_msghdr *rtm;
1587 	struct if_msghdr *ifm;
1588 	struct phyint *pi;
1589 	struct prefix *pr;
1590 	boolean_t need_initifs = _B_FALSE;
1591 	boolean_t need_ifscan = _B_FALSE;
1592 	int64_t	ifscan_msg[10][MSG_SIZE];
1593 	int ifscan_index = 0;
1594 	int i;
1595 
1596 	/* Empty the rtsock and coealesce all the work that we have */
1597 	while (ifscan_index < 10) {
1598 		n = read(rtsock, msg, sizeof (msg));
1599 		if (n <= 0) {
1600 			/* No more messages */
1601 			break;
1602 		}
1603 		rtm = (struct rt_msghdr *)msg;
1604 		if (rtm->rtm_version != RTM_VERSION) {
1605 			logmsg(LOG_ERR,
1606 			    "process_rtsock: version %d not understood\n",
1607 			    rtm->rtm_version);
1608 			return;
1609 		}
1610 		switch (rtm->rtm_type) {
1611 		case RTM_NEWADDR:
1612 		case RTM_DELADDR:
1613 			/*
1614 			 * Some logical interface has changed - have to scan
1615 			 * everything to determine what actually changed.
1616 			 */
1617 			if (debug & D_IFSCAN) {
1618 				logmsg(LOG_DEBUG, "process_rtsock: "
1619 				    "message %d\n", rtm->rtm_type);
1620 			}
1621 			need_initifs = _B_TRUE;
1622 			break;
1623 		case RTM_IFINFO:
1624 			need_ifscan = _B_TRUE;
1625 			(void) memcpy(ifscan_msg[ifscan_index], rtm,
1626 			    sizeof (msg));
1627 			ifscan_index++;
1628 			/* Handled below */
1629 			break;
1630 		default:
1631 			/* Not interesting */
1632 			break;
1633 		}
1634 	}
1635 	/*
1636 	 * If we do full scan i.e initifs, we don't need to
1637 	 * scan a particular interface as we should have
1638 	 * done that as part of initifs.
1639 	 */
1640 	if (need_initifs) {
1641 		initifs(_B_FALSE);
1642 		return;
1643 	}
1644 
1645 	if (!need_ifscan)
1646 		return;
1647 
1648 	for (i = 0; i < ifscan_index; i++) {
1649 		ifm = (struct if_msghdr *)ifscan_msg[i];
1650 		if (debug & D_IFSCAN)
1651 			logmsg(LOG_DEBUG, "process_rtsock: index %d\n",
1652 			    ifm->ifm_index);
1653 
1654 		pi = phyint_lookup_on_index(ifm->ifm_index);
1655 		if (pi == NULL) {
1656 			/*
1657 			 * A new physical interface. Do a full scan of the
1658 			 * to catch any new logical interfaces.
1659 			 */
1660 			initifs(_B_FALSE);
1661 			return;
1662 		}
1663 
1664 		if (ifm->ifm_flags != (uint_t)pi->pi_flags) {
1665 			if (debug & D_IFSCAN) {
1666 				logmsg(LOG_DEBUG, "process_rtsock: clr for "
1667 				    "%s old flags 0x%llx new flags 0x%x\n",
1668 				    pi->pi_name, pi->pi_flags, ifm->ifm_flags);
1669 			}
1670 		}
1671 
1672 
1673 		/*
1674 		 * Mark the interfaces so that we can find phyints and prefixes
1675 		 * which have disappeared from the kernel.
1676 		 * if_process will set pr_in_use when it finds the
1677 		 * interface in the kernel.
1678 		 * Before re-examining the state of the interfaces,
1679 		 * PI_PRESENT should be cleared from pi_kernel_state.
1680 		 */
1681 		pi->pi_kernel_state &= ~PI_PRESENT;
1682 		for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) {
1683 			pr->pr_in_use = _B_FALSE;
1684 		}
1685 
1686 		if (ifsock < 0) {
1687 			ifsock = socket(AF_INET6, SOCK_DGRAM, 0);
1688 			if (ifsock < 0) {
1689 				logperror("process_rtsock: socket");
1690 				return;
1691 			}
1692 		}
1693 		if_process(ifsock, pi->pi_name, _B_FALSE);
1694 		for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) {
1695 			if_process(ifsock, pr->pr_name, _B_FALSE);
1696 		}
1697 		/*
1698 		 * If interface (still) exists in kernel, set
1699 		 * pi_state to indicate that.
1700 		 */
1701 		if (pi->pi_kernel_state & PI_PRESENT) {
1702 			pi->pi_state |= PI_PRESENT;
1703 		}
1704 		check_if_removed(pi);
1705 		if (show_ifs)
1706 			phyint_print_all();
1707 	}
1708 }
1709 
1710 static void
1711 process_mibsock(int mibsock)
1712 {
1713 	struct phyint *pi;
1714 	socklen_t fromlen;
1715 	struct sockaddr_un from;
1716 	ndpd_info_t ndpd_info;
1717 	ssize_t len;
1718 	int command;
1719 
1720 	fromlen = (socklen_t)sizeof (from);
1721 	len = recvfrom(mibsock, &command, sizeof (int), 0,
1722 	    (struct sockaddr *)&from, &fromlen);
1723 
1724 	if (len < sizeof (int) || command != NDPD_SNMP_INFO_REQ) {
1725 		logperror("process_mibsock: bad command \n");
1726 		return;
1727 	}
1728 
1729 	ndpd_info.info_type = NDPD_SNMP_INFO_RESPONSE;
1730 	ndpd_info.info_version = NDPD_SNMP_INFO_VER;
1731 	ndpd_info.info_num_of_phyints = num_of_phyints;
1732 
1733 	(void) sendto(mibsock, &ndpd_info, sizeof (ndpd_info_t), 0,
1734 	    (struct sockaddr *)&from, fromlen);
1735 
1736 	for (pi = phyints; pi != NULL; pi = pi->pi_next) {
1737 		int prefixes;
1738 		int routers;
1739 		struct prefix   *prefix_list;
1740 		struct router   *router_list;
1741 		ndpd_phyint_info_t phyint;
1742 		ndpd_prefix_info_t prefix;
1743 		ndpd_router_info_t router;
1744 		/*
1745 		 * get number of prefixes
1746 		 */
1747 		routers = 0;
1748 		prefixes = 0;
1749 		prefix_list = pi->pi_prefix_list;
1750 		while (prefix_list != NULL) {
1751 			prefixes++;
1752 			prefix_list = prefix_list->pr_next;
1753 		}
1754 
1755 		/*
1756 		 * get number of routers
1757 		 */
1758 		router_list = pi->pi_router_list;
1759 		while (router_list != NULL) {
1760 			routers++;
1761 			router_list = router_list->dr_next;
1762 		}
1763 
1764 		phyint.phyint_info_type = NDPD_PHYINT_INFO;
1765 		phyint.phyint_info_version = NDPD_PHYINT_INFO_VER;
1766 		phyint.phyint_index = pi->pi_index;
1767 		bcopy(pi->pi_config,
1768 		    phyint.phyint_config, I_IFSIZE);
1769 		phyint.phyint_num_of_prefixes = prefixes;
1770 		phyint.phyint_num_of_routers = routers;
1771 		(void) sendto(mibsock, &phyint, sizeof (phyint), 0,
1772 		    (struct sockaddr *)&from, fromlen);
1773 
1774 		/*
1775 		 * Copy prefix information
1776 		 */
1777 
1778 		prefix_list = pi->pi_prefix_list;
1779 		while (prefix_list != NULL) {
1780 			prefix.prefix_info_type = NDPD_PREFIX_INFO;
1781 			prefix.prefix_info_version = NDPD_PREFIX_INFO_VER;
1782 			prefix.prefix_prefix = prefix_list->pr_prefix;
1783 			prefix.prefix_len = prefix_list->pr_prefix_len;
1784 			prefix.prefix_flags = prefix_list->pr_flags;
1785 			prefix.prefix_phyint_index = pi->pi_index;
1786 			prefix.prefix_ValidLifetime =
1787 			    prefix_list->pr_ValidLifetime;
1788 			prefix.prefix_PreferredLifetime =
1789 			    prefix_list->pr_PreferredLifetime;
1790 			prefix.prefix_OnLinkLifetime =
1791 			    prefix_list->pr_OnLinkLifetime;
1792 			prefix.prefix_OnLinkFlag =
1793 			    prefix_list->pr_OnLinkFlag;
1794 			prefix.prefix_AutonomousFlag =
1795 			    prefix_list->pr_AutonomousFlag;
1796 			(void) sendto(mibsock, &prefix, sizeof (prefix), 0,
1797 			    (struct sockaddr *)&from, fromlen);
1798 			prefix_list = prefix_list->pr_next;
1799 		}
1800 		/*
1801 		 * Copy router information
1802 		 */
1803 		router_list = pi->pi_router_list;
1804 		while (router_list != NULL) {
1805 			router.router_info_type = NDPD_ROUTER_INFO;
1806 			router.router_info_version = NDPD_ROUTER_INFO_VER;
1807 			router.router_address = router_list->dr_address;
1808 			router.router_lifetime = router_list->dr_lifetime;
1809 			router.router_phyint_index = pi->pi_index;
1810 			(void) sendto(mibsock, &router, sizeof (router), 0,
1811 			    (struct sockaddr *)&from, fromlen);
1812 			router_list = router_list->dr_next;
1813 		}
1814 	}
1815 }
1816 
1817 /*
1818  * Look if the phyint or one of its prefixes have been removed from
1819  * the kernel and take appropriate action.
1820  * Uses pr_in_use and pi{,_kernel}_state.
1821  */
1822 static void
1823 check_if_removed(struct phyint *pi)
1824 {
1825 	struct prefix *pr, *next_pr;
1826 
1827 	/*
1828 	 * Detect prefixes which are removed.
1829 	 * Static prefixes are just removed from our tables.
1830 	 * Non-static prefixes are recreated i.e. in.ndpd takes precedence
1831 	 * over manually removing prefixes via ifconfig.
1832 	 */
1833 	for (pr = pi->pi_prefix_list; pr != NULL; pr = next_pr) {
1834 		next_pr = pr->pr_next;
1835 		if (!pr->pr_in_use) {
1836 			/* Clear everything except PR_STATIC */
1837 			pr->pr_kernel_state &= PR_STATIC;
1838 			if (pr->pr_state & PR_STATIC)
1839 				prefix_update_ipadm_addrobj(pr, _B_FALSE);
1840 			pr->pr_name[0] = '\0';
1841 			if (pr->pr_state & PR_STATIC) {
1842 				prefix_delete(pr);
1843 			} else if (!(pi->pi_kernel_state & PI_PRESENT)) {
1844 				/*
1845 				 * Ensure that there are no future attempts to
1846 				 * run prefix_update_k since the phyint is gone.
1847 				 */
1848 				pr->pr_state = pr->pr_kernel_state;
1849 			} else if (pr->pr_state != pr->pr_kernel_state) {
1850 				logmsg(LOG_INFO, "Prefix manually removed "
1851 				    "on %s; recreating\n", pi->pi_name);
1852 				prefix_update_k(pr);
1853 			}
1854 		}
1855 	}
1856 
1857 	/*
1858 	 * Detect phyints that have been removed from the kernel, and tear
1859 	 * down any prefixes we created that are associated with that phyint.
1860 	 * (NOTE: IPMP depends on in.ndpd tearing down these prefixes so an
1861 	 * administrator can easily place an IP interface with ADDRCONF'd
1862 	 * addresses into an IPMP group.)
1863 	 */
1864 	if (!(pi->pi_kernel_state & PI_PRESENT) &&
1865 	    (pi->pi_state & PI_PRESENT)) {
1866 		logmsg(LOG_ERR, "Interface %s has been removed from kernel. "
1867 		    "in.ndpd will no longer use it\n", pi->pi_name);
1868 
1869 		for (pr = pi->pi_prefix_list; pr != NULL; pr = next_pr) {
1870 			next_pr = pr->pr_next;
1871 			if (pr->pr_state & PR_AUTO)
1872 				prefix_update_ipadm_addrobj(pr, _B_FALSE);
1873 			prefix_delete(pr);
1874 		}
1875 
1876 		/*
1877 		 * Clear state so that should the phyint reappear we will
1878 		 * start with initial advertisements or solicitations.
1879 		 */
1880 		phyint_cleanup(pi);
1881 	}
1882 }
1883 
1884 
1885 /*
1886  * Queuing mechanism for router advertisements that are sent by in.ndpd
1887  * and that also need to be processed by in.ndpd.
1888  * Uses "signal number" 255 to indicate to the main poll loop
1889  * that there is something to dequeue and send to incomining_ra().
1890  */
1891 struct raq {
1892 	struct raq	*raq_next;
1893 	struct phyint	*raq_pi;
1894 	int		raq_packetlen;
1895 	uchar_t		*raq_packet;
1896 };
1897 static struct raq *raq_head = NULL;
1898 
1899 /*
1900  * Allocate a struct raq and memory for the packet.
1901  * Send signal 255 to have poll dequeue.
1902  */
1903 static void
1904 loopback_ra_enqueue(struct phyint *pi, struct nd_router_advert *ra, int len)
1905 {
1906 	struct raq *raq;
1907 	struct raq **raqp;
1908 
1909 	if (no_loopback)
1910 		return;
1911 
1912 	if (debug & D_PKTOUT)
1913 		logmsg(LOG_DEBUG, "loopback_ra_enqueue for %s\n", pi->pi_name);
1914 
1915 	raq = calloc(sizeof (struct raq), 1);
1916 	if (raq == NULL) {
1917 		logmsg(LOG_ERR, "loopback_ra_enqueue: out of memory\n");
1918 		return;
1919 	}
1920 	raq->raq_packet = malloc(len);
1921 	if (raq->raq_packet == NULL) {
1922 		free(raq);
1923 		logmsg(LOG_ERR, "loopback_ra_enqueue: out of memory\n");
1924 		return;
1925 	}
1926 	bcopy(ra, raq->raq_packet, len);
1927 	raq->raq_packetlen = len;
1928 	raq->raq_pi = pi;
1929 
1930 	/* Tail insert */
1931 	raqp = &raq_head;
1932 	while (*raqp != NULL)
1933 		raqp = &((*raqp)->raq_next);
1934 	*raqp = raq;
1935 
1936 	/* Signal for poll loop */
1937 	sig_handler(255);
1938 }
1939 
1940 /*
1941  * Dequeue and process all queued advertisements.
1942  */
1943 static void
1944 loopback_ra_dequeue(void)
1945 {
1946 	struct sockaddr_in6 from = IN6ADDR_LOOPBACK_INIT;
1947 	struct raq *raq;
1948 
1949 	if (debug & D_PKTIN)
1950 		logmsg(LOG_DEBUG, "loopback_ra_dequeue()\n");
1951 
1952 	while ((raq = raq_head) != NULL) {
1953 		raq_head = raq->raq_next;
1954 		raq->raq_next = NULL;
1955 
1956 		if (debug & D_PKTIN) {
1957 			logmsg(LOG_DEBUG, "loopback_ra_dequeue for %s\n",
1958 			    raq->raq_pi->pi_name);
1959 		}
1960 
1961 		incoming_ra(raq->raq_pi,
1962 		    (struct nd_router_advert *)raq->raq_packet,
1963 		    raq->raq_packetlen, &from, _B_TRUE);
1964 		free(raq->raq_packet);
1965 		free(raq);
1966 	}
1967 }
1968 
1969 
1970 static void
1971 usage(char *cmd)
1972 {
1973 	(void) fprintf(stderr,
1974 	    "usage: %s [ -adt ] [-f <config file>]\n", cmd);
1975 }
1976 
1977 int
1978 main(int argc, char *argv[])
1979 {
1980 	int i;
1981 	struct phyint *pi;
1982 	int c;
1983 	char *config_file = PATH_NDPD_CONF;
1984 	boolean_t file_required = _B_FALSE;
1985 
1986 	argv0 = argv;
1987 	srandom(gethostid());
1988 	(void) umask(0022);
1989 
1990 	while ((c = getopt(argc, argv, "adD:ntIf:")) != EOF) {
1991 		switch (c) {
1992 		case 'a':
1993 			/*
1994 			 * The StatelessAddrConf variable in ndpd.conf, if
1995 			 * present, will override this setting.
1996 			 */
1997 			ifdefaults[I_StatelessAddrConf].cf_value = 0;
1998 			break;
1999 		case 'd':
2000 			debug = D_ALL;
2001 			break;
2002 		case 'D':
2003 			i = strtol((char *)optarg, NULL, 0);
2004 			if (i == 0) {
2005 				(void) fprintf(stderr, "Bad debug flags: %s\n",
2006 				    (char *)optarg);
2007 				exit(1);
2008 			}
2009 			debug |= i;
2010 			break;
2011 		case 'n':
2012 			no_loopback = 1;
2013 			break;
2014 		case 'I':
2015 			show_ifs = 1;
2016 			break;
2017 		case 't':
2018 			debug |= D_PKTIN | D_PKTOUT | D_PKTBAD;
2019 			break;
2020 		case 'f':
2021 			config_file = (char *)optarg;
2022 			file_required = _B_TRUE;
2023 			break;
2024 		case '?':
2025 			usage(argv[0]);
2026 			exit(1);
2027 		}
2028 	}
2029 
2030 	if (parse_config(config_file, file_required) == -1)
2031 		exit(2);
2032 
2033 	if (show_ifs)
2034 		phyint_print_all();
2035 
2036 	if (debug == 0)
2037 		initlog();
2038 
2039 	cmdsock = ndpd_setup_cmd_listener();
2040 	setup_eventpipe();
2041 	rtsock = setup_rtsock();
2042 	mibsock = setup_mibsock();
2043 	timer_init();
2044 	initifs(_B_TRUE);
2045 
2046 	check_daemonize();
2047 
2048 	for (;;) {
2049 		if (poll(pollfds, pollfd_num, -1) < 0) {
2050 			if (errno == EINTR)
2051 				continue;
2052 			logperror("main: poll");
2053 			exit(1);
2054 		}
2055 		for (i = 0; i < pollfd_num; i++) {
2056 			if (!(pollfds[i].revents & POLLIN))
2057 				continue;
2058 			if (pollfds[i].fd == eventpipe_read) {
2059 				in_signal(eventpipe_read);
2060 				break;
2061 			}
2062 			if (pollfds[i].fd == rtsock) {
2063 				process_rtsock(rtsock);
2064 				break;
2065 			}
2066 			if (pollfds[i].fd == mibsock) {
2067 				process_mibsock(mibsock);
2068 				break;
2069 			}
2070 			if (pollfds[i].fd == cmdsock) {
2071 				ndpd_cmd_handler(cmdsock);
2072 				break;
2073 			}
2074 			/*
2075 			 * Run timer routine to advance clock if more than
2076 			 * half a second since the clock was advanced.
2077 			 * This limits CPU usage under severe packet
2078 			 * arrival rates but it creates a slight inaccuracy
2079 			 * in the timer mechanism.
2080 			 */
2081 			conditional_run_timeouts(500U);
2082 			for (pi = phyints; pi != NULL; pi = pi->pi_next) {
2083 				if (pollfds[i].fd == pi->pi_sock) {
2084 					in_data(pi);
2085 					break;
2086 				}
2087 			}
2088 		}
2089 	}
2090 	/* NOTREACHED */
2091 	return (0);
2092 }
2093 
2094 /*
2095  * LOGGER
2096  */
2097 
2098 static boolean_t logging = _B_FALSE;
2099 
2100 static void
2101 initlog(void)
2102 {
2103 	logging = _B_TRUE;
2104 	openlog("in.ndpd", LOG_PID | LOG_CONS, LOG_DAEMON);
2105 }
2106 
2107 /* Print the date/time without a trailing carridge return */
2108 static void
2109 fprintdate(FILE *file)
2110 {
2111 	char buf[BUFSIZ];
2112 	struct tm tms;
2113 	time_t now;
2114 
2115 	now = time(NULL);
2116 	(void) localtime_r(&now, &tms);
2117 	(void) strftime(buf, sizeof (buf), "%h %d %X", &tms);
2118 	(void) fprintf(file, "%s ", buf);
2119 }
2120 
2121 /* PRINTFLIKE2 */
2122 void
2123 logmsg(int level, const char *fmt, ...)
2124 {
2125 	va_list ap;
2126 	va_start(ap, fmt);
2127 
2128 	if (logging) {
2129 		vsyslog(level, fmt, ap);
2130 	} else {
2131 		fprintdate(stderr);
2132 		(void) vfprintf(stderr, fmt, ap);
2133 	}
2134 	va_end(ap);
2135 }
2136 
2137 void
2138 logperror(const char *str)
2139 {
2140 	if (logging) {
2141 		syslog(LOG_ERR, "%s: %m\n", str);
2142 	} else {
2143 		fprintdate(stderr);
2144 		(void) fprintf(stderr, "%s: %s\n", str, strerror(errno));
2145 	}
2146 }
2147 
2148 void
2149 logperror_pi(const struct phyint *pi, const char *str)
2150 {
2151 	if (logging) {
2152 		syslog(LOG_ERR, "%s (interface %s): %m\n",
2153 		    str, pi->pi_name);
2154 	} else {
2155 		fprintdate(stderr);
2156 		(void) fprintf(stderr, "%s (interface %s): %s\n",
2157 		    str, pi->pi_name, strerror(errno));
2158 	}
2159 }
2160 
2161 void
2162 logperror_pr(const struct prefix *pr, const char *str)
2163 {
2164 	if (logging) {
2165 		syslog(LOG_ERR, "%s (prefix %s if %s): %m\n",
2166 		    str, pr->pr_name, pr->pr_physical->pi_name);
2167 	} else {
2168 		fprintdate(stderr);
2169 		(void) fprintf(stderr, "%s (prefix %s if %s): %s\n",
2170 		    str, pr->pr_name, pr->pr_physical->pi_name,
2171 		    strerror(errno));
2172 	}
2173 }
2174 
2175 static int
2176 ndpd_setup_cmd_listener(void)
2177 {
2178 	int sock;
2179 	int ret;
2180 	struct sockaddr_un servaddr;
2181 
2182 	sock = socket(AF_UNIX, SOCK_STREAM, 0);
2183 	if (sock < 0) {
2184 		logperror("socket");
2185 		exit(1);
2186 	}
2187 
2188 	bzero(&servaddr, sizeof (servaddr));
2189 	servaddr.sun_family = AF_UNIX;
2190 	(void) strlcpy(servaddr.sun_path, IPADM_UDS_PATH,
2191 	    sizeof (servaddr.sun_path));
2192 	(void) unlink(servaddr.sun_path);
2193 	ret = bind(sock, (struct sockaddr *)&servaddr, sizeof (servaddr));
2194 	if (ret < 0) {
2195 		logperror("bind");
2196 		exit(1);
2197 	}
2198 	if (listen(sock, 30) < 0) {
2199 		logperror("listen");
2200 		exit(1);
2201 	}
2202 	if (poll_add(sock) == -1) {
2203 		logmsg(LOG_ERR, "command socket could not be added to the "
2204 		    "polling set\n");
2205 		exit(1);
2206 	}
2207 
2208 	return (sock);
2209 }
2210 
2211 /*
2212  * Commands received over the command socket come here
2213  */
2214 static void
2215 ndpd_cmd_handler(int sock)
2216 {
2217 	int			newfd;
2218 	struct sockaddr_storage	peer;
2219 	socklen_t		peerlen;
2220 	ipadm_ndpd_msg_t	ndpd_msg;
2221 	int			retval;
2222 
2223 	peerlen = sizeof (peer);
2224 	newfd = accept(sock, (struct sockaddr *)&peer, &peerlen);
2225 	if (newfd < 0) {
2226 		logperror("accept");
2227 		return;
2228 	}
2229 
2230 	retval = ipadm_ndpd_read(newfd, &ndpd_msg, sizeof (ndpd_msg));
2231 	if (retval != 0)
2232 		logperror("Could not read ndpd command");
2233 
2234 	retval = ndpd_process_cmd(newfd, &ndpd_msg);
2235 	if (retval != 0) {
2236 		logmsg(LOG_ERR, "ndpd command on interface %s failed with "
2237 		    "error %s\n", ndpd_msg.inm_ifname, strerror(retval));
2238 	}
2239 	(void) close(newfd);
2240 }
2241 
2242 /*
2243  * Process the commands received from the cmd listener socket.
2244  */
2245 static int
2246 ndpd_process_cmd(int newfd, ipadm_ndpd_msg_t *msg)
2247 {
2248 	int err;
2249 
2250 	if (!ipadm_check_auth()) {
2251 		logmsg(LOG_ERR, "User not authorized to send the command\n");
2252 		(void) ndpd_send_error(newfd, EPERM);
2253 		return (EPERM);
2254 	}
2255 	switch (msg->inm_cmd) {
2256 	case IPADM_DISABLE_AUTOCONF:
2257 		err = ndpd_set_autoconf(msg->inm_ifname, _B_FALSE);
2258 		break;
2259 
2260 	case IPADM_ENABLE_AUTOCONF:
2261 		err = ndpd_set_autoconf(msg->inm_ifname, _B_TRUE);
2262 		break;
2263 
2264 	case IPADM_CREATE_ADDRS:
2265 		err = ndpd_create_addrs(msg->inm_ifname, msg->inm_intfid,
2266 		    msg->inm_intfidlen, msg->inm_stateless,
2267 		    msg->inm_stateful, msg->inm_aobjname);
2268 		break;
2269 
2270 	case IPADM_DELETE_ADDRS:
2271 		err = ndpd_delete_addrs(msg->inm_ifname);
2272 		break;
2273 
2274 	default:
2275 		err = EINVAL;
2276 		break;
2277 	}
2278 
2279 	(void) ndpd_send_error(newfd, err);
2280 
2281 	return (err);
2282 }
2283 
2284 static int
2285 ndpd_send_error(int fd, int error)
2286 {
2287 	return (ipadm_ndpd_write(fd, &error, sizeof (error)));
2288 }
2289 
2290 /*
2291  * Disables/Enables autoconfiguration of addresses on the
2292  * given physical interface.
2293  * This is provided to support the legacy method of configuring IPv6
2294  * addresses. i.e. `ifconfig bge0 inet6 plumb` will plumb the interface
2295  * and start stateless and stateful autoconfiguration. If this function is
2296  * not called with enable=_B_FALSE, no autoconfiguration will be done until
2297  * ndpd_create_addrs() is called with an Interface ID.
2298  */
2299 static int
2300 ndpd_set_autoconf(const char *ifname, boolean_t enable)
2301 {
2302 	struct phyint *pi;
2303 
2304 	pi = phyint_lookup((char *)ifname);
2305 	if (pi == NULL) {
2306 		/*
2307 		 * If the physical interface was plumbed but no
2308 		 * addresses were configured yet, phyint will not exist.
2309 		 */
2310 		pi = phyint_create((char *)ifname);
2311 		if (pi == NULL) {
2312 			logmsg(LOG_ERR, "could not create phyint for "
2313 			    "interface %s", ifname);
2314 			return (ENOMEM);
2315 		}
2316 	}
2317 	pi->pi_autoconf = enable;
2318 
2319 	if (debug & D_PHYINT) {
2320 		logmsg(LOG_DEBUG, "ndpd_set_autoconf: %s autoconf for "
2321 		    "interface %s\n", (enable ? "enabled" : "disabled"),
2322 		    pi->pi_name);
2323 	}
2324 	return (0);
2325 }
2326 
2327 /*
2328  * Create auto-configured addresses on the given interface using
2329  * the given token as the interface id during the next Router Advertisement.
2330  * Currently, only one token per interface is supported.
2331  */
2332 static int
2333 ndpd_create_addrs(const char *ifname, struct sockaddr_in6 intfid, int intfidlen,
2334     boolean_t stateless, boolean_t stateful, char *addrobj)
2335 {
2336 	struct phyint *pi;
2337 	struct lifreq lifr;
2338 	struct sockaddr_in6 *sin6;
2339 	int err;
2340 
2341 	pi = phyint_lookup((char *)ifname);
2342 	if (pi == NULL) {
2343 		/*
2344 		 * If the physical interface was plumbed but no
2345 		 * addresses were configured yet, phyint will not exist.
2346 		 */
2347 		pi = phyint_create((char *)ifname);
2348 		if (pi == NULL) {
2349 			if (debug & D_PHYINT)
2350 				logmsg(LOG_ERR, "could not create phyint "
2351 				    "for interface %s", ifname);
2352 			return (ENOMEM);
2353 		}
2354 	} else if (pi->pi_autoconf) {
2355 		logmsg(LOG_ERR, "autoconfiguration already in progress\n");
2356 		return (EEXIST);
2357 	}
2358 	check_autoconf_var_consistency(pi, stateless, stateful);
2359 
2360 	if (intfidlen == 0) {
2361 		pi->pi_default_token = _B_TRUE;
2362 		if (ifsock < 0) {
2363 			ifsock = socket(AF_INET6, SOCK_DGRAM, 0);
2364 			if (ifsock < 0) {
2365 				err = errno;
2366 				logperror("ndpd_create_addrs: socket");
2367 				return (err);
2368 			}
2369 		}
2370 		(void) strncpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
2371 		sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
2372 		if (ioctl(ifsock, SIOCGLIFTOKEN, (char *)&lifr) < 0) {
2373 			err = errno;
2374 			logperror("SIOCGLIFTOKEN");
2375 			return (err);
2376 		}
2377 		pi->pi_token = sin6->sin6_addr;
2378 		pi->pi_token_length = lifr.lifr_addrlen;
2379 	} else {
2380 		pi->pi_default_token = _B_FALSE;
2381 		pi->pi_token = intfid.sin6_addr;
2382 		pi->pi_token_length = intfidlen;
2383 	}
2384 	pi->pi_stateless = stateless;
2385 	pi->pi_stateful = stateful;
2386 	(void) strlcpy(pi->pi_ipadm_aobjname, addrobj,
2387 	    sizeof (pi->pi_ipadm_aobjname));
2388 
2389 	/* We can allow autoconfiguration now. */
2390 	pi->pi_autoconf = _B_TRUE;
2391 
2392 	/* Restart the solicitations. */
2393 	if (pi->pi_sol_state == DONE_SOLICIT)
2394 		pi->pi_sol_state = NO_SOLICIT;
2395 	if (pi->pi_sol_state == NO_SOLICIT)
2396 		check_to_solicit(pi, START_INIT_SOLICIT);
2397 	if (debug & D_PHYINT)
2398 		logmsg(LOG_DEBUG, "ndpd_create_addrs: "
2399 		    "added token to interface %s\n", pi->pi_name);
2400 	return (0);
2401 }
2402 
2403 /*
2404  * This function deletes all addresses on the given interface
2405  * with the given Interface ID.
2406  */
2407 static int
2408 ndpd_delete_addrs(const char *ifname)
2409 {
2410 	struct phyint *pi;
2411 	struct prefix *pr, *next_pr;
2412 	struct lifreq lifr;
2413 	int err;
2414 
2415 	pi = phyint_lookup((char *)ifname);
2416 	if (pi == NULL) {
2417 		logmsg(LOG_ERR, "no phyint found for %s", ifname);
2418 		return (ENXIO);
2419 	}
2420 	if (IN6_IS_ADDR_UNSPECIFIED(&pi->pi_token)) {
2421 		logmsg(LOG_ERR, "token does not exist for %s", ifname);
2422 		return (ENOENT);
2423 	}
2424 
2425 	if (ifsock < 0) {
2426 		ifsock = socket(AF_INET6, SOCK_DGRAM, 0);
2427 		if (ifsock < 0) {
2428 			err = errno;
2429 			logperror("ndpd_create_addrs: socket");
2430 			return (err);
2431 		}
2432 	}
2433 	/* Remove the prefixes for this phyint if they exist */
2434 	for (pr = pi->pi_prefix_list; pr != NULL; pr = next_pr) {
2435 		next_pr = pr->pr_next;
2436 		if (pr->pr_name[0] == '\0') {
2437 			prefix_delete(pr);
2438 			continue;
2439 		}
2440 		/*
2441 		 * Delete all the prefixes for the auto-configured
2442 		 * addresses as well as the DHCPv6 addresses.
2443 		 */
2444 		(void) strncpy(lifr.lifr_name, pr->pr_name,
2445 		    sizeof (lifr.lifr_name));
2446 		if (ioctl(ifsock, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
2447 			err = errno;
2448 			logperror("SIOCGLIFFLAGS");
2449 			return (err);
2450 		}
2451 		if ((lifr.lifr_flags & IFF_ADDRCONF) ||
2452 		    (lifr.lifr_flags & IFF_DHCPRUNNING)) {
2453 			prefix_update_ipadm_addrobj(pr, _B_FALSE);
2454 		}
2455 		prefix_delete(pr);
2456 	}
2457 
2458 	/*
2459 	 * If we had started dhcpagent, we need to release the leases
2460 	 * if any are required.
2461 	 */
2462 	if (pi->pi_stateful) {
2463 		(void) strncpy(lifr.lifr_name, pi->pi_name,
2464 		    sizeof (lifr.lifr_name));
2465 		if (ioctl(ifsock, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
2466 			err = errno;
2467 			logperror("SIOCGLIFFLAGS");
2468 			return (err);
2469 		}
2470 		if (lifr.lifr_flags & IFF_DHCPRUNNING)
2471 			release_dhcp(pi);
2472 	}
2473 
2474 	/*
2475 	 * Reset the Interface ID on this phyint and stop autoconfigurations
2476 	 * until a new interface ID is provided.
2477 	 */
2478 	pi->pi_token = in6addr_any;
2479 	pi->pi_token_length = 0;
2480 	pi->pi_autoconf = _B_FALSE;
2481 	pi->pi_ipadm_aobjname[0] = '\0';
2482 
2483 	/* Reset the stateless and stateful settings to default. */
2484 	pi->pi_stateless = pi->pi_StatelessAddrConf;
2485 	pi->pi_stateful = pi->pi_StatefulAddrConf;
2486 
2487 	if (debug & D_PHYINT) {
2488 		logmsg(LOG_DEBUG, "ndpd_delete_addrs: "
2489 		    "removed token from interface %s\n", pi->pi_name);
2490 	}
2491 	return (0);
2492 }
2493 
2494 void
2495 check_autoconf_var_consistency(struct phyint *pi, boolean_t stateless,
2496     boolean_t stateful)
2497 {
2498 	/*
2499 	 * If StatelessAddrConf and StatelessAddrConf are set in
2500 	 * /etc/inet/ndpd.conf, check if the new values override those
2501 	 * settings. If so, log a warning.
2502 	 */
2503 	if ((pi->pi_StatelessAddrConf !=
2504 	    ifdefaults[I_StatelessAddrConf].cf_value &&
2505 	    stateless != pi->pi_StatelessAddrConf) ||
2506 	    (pi->pi_StatefulAddrConf !=
2507 	    ifdefaults[I_StatefulAddrConf].cf_value &&
2508 	    stateful != pi->pi_StatefulAddrConf)) {
2509 		logmsg(LOG_ERR, "check_autoconf_var_consistency: "
2510 		    "Overriding the StatelessAddrConf or StatefulAddrConf "
2511 		    "settings in ndpd.conf with the new values for "
2512 		    "interface %s\n", pi->pi_name);
2513 	}
2514 }
2515 
2516 /*
2517  * If ipadm was used to start autoconfiguration and in.ndpd was restarted
2518  * for some reason, in.ndpd has to resume autoconfiguration when it comes up.
2519  * In this function, it scans the ipadm_addr_info() output to find a link-local
2520  * on this interface with address type "addrconf" and extracts the interface id.
2521  * It also stores the addrobj name to be used later when new addresses are
2522  * created for the prefixes advertised by the router.
2523  * If autoconfiguration was never started on this interface before in.ndpd
2524  * was killed, then in.ndpd should refrain from configuring prefixes, even if
2525  * there is a valid link-local on this interface, created by ipadm (identified
2526  * if there is a valid addrobj name).
2527  */
2528 static int
2529 phyint_check_ipadm_intfid(struct phyint *pi)
2530 {
2531 	ipadm_status_t		status;
2532 	ipadm_addr_info_t	*addrinfo;
2533 	struct ifaddrs		*ifap;
2534 	ipadm_addr_info_t	*ainfop;
2535 	struct sockaddr_in6	*sin6;
2536 	ipadm_handle_t		iph;
2537 
2538 	if (ipadm_open(&iph, 0) != IPADM_SUCCESS) {
2539 		logmsg(LOG_ERR, "could not open handle to libipadm\n");
2540 		return (-1);
2541 	}
2542 
2543 	status = ipadm_addr_info(iph, pi->pi_name, &addrinfo,
2544 	    IPADM_OPT_ZEROADDR, LIFC_NOXMIT|LIFC_TEMPORARY);
2545 	if (status != IPADM_SUCCESS) {
2546 		ipadm_close(iph);
2547 		return (-1);
2548 	}
2549 	pi->pi_autoconf = _B_TRUE;
2550 	for (ainfop = addrinfo; ainfop != NULL; ainfop = IA_NEXT(ainfop)) {
2551 		ifap = &ainfop->ia_ifa;
2552 		if (ifap->ifa_addr->sa_family != AF_INET6 ||
2553 		    ainfop->ia_state == IFA_DISABLED)
2554 			continue;
2555 		sin6 = (struct sockaddr_in6 *)ifap->ifa_addr;
2556 		if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
2557 			if (ainfop->ia_atype == IPADM_ADDR_IPV6_ADDRCONF) {
2558 				pi->pi_token = sin6->sin6_addr;
2559 				pi->pi_token._S6_un._S6_u32[0] = 0;
2560 				pi->pi_token._S6_un._S6_u32[1] = 0;
2561 				pi->pi_autoconf = _B_TRUE;
2562 				(void) strlcpy(pi->pi_ipadm_aobjname,
2563 				    ainfop->ia_aobjname,
2564 				    sizeof (pi->pi_ipadm_aobjname));
2565 				break;
2566 			}
2567 			/*
2568 			 * If IFF_NOLINKLOCAL is set, then the link-local
2569 			 * was created using ipadm. Do not autoconfigure until
2570 			 * ipadm is explicitly used for autoconfiguration.
2571 			 */
2572 			if (ifap->ifa_flags & IFF_NOLINKLOCAL)
2573 				pi->pi_autoconf = _B_FALSE;
2574 		} else if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
2575 		    strrchr(ifap->ifa_name, ':') == NULL) {
2576 			/* The interface was created using ipadm. */
2577 			pi->pi_autoconf = _B_FALSE;
2578 		}
2579 	}
2580 	ipadm_free_addr_info(addrinfo);
2581 	if (!pi->pi_autoconf) {
2582 		pi->pi_token = in6addr_any;
2583 		pi->pi_token_length = 0;
2584 	}
2585 	ipadm_close(iph);
2586 	return (0);
2587 }
2588