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