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