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  */
  23 
  24 #include "defs.h"
  25 #include "tables.h"
  26 #include <fcntl.h>
  27 #include <sys/un.h>
  28 
  29 static void     initlog(void);
  30 static void     run_timeouts(void);
  31 
  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);
  41 
  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 } };
  46 
  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 } };
  51 
  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 } };
  57 
  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 } };
  63 
  64 static char **argv0;            /* Saved for re-exec on SIGHUP */
  65 
  66 static uint64_t packet[(IP_MAXPACKET + 1)/8];
  67 
  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 */
  72 
  73 /*
  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).
  77  */
  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)
  83 
  84 /*
  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.
  88  */
  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 */
  93 
  94 /*
  95  * These sockets are used internally in this file.
  96  */
  97 static int      mibsock = -1;                   /* mib request socket */
  98 static int      cmdsock = -1;                   /* command socket */
  99 
 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 *);
 109 
 110 /*
 111  * Return the current time in milliseconds truncated to
 112  * fit in an integer.
 113  */
 114 uint_t
 115 getcurrenttime(void)
 116 {
 117         struct timeval tp;
 118 
 119         if (gettimeofday(&tp, NULL) < 0) {
 120                 logperror("getcurrenttime: gettimeofday failed");
 121                 exit(1);
 122         }
 123         return (tp.tv_sec * 1000 + tp.tv_usec / 1000);
 124 }
 125 
 126 /*
 127  * Output a preformated packet from the packet[] buffer.
 128  */
 129 static void
 130 sendpacket(struct sockaddr_in6 *sin6, int sock, int size, int flags)
 131 {
 132         int cc;
 133         char abuf[INET6_ADDRSTRLEN];
 134 
 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");
 140                 }
 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);
 146         }
 147 }
 148 
 149 /*
 150  * If possible, place an ND_OPT_SOURCE_LINKADDR option at `optp'.
 151  * Return the number of bytes placed in the option.
 152  */
 153 static uint_t
 154 add_opt_lla(struct phyint *pi, struct nd_opt_lla *optp)
 155 {
 156         uint_t optlen;
 157         uint_t hwaddrlen;
 158         struct lifreq lifr;
 159 
 160         /* If this phyint doesn't have a link-layer address, bail */
 161         if (phyint_get_lla(pi, &lifr) == -1)
 162                 return (0);
 163 
 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);
 171 
 172         return (optlen);
 173 }
 174 
 175 /* Send a Router Solicitation */
 176 static void
 177 solicit(struct sockaddr_in6 *sin6, struct phyint *pi)
 178 {
 179         int packetlen = 0;
 180         struct  nd_router_solicit *rs = (struct nd_router_solicit *)packet;
 181         char *pptr = (char *)packet;
 182 
 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);
 187 
 188         packetlen += sizeof (*rs);
 189         pptr += sizeof (*rs);
 190 
 191         /* add options */
 192         packetlen += add_opt_lla(pi, (struct nd_opt_lla *)pptr);
 193 
 194         if (debug & D_PKTOUT) {
 195                 print_route_sol("Sending solicitation to ", pi, rs, packetlen,
 196                     sin6);
 197         }
 198         sendpacket(sin6, pi->pi_sock, packetlen, 0);
 199 }
 200 
 201 /*
 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.
 206  */
 207 static void
 208 advertise(struct sockaddr_in6 *sin6, struct phyint *pi, boolean_t no_prefixes)
 209 {
 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;
 215 
 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;
 226 
 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);
 233 
 234         packetlen = sizeof (*ra);
 235         pptr += sizeof (*ra);
 236 
 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);
 241                 }
 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;
 246         }
 247 
 248         /* add options */
 249         packetlen += add_opt_lla(pi, (struct nd_opt_lla *)pptr);
 250         pptr = (char *)packet + packetlen;
 251 
 252         if (pi->pi_AdvLinkMTU != 0) {
 253                 struct nd_opt_mtu *mo = (struct nd_opt_mtu *)pptr;
 254 
 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);
 259 
 260                 packetlen += sizeof (struct nd_opt_mtu);
 261                 pptr += sizeof (struct nd_opt_mtu);
 262         }
 263 
 264         if (no_prefixes) {
 265                 if (debug & D_PKTOUT) {
 266                         print_route_adv("Sending advert to ", pi,
 267                             ra, packetlen, sin6);
 268                 }
 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;
 273         }
 274 
 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;
 281                 }
 282 
 283                 /*
 284                  * If the prefix doesn't fit in packet send
 285                  * what we have so far and start with new packet.
 286                  */
 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);
 293                         }
 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;
 300                 }
 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;
 307                 }
 308                 if (adv_pr->adv_pr_AdvAutonomousFlag) {
 309                         po->nd_opt_pi_flags_reserved |=
 310                             ND_OPT_PI_FLAG_AUTO;
 311                 }
 312                 po->nd_opt_pi_prefix_len = adv_pr->adv_pr_prefix_len;
 313                 /*
 314                  * If both Adv*Expiration and Adv*Lifetime are
 315                  * set we prefer the former and make the lifetime
 316                  * decrement in real time.
 317                  */
 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);
 324                 }
 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);
 331                 }
 332                 po->nd_opt_pi_reserved2 = htonl(0);
 333                 po->nd_opt_pi_prefix = adv_pr->adv_pr_prefix;
 334 
 335                 po++;
 336                 packetlen += sizeof (*po);
 337         }
 338         if (debug & D_PKTOUT) {
 339                 print_route_adv("Sending advert to ", pi,
 340                     ra, packetlen, sin6);
 341         }
 342         sendpacket(sin6, pi->pi_sock, packetlen, 0);
 343         /* Feed packet back in for router operation */
 344         loopback_ra_enqueue(pi, ra, packetlen);
 345 }
 346 
 347 /* Poll support */
 348 static int              pollfd_num = 0; /* Allocated and initialized */
 349 static struct pollfd    *pollfds = NULL;
 350 
 351 /*
 352  * Add fd to the set being polled. Returns 0 if ok; -1 if failed.
 353  */
 354 int
 355 poll_add(int fd)
 356 {
 357         int i;
 358         int new_num;
 359         struct pollfd *newfds;
 360 
 361         /* Check if already present */
 362         for (i = 0; i < pollfd_num; i++) {
 363                 if (pollfds[i].fd == fd)
 364                         return (0);
 365         }
 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);
 371                 }
 372         }
 373 
 374         /* Allocate space for 32 more fds and initialize to -1 */
 375         new_num = pollfd_num + 32;
 376         newfds = realloc(pollfds, new_num * sizeof (struct pollfd));
 377         if (newfds == NULL) {
 378                 logperror("realloc");
 379                 return (-1);
 380         }
 381 
 382         newfds[pollfd_num].fd = fd;
 383         newfds[pollfd_num++].events = POLLIN;
 384 
 385         for (i = pollfd_num; i < new_num; i++) {
 386                 newfds[i].fd = -1;
 387                 newfds[i].events = POLLIN;
 388         }
 389         pollfd_num = new_num;
 390         pollfds = newfds;
 391         return (0);
 392 }
 393 
 394 /*
 395  * Remove fd from the set being polled. Returns 0 if ok; -1 if failed.
 396  */
 397 int
 398 poll_remove(int fd)
 399 {
 400         int i;
 401 
 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);
 407                 }
 408         }
 409         return (-1);
 410 }
 411 
 412 /*
 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.
 419  */
 420 static void
 421 if_process(int s, char *ifname, boolean_t first)
 422 {
 423         struct lifreq lifr;
 424         struct phyint *pi;
 425         struct prefix *pr;
 426         char *cp;
 427         char phyintname[LIFNAMSIZ + 1];
 428 
 429         if (debug & D_IFSCAN)
 430                 logmsg(LOG_DEBUG, "if_process(%s)\n", ifname);
 431 
 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) {
 436                         /*
 437                          * Interface has disappeared
 438                          */
 439                         return;
 440                 }
 441                 logperror("if_process: ioctl (get interface flags)");
 442                 return;
 443         }
 444 
 445         /*
 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.
 449          */
 450         if (!(lifr.lifr_flags & IFF_MULTICAST) ||
 451             (lifr.lifr_flags & (IFF_LOOPBACK|IFF_VRRP))) {
 452                 return;
 453         }
 454 
 455         if (!(lifr.lifr_flags & IFF_IPV6))
 456                 return;
 457 
 458         (void) strncpy(phyintname, ifname, sizeof (phyintname));
 459         phyintname[sizeof (phyintname) - 1] = '\0';
 460         if ((cp = strchr(phyintname, IF_SEPARATOR)) != NULL) {
 461                 *cp = '\0';
 462         }
 463 
 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;
 470                 }
 471                 /*
 472                  * if in.ndpd is restarted, check with ipmgmtd if there is any
 473                  * interface id to be configured for this interface.
 474                  */
 475                 if (first) {
 476                         if (phyint_check_ipadm_intfid(pi) == -1)
 477                                 logmsg(LOG_ERR, "Could not get ipadm info\n");
 478                 }
 479         } else {
 480                 /*
 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().
 484                  */
 485                 (void) phyint_init_from_k(pi);
 486         }
 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);
 492                 }
 493                 return;
 494         }
 495 
 496         if (pi->pi_sock != -1) {
 497                 if (poll_add(pi->pi_sock) == -1) {
 498                         /*
 499                          * reset state.
 500                          */
 501                         phyint_cleanup(pi);
 502                 }
 503         }
 504 
 505         /*
 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.
 511          */
 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);
 516 
 517                 pi->pi_AdvSendAdvertisements = 0;
 518                 pi->pi_sol_state = NO_SOLICIT;
 519         }
 520 
 521         /*
 522          * Send advertisments and solicitation only if the interface is
 523          * present in the kernel.
 524          */
 525         if (pi->pi_kernel_state & PI_PRESENT) {
 526 
 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);
 533                 }
 534         }
 535 
 536         /*
 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.
 540          */
 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;
 547                 }
 548                 if (prefix_init_from_k(pr) == -1) {
 549                         prefix_delete(pr);
 550                         return;
 551                 }
 552         }
 553         /* Detect prefixes which are removed */
 554         if (pr->pr_kernel_state != 0)
 555                 pr->pr_in_use = _B_TRUE;
 556 
 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];
 563 
 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;
 574                 }
 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;
 581                 }
 582                 token = &pi->pi_tmp_token;
 583                 for (i = 0; i < 16; i++) {
 584                         /*
 585                          * prefix_create ensures that pr_prefix has all-zero
 586                          * bits after prefixlen.
 587                          */
 588                         pr->pr_address.s6_addr[i] = pr->pr_prefix.s6_addr[i] |
 589                             token->s6_addr[i];
 590                 }
 591                 if (prefix_lookup_addr_match(pr) != NULL) {
 592                         prefix_delete(pr);
 593                         return;
 594                 }
 595                 pr->pr_CreateTime = getcurrenttime() / MILLISEC;
 596                 /*
 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.
 600                  */
 601                 pr->pr_kernel_state &= ~PR_AUTO;
 602                 prefix_update_k(pr);
 603         }
 604 }
 605 
 606 static int ifsock = -1;
 607 
 608 /*
 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.
 611  */
 612 static void
 613 initifs(boolean_t first)
 614 {
 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;
 625 
 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;
 633                 }
 634         }
 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;
 640         }
 641         numifs = lifn.lifn_count;
 642         bufsize = numifs * sizeof (struct lifreq);
 643 
 644         buf = (char *)malloc(bufsize);
 645         if (buf == NULL) {
 646                 logmsg(LOG_ERR, "initifs: out of memory\n");
 647                 return;
 648         }
 649 
 650         /*
 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.
 655          */
 656         for (pi = phyints; pi != NULL; pi = pi->pi_next) {
 657                 /*
 658                  * Before re-examining the state of the interfaces,
 659                  * PI_PRESENT should be cleared from pi_kernel_state.
 660                  */
 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;
 664                 }
 665         }
 666 
 667         lifc.lifc_family = AF_INET6;
 668         lifc.lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY;
 669         lifc.lifc_len = bufsize;
 670         lifc.lifc_buf = buf;
 671 
 672         if (ioctl(ifsock, SIOCGLIFCONF, (char *)&lifc) < 0) {
 673                 logperror("initifs: ioctl (get interface configuration)");
 674                 free(buf);
 675                 return;
 676         }
 677 
 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);
 682 
 683         /*
 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.
 687          */
 688         for (pi = phyints; pi != NULL; pi = next_pi) {
 689                 next_pi = pi->pi_next;
 690                 /*
 691                  * If interface (still) exists in kernel, set
 692                  * pi_state to indicate that.
 693                  */
 694                 if (pi->pi_kernel_state & PI_PRESENT) {
 695                         pi->pi_state |= PI_PRESENT;
 696                 }
 697 
 698                 check_if_removed(pi);
 699         }
 700         if (show_ifs)
 701                 phyint_print_all();
 702 }
 703 
 704 
 705 /*
 706  * Router advertisement state machine. Used for everything but timer
 707  * events which use advertise_event directly.
 708  */
 709 void
 710 check_to_advertise(struct phyint *pi, enum adv_events event)
 711 {
 712         uint_t delay;
 713         enum adv_states old_state = pi->pi_adv_state;
 714 
 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);
 718         }
 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);
 723         }
 724 
 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);
 729         }
 730 }
 731 
 732 /*
 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.
 738  */
 739 uint_t
 740 advertise_event(struct phyint *pi, enum adv_events event, uint_t elapsed)
 741 {
 742         uint_t delay;
 743 
 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);
 747         }
 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);
 756                 }
 757                 return (TIMER_INFINITY);
 758         }
 759 
 760         switch (event) {
 761         case ADV_OFF:
 762                 pi->pi_adv_state = NO_ADV;
 763                 return (TIMER_INFINITY);
 764 
 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 */
 772 
 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 */
 782 
 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;
 790                 }
 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) {
 795                         /*
 796                          * Send an advertisement (ND_MIN_DELAY_BETWEEN_RAS
 797                          * plus random delay) after the previous
 798                          * advertisement was sent.
 799                          */
 800                         pi->pi_adv_time_left = delay +
 801                             ND_MIN_DELAY_BETWEEN_RAS -
 802                             pi->pi_adv_time_since_sent;
 803                 }
 804                 pi->pi_adv_state = SOLICIT_ADV;
 805                 break;
 806 
 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;
 815 
 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);
 823         }
 824 
 825         if (pi->pi_adv_time_left != 0)
 826                 return (pi->pi_adv_time_left);
 827 
 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);
 834         }
 835         pi->pi_adv_time_since_sent = 0;
 836 
 837         switch (pi->pi_adv_state) {
 838         case SOLICIT_ADV:
 839                 /*
 840                  * The solicited advertisement has been sent.
 841                  * Revert to periodic advertisements.
 842                  */
 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;
 850 
 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;
 863                 }
 864                 break;
 865 
 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;
 872                 }
 873                 break;
 874         }
 875         if (pi->pi_adv_state != NO_ADV)
 876                 return (pi->pi_adv_time_left);
 877         else
 878                 return (TIMER_INFINITY);
 879 }
 880 
 881 /*
 882  * Router solicitation state machine. Used for everything but timer
 883  * events which use solicit_event directly.
 884  */
 885 void
 886 check_to_solicit(struct phyint *pi, enum solicit_events event)
 887 {
 888         uint_t delay;
 889         enum solicit_states old_state = pi->pi_sol_state;
 890 
 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);
 894         }
 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);
 899         }
 900 
 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);
 905         }
 906 }
 907 
 908 static void
 909 daemonize_ndpd(void)
 910 {
 911         struct itimerval it;
 912         boolean_t timerval = _B_TRUE;
 913 
 914         /*
 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.
 918          */
 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;
 924         }
 925 
 926         /* Daemonize. */
 927         if (daemon(0, 0) == -1) {
 928                 logperror("fork");
 929                 exit(1);
 930         }
 931 
 932         already_daemonized = _B_TRUE;
 933 
 934         /*
 935          * Restore timer values, if we were able to save them; if not,
 936          * check and set the right value by calling run_timeouts().
 937          */
 938         if (timerval) {
 939                 if (setitimer(ITIMER_REAL, &it, NULL) < 0) {
 940                         logperror("daemonize_ndpd: setitimer");
 941                         exit(2);
 942                 }
 943         } else {
 944                 run_timeouts();
 945         }
 946 }
 947 
 948 /*
 949  * Check to see if the time is right to daemonize.  The right time is when:
 950  *
 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.
 957  */
 958 static void
 959 check_daemonize(void)
 960 {
 961         struct phyint           *pi;
 962 
 963         if (already_daemonized || debug != 0)
 964                 return;
 965 
 966         for (pi = phyints; pi != NULL; pi = pi->pi_next) {
 967                 if (!(pi->pi_flags & IFF_NOXMIT))
 968                         break;
 969         }
 970 
 971         /*
 972          * If we can't transmit on any of the interfaces there is no reason
 973          * to hold up progress.
 974          */
 975         if (pi == NULL) {
 976                 daemonize_ndpd();
 977                 return;
 978         }
 979 
 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;
 985 
 986                 if (pi->pi_sol_state == INIT_SOLICIT)
 987                         return;
 988         }
 989 
 990         daemonize_ndpd();
 991 }
 992 
 993 /*
 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.
 999  */
1000 uint_t
1001 solicit_event(struct phyint *pi, enum solicit_events event, uint_t elapsed)
1002 {
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);
1006         }
1007 
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);
1015                 }
1016                 return (TIMER_INFINITY);
1017         }
1018 
1019         switch (event) {
1020         case SOLICIT_OFF:
1021                 pi->pi_sol_state = NO_SOLICIT;
1022                 check_daemonize();
1023                 return (TIMER_INFINITY);
1024 
1025         case SOLICIT_DONE:
1026                 pi->pi_sol_state = DONE_SOLICIT;
1027                 check_daemonize();
1028                 return (TIMER_INFINITY);
1029 
1030         case RESTART_INIT_SOLICIT:
1031                 /*
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.
1036                  */
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;
1044 
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;
1054 
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);
1068         }
1069 
1070         if (pi->pi_sol_time_left != 0)
1071                 return (pi->pi_sol_time_left);
1072 
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);
1082                         }
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);
1087                         }
1088                         pi->pi_sol_state = DONE_SOLICIT;
1089                         check_daemonize();
1090                         return (TIMER_INFINITY);
1091                 }
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);
1099         }
1100 }
1101 
1102 /*
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.
1106  */
1107 static uint_t timer_previous;   /* When last SIGALRM occurred */
1108 static uint_t timer_next;       /* Currently scheduled timeout */
1109 
1110 static void
1111 timer_init(void)
1112 {
1113         timer_previous = getcurrenttime();
1114         timer_next = TIMER_INFINITY;
1115         run_timeouts();
1116 }
1117 
1118 /*
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.
1123  */
1124 void
1125 timer_schedule(uint_t delay)
1126 {
1127         uint_t now;
1128         struct itimerval itimerval;
1129 
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);
1134         }
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);
1141                 }
1142                 return;
1143         }
1144         if (delay == 0) {
1145                 /* Minimum allowed delay */
1146                 delay = 1;
1147         }
1148         timer_next = now + delay;
1149 
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);
1158         }
1159         if (setitimer(ITIMER_REAL, &itimerval, NULL) < 0) {
1160                 logperror("timer_schedule: setitimer");
1161                 exit(2);
1162         }
1163 }
1164 
1165 /*
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.
1169  */
1170 static void
1171 conditional_run_timeouts(uint_t minimal_time)
1172 {
1173         uint_t now;
1174         uint_t elapsed;
1175 
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);
1182                 }
1183                 run_timeouts();
1184         }
1185 }
1186 
1187 /*
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.
1196  */
1197 static void
1198 run_timeouts(void)
1199 {
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;
1214 
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;
1220         }
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;
1227 
1228         if (debug & D_TIMER)
1229                 logmsg(LOG_DEBUG, "run_timeouts: elapsed %d\n", elapsed);
1230 
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);
1240                 }
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);
1249                         }
1250                 }
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);
1262                         }
1263                 }
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);
1272                         }
1273                 }
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);
1281                         }
1282                 }
1283         }
1284         /*
1285          * Make sure the timer functions are run at least once
1286          * an hour.
1287          */
1288         if (next == TIMER_INFINITY)
1289                 next = 3600 * 1000;     /* 1 hour */
1290 
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;
1299         }
1300         timeout_running = _B_FALSE;
1301 }
1302 
1303 static int eventpipe_read = -1; /* Used for synchronous signal delivery */
1304 static int eventpipe_write = -1;
1305 
1306 /*
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.
1310  */
1311 static void
1312 sig_handler(int signo)
1313 {
1314         uchar_t buf = (uchar_t)signo;
1315 
1316         if (eventpipe_write == -1) {
1317                 logmsg(LOG_ERR, "sig_handler: no pipe\n");
1318                 return;
1319         }
1320         if (write(eventpipe_write, &buf, sizeof (buf)) < 0)
1321                 logperror("sig_handler: write");
1322 }
1323 
1324 /*
1325  * Pick up a signal "byte" from the pipe and process it.
1326  */
1327 static void
1328 in_signal(int fd)
1329 {
1330         uchar_t buf;
1331         struct phyint *pi;
1332         struct phyint *next_pi;
1333 
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);
1348         }
1349 
1350         if (debug & D_TIMER)
1351                 logmsg(LOG_DEBUG, "in_signal() got %d\n", buf);
1352 
1353         switch (buf) {
1354         case SIGALRM:
1355                 if (debug & D_TIMER) {
1356                         uint_t now = getcurrenttime();
1357 
1358                         logmsg(LOG_DEBUG, "in_signal(SIGALRM) delta %u\n",
1359                             now - timer_next);
1360                 }
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);
1370 
1371                         /*
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.
1376                          */
1377                         phyint_delete(pi);
1378                 }
1379 
1380                 /*
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.
1384                  */
1385                 closefrom(3);
1386 
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);
1402 
1403                         phyint_delete(pi);
1404                 }
1405                 (void) unlink(NDPD_SNMP_SOCKET);
1406                 exit(0);
1407                 /* NOTREACHED */
1408         case 255:
1409                 /*
1410                  * Special "signal" from loopback_ra_enqueue.
1411                  * Handle any queued loopback router advertisements.
1412                  */
1413                 loopback_ra_dequeue();
1414                 break;
1415         default:
1416                 logmsg(LOG_ERR, "in_signal: unknown signal: %d\n", buf);
1417         }
1418 }
1419 
1420 /*
1421  * Create pipe for signal delivery and set up signal handlers.
1422  */
1423 static void
1424 setup_eventpipe(void)
1425 {
1426         int fds[2];
1427         struct sigaction act;
1428 
1429         if ((pipe(fds)) < 0) {
1430                 logperror("setup_eventpipe: pipe");
1431                 exit(1);
1432         }
1433         eventpipe_read = fds[0];
1434         eventpipe_write = fds[1];
1435         if (poll_add(eventpipe_read) == -1) {
1436                 exit(1);
1437         }
1438         act.sa_handler = sig_handler;
1439         act.sa_flags = SA_RESTART;
1440         (void) sigaction(SIGALRM, &act, NULL);
1441 
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);
1447 }
1448 
1449 /*
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.
1452  */
1453 static int
1454 setup_rtsock(void)
1455 {
1456         int s;
1457         int ret;
1458         char *cp;
1459         struct sockaddr_in6 *sin6;
1460 
1461         s = socket(PF_ROUTE, SOCK_RAW, AF_INET6);
1462         if (s == -1) {
1463                 logperror("socket(PF_ROUTE)");
1464                 exit(1);
1465         }
1466         ret = fcntl(s, F_SETFL, O_NDELAY|O_NONBLOCK);
1467         if (ret < 0) {
1468                 logperror("fcntl(O_NDELAY)");
1469                 exit(1);
1470         }
1471         if (poll_add(s) == -1) {
1472                 exit(1);
1473         }
1474 
1475         /*
1476          * Allocate storage for the routing socket message.
1477          */
1478         rt_msg = (struct rt_msghdr *)malloc(NDP_RTM_MSGLEN);
1479         if (rt_msg == NULL) {
1480                 logperror("malloc");
1481                 exit(1);
1482         }
1483 
1484         /*
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.
1488          */
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);
1497         }
1498 
1499         /*
1500          * The RTA_DST sockaddr does not change during the lifetime of the
1501          * process so it can be completely initialized at this time.
1502          */
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;
1507 
1508         /*
1509          * Initialize the constant portion of the RTA_GATEWAY sockaddr.
1510          */
1511         cp += sizeof (struct sockaddr_in6);
1512         rta_gateway = (struct sockaddr_in6 *)cp;
1513         rta_gateway->sin6_family = AF_INET6;
1514 
1515         /*
1516          * The RTA_NETMASK sockaddr does not change during the lifetime of the
1517          * process so it can be completely initialized at this time.
1518          */
1519         cp += sizeof (struct sockaddr_in6);
1520         sin6 = (struct sockaddr_in6 *)cp;
1521         sin6->sin6_family = AF_INET6;
1522         sin6->sin6_addr = in6addr_any;
1523 
1524         /*
1525          * Initialize the constant portion of the RTA_IFP sockaddr.
1526          */
1527         cp += sizeof (struct sockaddr_in6);
1528         rta_ifp = (struct sockaddr_dl *)cp;
1529         rta_ifp->sdl_family = AF_LINK;
1530 
1531         return (s);
1532 }
1533 
1534 static int
1535 setup_mibsock(void)
1536 {
1537         int sock;
1538         int ret;
1539         int len;
1540         struct sockaddr_un laddr;
1541 
1542         sock = socket(AF_UNIX, SOCK_DGRAM, 0);
1543         if (sock == -1) {
1544                 logperror("setup_mibsock: socket(AF_UNIX)");
1545                 exit(1);
1546         }
1547 
1548         bzero(&laddr, sizeof (laddr));
1549         laddr.sun_family = AF_UNIX;
1550 
1551         (void) strncpy(laddr.sun_path, NDPD_SNMP_SOCKET,
1552             sizeof (laddr.sun_path));
1553         len = sizeof (struct sockaddr_un);
1554 
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);
1560         }
1561 
1562         ret = fcntl(sock, F_SETFL, O_NONBLOCK);
1563         if (ret < 0) {
1564                 logperror("fcntl(O_NONBLOCK)");
1565                 exit(1);
1566         }
1567         if (poll_add(sock) == -1) {
1568                 exit(1);
1569         }
1570         return (sock);
1571 }
1572 
1573 /*
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.
1578  */
1579 static void
1580 process_rtsock(int rtsock)
1581 {
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;
1594 
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;
1601                 }
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;
1608                 }
1609                 switch (rtm->rtm_type) {
1610                 case RTM_NEWADDR:
1611                 case RTM_DELADDR:
1612                         /*
1613                          * Some logical interface has changed - have to scan
1614                          * everything to determine what actually changed.
1615                          */
1616                         if (debug & D_IFSCAN) {
1617                                 logmsg(LOG_DEBUG, "process_rtsock: "
1618                                     "message %d\n", rtm->rtm_type);
1619                         }
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;
1632                 }
1633         }
1634         /*
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.
1638          */
1639         if (need_initifs) {
1640                 initifs(_B_FALSE);
1641                 return;
1642         }
1643 
1644         if (!need_ifscan)
1645                 return;
1646 
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);
1652 
1653                 pi = phyint_lookup_on_index(ifm->ifm_index);
1654                 if (pi == NULL) {
1655                         /*
1656                          * A new physical interface. Do a full scan of the
1657                          * to catch any new logical interfaces.
1658                          */
1659                         initifs(_B_FALSE);
1660                         return;
1661                 }
1662 
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);
1668                         }
1669                 }
1670 
1671 
1672                 /*
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.
1679                  */
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;
1683                 }
1684 
1685                 if (ifsock < 0) {
1686                         ifsock = socket(AF_INET6, SOCK_DGRAM, 0);
1687                         if (ifsock < 0) {
1688                                 logperror("process_rtsock: socket");
1689                                 return;
1690                         }
1691                 }
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);
1695                 }
1696                 /*
1697                  * If interface (still) exists in kernel, set
1698                  * pi_state to indicate that.
1699                  */
1700                 if (pi->pi_kernel_state & PI_PRESENT) {
1701                         pi->pi_state |= PI_PRESENT;
1702                 }
1703                 check_if_removed(pi);
1704                 if (show_ifs)
1705                         phyint_print_all();
1706         }
1707 }
1708 
1709 static void
1710 process_mibsock(int mibsock)
1711 {
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;
1718 
1719         fromlen = (socklen_t)sizeof (from);
1720         len = recvfrom(mibsock, &command, sizeof (int), 0,
1721             (struct sockaddr *)&from, &fromlen);
1722 
1723         if (len < sizeof (int) || command != NDPD_SNMP_INFO_REQ) {
1724                 logperror("process_mibsock: bad command \n");
1725                 return;
1726         }
1727 
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;
1731 
1732         (void) sendto(mibsock, &ndpd_info, sizeof (ndpd_info_t), 0,
1733             (struct sockaddr *)&from, fromlen);
1734 
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;
1743                 /*
1744                  * get number of prefixes
1745                  */
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;
1752                 }
1753 
1754                 /*
1755                  * get number of routers
1756                  */
1757                 router_list = pi->pi_router_list;
1758                 while (router_list != NULL) {
1759                         routers++;
1760                         router_list = router_list->dr_next;
1761                 }
1762 
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);
1772 
1773                 /*
1774                  * Copy prefix information
1775                  */
1776 
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;
1798                 }
1799                 /*
1800                  * Copy router information
1801                  */
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;
1812                 }
1813         }
1814 }
1815 
1816 /*
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.
1820  */
1821 static void
1822 check_if_removed(struct phyint *pi)
1823 {
1824         struct prefix *pr, *next_pr;
1825 
1826         /*
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.
1831          */
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)) {
1843                                 /*
1844                                  * Ensure that there are no future attempts to
1845                                  * run prefix_update_k since the phyint is gone.
1846                                  */
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);
1852                         }
1853                 }
1854         }
1855 
1856         /*
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.)
1862          */
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);
1867 
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);
1873                 }
1874 
1875                 /*
1876                  * Clear state so that should the phyint reappear we will
1877                  * start with initial advertisements or solicitations.
1878                  */
1879                 phyint_cleanup(pi);
1880         }
1881 }
1882 
1883 
1884 /*
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().
1889  */
1890 struct raq {
1891         struct raq      *raq_next;
1892         struct phyint   *raq_pi;
1893         int             raq_packetlen;
1894         uchar_t         *raq_packet;
1895 };
1896 static struct raq *raq_head = NULL;
1897 
1898 /*
1899  * Allocate a struct raq and memory for the packet.
1900  * Send signal 255 to have poll dequeue.
1901  */
1902 static void
1903 loopback_ra_enqueue(struct phyint *pi, struct nd_router_advert *ra, int len)
1904 {
1905         struct raq *raq;
1906         struct raq **raqp;
1907 
1908         if (no_loopback)
1909                 return;
1910 
1911         if (debug & D_PKTOUT)
1912                 logmsg(LOG_DEBUG, "loopback_ra_enqueue for %s\n", pi->pi_name);
1913 
1914         raq = calloc(sizeof (struct raq), 1);
1915         if (raq == NULL) {
1916                 logmsg(LOG_ERR, "loopback_ra_enqueue: out of memory\n");
1917                 return;
1918         }
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;
1924         }
1925         bcopy(ra, raq->raq_packet, len);
1926         raq->raq_packetlen = len;
1927         raq->raq_pi = pi;
1928 
1929         /* Tail insert */
1930         raqp = &raq_head;
1931         while (*raqp != NULL)
1932                 raqp = &((*raqp)->raq_next);
1933         *raqp = raq;
1934 
1935         /* Signal for poll loop */
1936         sig_handler(255);
1937 }
1938 
1939 /*
1940  * Dequeue and process all queued advertisements.
1941  */
1942 static void
1943 loopback_ra_dequeue(void)
1944 {
1945         struct sockaddr_in6 from = IN6ADDR_LOOPBACK_INIT;
1946         struct raq *raq;
1947 
1948         if (debug & D_PKTIN)
1949                 logmsg(LOG_DEBUG, "loopback_ra_dequeue()\n");
1950 
1951         while ((raq = raq_head) != NULL) {
1952                 raq_head = raq->raq_next;
1953                 raq->raq_next = NULL;
1954 
1955                 if (debug & D_PKTIN) {
1956                         logmsg(LOG_DEBUG, "loopback_ra_dequeue for %s\n",
1957                             raq->raq_pi->pi_name);
1958                 }
1959 
1960                 incoming_ra(raq->raq_pi,
1961                     (struct nd_router_advert *)raq->raq_packet,
1962                     raq->raq_packetlen, &from, _B_TRUE);
1963                 free(raq->raq_packet);
1964                 free(raq);
1965         }
1966 }
1967 
1968 
1969 static void
1970 usage(char *cmd)
1971 {
1972         (void) fprintf(stderr,
1973             "usage: %s [ -adt ] [-f <config file>]\n", cmd);
1974 }
1975 
1976 int
1977 main(int argc, char *argv[])
1978 {
1979         int i;
1980         struct phyint *pi;
1981         int c;
1982         char *config_file = PATH_NDPD_CONF;
1983         boolean_t file_required = _B_FALSE;
1984 
1985         argv0 = argv;
1986         srandom(gethostid());
1987         (void) umask(0022);
1988 
1989         while ((c = getopt(argc, argv, "adD:ntIf:")) != EOF) {
1990                 switch (c) {
1991                 case 'a':
1992                         /*
1993                          * The StatelessAddrConf variable in ndpd.conf, if
1994                          * present, will override this setting.
1995                          */
1996                         ifdefaults[I_StatelessAddrConf].cf_value = 0;
1997                         break;
1998                 case 'd':
1999                         debug = D_ALL;
2000                         break;
2001                 case 'D':
2002                         i = strtol((char *)optarg, NULL, 0);
2003                         if (i == 0) {
2004                                 (void) fprintf(stderr, "Bad debug flags: %s\n",
2005                                     (char *)optarg);
2006                                 exit(1);
2007                         }
2008                         debug |= i;
2009                         break;
2010                 case 'n':
2011                         no_loopback = 1;
2012                         break;
2013                 case 'I':
2014                         show_ifs = 1;
2015                         break;
2016                 case 't':
2017                         debug |= D_PKTIN | D_PKTOUT | D_PKTBAD;
2018                         break;
2019                 case 'f':
2020                         config_file = (char *)optarg;
2021                         file_required = _B_TRUE;
2022                         break;
2023                 case '?':
2024                         usage(argv[0]);
2025                         exit(1);
2026                 }
2027         }
2028 
2029         if (parse_config(config_file, file_required) == -1)
2030                 exit(2);
2031 
2032         if (show_ifs)
2033                 phyint_print_all();
2034 
2035         if (debug == 0)
2036                 initlog();
2037 
2038         cmdsock = ndpd_setup_cmd_listener();
2039         setup_eventpipe();
2040         rtsock = setup_rtsock();
2041         mibsock = setup_mibsock();
2042         timer_init();
2043         initifs(_B_TRUE);
2044 
2045         check_daemonize();
2046 
2047         for (;;) {
2048                 if (poll(pollfds, pollfd_num, -1) < 0) {
2049                         if (errno == EINTR)
2050                                 continue;
2051                         logperror("main: poll");
2052                         exit(1);
2053                 }
2054                 for (i = 0; i < pollfd_num; i++) {
2055                         if (!(pollfds[i].revents & POLLIN))
2056                                 continue;
2057                         if (pollfds[i].fd == eventpipe_read) {
2058                                 in_signal(eventpipe_read);
2059                                 break;
2060                         }
2061                         if (pollfds[i].fd == rtsock) {
2062                                 process_rtsock(rtsock);
2063                                 break;
2064                         }
2065                         if (pollfds[i].fd == mibsock) {
2066                                 process_mibsock(mibsock);
2067                                 break;
2068                         }
2069                         if (pollfds[i].fd == cmdsock) {
2070                                 ndpd_cmd_handler(cmdsock);
2071                                 break;
2072                         }
2073                         /*
2074                          * Run timer routine to advance clock if more than
2075                          * half a second since the clock was advanced.
2076                          * This limits CPU usage under severe packet
2077                          * arrival rates but it creates a slight inaccuracy
2078                          * in the timer mechanism.
2079                          */
2080                         conditional_run_timeouts(500U);
2081                         for (pi = phyints; pi != NULL; pi = pi->pi_next) {
2082                                 if (pollfds[i].fd == pi->pi_sock) {
2083                                         in_data(pi);
2084                                         break;
2085                                 }
2086                         }
2087                 }
2088         }
2089         /* NOTREACHED */
2090         return (0);
2091 }
2092 
2093 /*
2094  * LOGGER
2095  */
2096 
2097 static boolean_t logging = _B_FALSE;
2098 
2099 static void
2100 initlog(void)
2101 {
2102         logging = _B_TRUE;
2103         openlog("in.ndpd", LOG_PID | LOG_CONS, LOG_DAEMON);
2104 }
2105 
2106 /* Print the date/time without a trailing carridge return */
2107 static void
2108 fprintdate(FILE *file)
2109 {
2110         char buf[BUFSIZ];
2111         struct tm tms;
2112         time_t now;
2113 
2114         now = time(NULL);
2115         (void) localtime_r(&now, &tms);
2116         (void) strftime(buf, sizeof (buf), "%h %d %X", &tms);
2117         (void) fprintf(file, "%s ", buf);
2118 }
2119 
2120 /* PRINTFLIKE2 */
2121 void
2122 logmsg(int level, const char *fmt, ...)
2123 {
2124         va_list ap;
2125         va_start(ap, fmt);
2126 
2127         if (logging) {
2128                 vsyslog(level, fmt, ap);
2129         } else {
2130                 fprintdate(stderr);
2131                 (void) vfprintf(stderr, fmt, ap);
2132         }
2133         va_end(ap);
2134 }
2135 
2136 void
2137 logperror(const char *str)
2138 {
2139         if (logging) {
2140                 syslog(LOG_ERR, "%s: %m\n", str);
2141         } else {
2142                 fprintdate(stderr);
2143                 (void) fprintf(stderr, "%s: %s\n", str, strerror(errno));
2144         }
2145 }
2146 
2147 void
2148 logperror_pi(const struct phyint *pi, const char *str)
2149 {
2150         if (logging) {
2151                 syslog(LOG_ERR, "%s (interface %s): %m\n",
2152                     str, pi->pi_name);
2153         } else {
2154                 fprintdate(stderr);
2155                 (void) fprintf(stderr, "%s (interface %s): %s\n",
2156                     str, pi->pi_name, strerror(errno));
2157         }
2158 }
2159 
2160 void
2161 logperror_pr(const struct prefix *pr, const char *str)
2162 {
2163         if (logging) {
2164                 syslog(LOG_ERR, "%s (prefix %s if %s): %m\n",
2165                     str, pr->pr_name, pr->pr_physical->pi_name);
2166         } else {
2167                 fprintdate(stderr);
2168                 (void) fprintf(stderr, "%s (prefix %s if %s): %s\n",
2169                     str, pr->pr_name, pr->pr_physical->pi_name,
2170                     strerror(errno));
2171         }
2172 }
2173 
2174 static int
2175 ndpd_setup_cmd_listener(void)
2176 {
2177         int sock;
2178         int ret;
2179         struct sockaddr_un servaddr;
2180 
2181         sock = socket(AF_UNIX, SOCK_STREAM, 0);
2182         if (sock < 0) {
2183                 logperror("socket");
2184                 exit(1);
2185         }
2186 
2187         bzero(&servaddr, sizeof (servaddr));
2188         servaddr.sun_family = AF_UNIX;
2189         (void) strlcpy(servaddr.sun_path, IPADM_UDS_PATH,
2190             sizeof (servaddr.sun_path));
2191         (void) unlink(servaddr.sun_path);
2192         ret = bind(sock, (struct sockaddr *)&servaddr, sizeof (servaddr));
2193         if (ret < 0) {
2194                 logperror("bind");
2195                 exit(1);
2196         }
2197         if (listen(sock, 30) < 0) {
2198                 logperror("listen");
2199                 exit(1);
2200         }
2201         if (poll_add(sock) == -1) {
2202                 logmsg(LOG_ERR, "command socket could not be added to the "
2203                     "polling set\n");
2204                 exit(1);
2205         }
2206 
2207         return (sock);
2208 }
2209 
2210 /*
2211  * Commands received over the command socket come here
2212  */
2213 static void
2214 ndpd_cmd_handler(int sock)
2215 {
2216         int                     newfd;
2217         struct sockaddr_storage peer;
2218         socklen_t               peerlen;
2219         ipadm_ndpd_msg_t        ndpd_msg;
2220         int                     retval;
2221 
2222         peerlen = sizeof (peer);
2223         newfd = accept(sock, (struct sockaddr *)&peer, &peerlen);
2224         if (newfd < 0) {
2225                 logperror("accept");
2226                 return;
2227         }
2228 
2229         retval = ipadm_ndpd_read(newfd, &ndpd_msg, sizeof (ndpd_msg));
2230         if (retval != 0)
2231                 logperror("Could not read ndpd command");
2232 
2233         retval = ndpd_process_cmd(newfd, &ndpd_msg);
2234         if (retval != 0) {
2235                 logmsg(LOG_ERR, "ndpd command on interface %s failed with "
2236                     "error %s\n", ndpd_msg.inm_ifname, strerror(retval));
2237         }
2238         (void) close(newfd);
2239 }
2240 
2241 /*
2242  * Process the commands received from the cmd listener socket.
2243  */
2244 static int
2245 ndpd_process_cmd(int newfd, ipadm_ndpd_msg_t *msg)
2246 {
2247         int err;
2248 
2249         if (!ipadm_check_auth()) {
2250                 logmsg(LOG_ERR, "User not authorized to send the command\n");
2251                 (void) ndpd_send_error(newfd, EPERM);
2252                 return (EPERM);
2253         }
2254         switch (msg->inm_cmd) {
2255         case IPADM_DISABLE_AUTOCONF:
2256                 err = ndpd_set_autoconf(msg->inm_ifname, _B_FALSE);
2257                 break;
2258 
2259         case IPADM_ENABLE_AUTOCONF:
2260                 err = ndpd_set_autoconf(msg->inm_ifname, _B_TRUE);
2261                 break;
2262 
2263         case IPADM_CREATE_ADDRS:
2264                 err = ndpd_create_addrs(msg->inm_ifname, msg->inm_intfid,
2265                     msg->inm_intfidlen, msg->inm_stateless,
2266                     msg->inm_stateful, msg->inm_aobjname);
2267                 break;
2268 
2269         case IPADM_DELETE_ADDRS:
2270                 err = ndpd_delete_addrs(msg->inm_ifname);
2271                 break;
2272 
2273         default:
2274                 err = EINVAL;
2275                 break;
2276         }
2277 
2278         (void) ndpd_send_error(newfd, err);
2279 
2280         return (err);
2281 }
2282 
2283 static int
2284 ndpd_send_error(int fd, int error)
2285 {
2286         return (ipadm_ndpd_write(fd, &error, sizeof (error)));
2287 }
2288 
2289 /*
2290  * Disables/Enables autoconfiguration of addresses on the
2291  * given physical interface.
2292  * This is provided to support the legacy method of configuring IPv6
2293  * addresses. i.e. `ifconfig bge0 inet6 plumb` will plumb the interface
2294  * and start stateless and stateful autoconfiguration. If this function is
2295  * not called with enable=_B_FALSE, no autoconfiguration will be done until
2296  * ndpd_create_addrs() is called with an Interface ID.
2297  */
2298 static int
2299 ndpd_set_autoconf(const char *ifname, boolean_t enable)
2300 {
2301         struct phyint *pi;
2302 
2303         pi = phyint_lookup((char *)ifname);
2304         if (pi == NULL) {
2305                 /*
2306                  * If the physical interface was plumbed but no
2307                  * addresses were configured yet, phyint will not exist.
2308                  */
2309                 pi = phyint_create((char *)ifname);
2310                 if (pi == NULL) {
2311                         logmsg(LOG_ERR, "could not create phyint for "
2312                             "interface %s", ifname);
2313                         return (ENOMEM);
2314                 }
2315         }
2316         pi->pi_autoconf = enable;
2317 
2318         if (debug & D_PHYINT) {
2319                 logmsg(LOG_DEBUG, "ndpd_set_autoconf: %s autoconf for "
2320                     "interface %s\n", (enable ? "enabled" : "disabled"),
2321                     pi->pi_name);
2322         }
2323         return (0);
2324 }
2325 
2326 /*
2327  * Create auto-configured addresses on the given interface using
2328  * the given token as the interface id during the next Router Advertisement.
2329  * Currently, only one token per interface is supported.
2330  */
2331 static int
2332 ndpd_create_addrs(const char *ifname, struct sockaddr_in6 intfid, int intfidlen,
2333     boolean_t stateless, boolean_t stateful, char *addrobj)
2334 {
2335         struct phyint *pi;
2336         struct lifreq lifr;
2337         struct sockaddr_in6 *sin6;
2338         int err;
2339 
2340         pi = phyint_lookup((char *)ifname);
2341         if (pi == NULL) {
2342                 /*
2343                  * If the physical interface was plumbed but no
2344                  * addresses were configured yet, phyint will not exist.
2345                  */
2346                 pi = phyint_create((char *)ifname);
2347                 if (pi == NULL) {
2348                         if (debug & D_PHYINT)
2349                                 logmsg(LOG_ERR, "could not create phyint "
2350                                     "for interface %s", ifname);
2351                         return (ENOMEM);
2352                 }
2353         } else if (pi->pi_autoconf) {
2354                 logmsg(LOG_ERR, "autoconfiguration already in progress\n");
2355                 return (EEXIST);
2356         }
2357         check_autoconf_var_consistency(pi, stateless, stateful);
2358 
2359         if (intfidlen == 0) {
2360                 pi->pi_default_token = _B_TRUE;
2361                 if (ifsock < 0) {
2362                         ifsock = socket(AF_INET6, SOCK_DGRAM, 0);
2363                         if (ifsock < 0) {
2364                                 err = errno;
2365                                 logperror("ndpd_create_addrs: socket");
2366                                 return (err);
2367                         }
2368                 }
2369                 (void) strncpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
2370                 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
2371                 if (ioctl(ifsock, SIOCGLIFTOKEN, (char *)&lifr) < 0) {
2372                         err = errno;
2373                         logperror("SIOCGLIFTOKEN");
2374                         return (err);
2375                 }
2376                 pi->pi_token = sin6->sin6_addr;
2377                 pi->pi_token_length = lifr.lifr_addrlen;
2378         } else {
2379                 pi->pi_default_token = _B_FALSE;
2380                 pi->pi_token = intfid.sin6_addr;
2381                 pi->pi_token_length = intfidlen;
2382         }
2383         pi->pi_stateless = stateless;
2384         pi->pi_stateful = stateful;
2385         (void) strlcpy(pi->pi_ipadm_aobjname, addrobj,
2386             sizeof (pi->pi_ipadm_aobjname));
2387 
2388         /* We can allow autoconfiguration now. */
2389         pi->pi_autoconf = _B_TRUE;
2390 
2391         /* Restart the solicitations. */
2392         if (pi->pi_sol_state == DONE_SOLICIT)
2393                 pi->pi_sol_state = NO_SOLICIT;
2394         if (pi->pi_sol_state == NO_SOLICIT)
2395                 check_to_solicit(pi, START_INIT_SOLICIT);
2396         if (debug & D_PHYINT)
2397                 logmsg(LOG_DEBUG, "ndpd_create_addrs: "
2398                     "added token to interface %s\n", pi->pi_name);
2399         return (0);
2400 }
2401 
2402 /*
2403  * This function deletes all addresses on the given interface
2404  * with the given Interface ID.
2405  */
2406 static int
2407 ndpd_delete_addrs(const char *ifname)
2408 {
2409         struct phyint *pi;
2410         struct prefix *pr, *next_pr;
2411         struct lifreq lifr;
2412         int err;
2413 
2414         pi = phyint_lookup((char *)ifname);
2415         if (pi == NULL) {
2416                 logmsg(LOG_ERR, "no phyint found for %s", ifname);
2417                 return (ENXIO);
2418         }
2419         if (IN6_IS_ADDR_UNSPECIFIED(&pi->pi_token)) {
2420                 logmsg(LOG_ERR, "token does not exist for %s", ifname);
2421                 return (EINVAL);
2422         }
2423 
2424         if (ifsock < 0) {
2425                 ifsock = socket(AF_INET6, SOCK_DGRAM, 0);
2426                 if (ifsock < 0) {
2427                         err = errno;
2428                         logperror("ndpd_create_addrs: socket");
2429                         return (err);
2430                 }
2431         }
2432         /* Remove the prefixes for this phyint if they exist */
2433         for (pr = pi->pi_prefix_list; pr != NULL; pr = next_pr) {
2434                 next_pr = pr->pr_next;
2435                 if (pr->pr_name[0] == '\0') {
2436                         prefix_delete(pr);
2437                         continue;
2438                 }
2439                 /*
2440                  * Delete all the prefixes for the auto-configured
2441                  * addresses as well as the DHCPv6 addresses.
2442                  */
2443                 (void) strncpy(lifr.lifr_name, pr->pr_name,
2444                     sizeof (lifr.lifr_name));
2445                 if (ioctl(ifsock, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
2446                         err = errno;
2447                         logperror("SIOCGLIFFLAGS");
2448                         return (err);
2449                 }
2450                 if ((lifr.lifr_flags & IFF_ADDRCONF) ||
2451                     (lifr.lifr_flags & IFF_DHCPRUNNING)) {
2452                         prefix_update_ipadm_addrobj(pr, _B_FALSE);
2453                 }
2454                 prefix_delete(pr);
2455         }
2456 
2457         /*
2458          * If we had started dhcpagent, we need to release the leases
2459          * if any are required.
2460          */
2461         if (pi->pi_stateful) {
2462                 (void) strncpy(lifr.lifr_name, pi->pi_name,
2463                     sizeof (lifr.lifr_name));
2464                 if (ioctl(ifsock, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
2465                         err = errno;
2466                         logperror("SIOCGLIFFLAGS");
2467                         return (err);
2468                 }
2469                 if (lifr.lifr_flags & IFF_DHCPRUNNING)
2470                         release_dhcp(pi);
2471         }
2472 
2473         /*
2474          * Reset the Interface ID on this phyint and stop autoconfigurations
2475          * until a new interface ID is provided.
2476          */
2477         pi->pi_token = in6addr_any;
2478         pi->pi_token_length = 0;
2479         pi->pi_autoconf = _B_FALSE;
2480         pi->pi_ipadm_aobjname[0] = '\0';
2481 
2482         /* Reset the stateless and stateful settings to default. */
2483         pi->pi_stateless = pi->pi_StatelessAddrConf;
2484         pi->pi_stateful = pi->pi_StatefulAddrConf;
2485 
2486         if (debug & D_PHYINT) {
2487                 logmsg(LOG_DEBUG, "ndpd_delete_addrs: "
2488                     "removed token from interface %s\n", pi->pi_name);
2489         }
2490         return (0);
2491 }
2492 
2493 void
2494 check_autoconf_var_consistency(struct phyint *pi, boolean_t stateless,
2495     boolean_t stateful)
2496 {
2497         /*
2498          * If StatelessAddrConf and StatelessAddrConf are set in
2499          * /etc/inet/ndpd.conf, check if the new values override those
2500          * settings. If so, log a warning.
2501          */
2502         if ((pi->pi_StatelessAddrConf !=
2503             ifdefaults[I_StatelessAddrConf].cf_value &&
2504             stateless != pi->pi_StatelessAddrConf) ||
2505             (pi->pi_StatefulAddrConf !=
2506             ifdefaults[I_StatefulAddrConf].cf_value &&
2507             stateful != pi->pi_StatefulAddrConf)) {
2508                 logmsg(LOG_ERR, "check_autoconf_var_consistency: "
2509                     "Overriding the StatelessAddrConf or StatefulAddrConf "
2510                     "settings in ndpd.conf with the new values for "
2511                     "interface %s\n", pi->pi_name);
2512         }
2513 }
2514 
2515 /*
2516  * If ipadm was used to start autoconfiguration and in.ndpd was restarted
2517  * for some reason, in.ndpd has to resume autoconfiguration when it comes up.
2518  * In this function, it scans the ipadm_addr_info() output to find a link-local
2519  * on this interface with address type "addrconf" and extracts the interface id.
2520  * It also stores the addrobj name to be used later when new addresses are
2521  * created for the prefixes advertised by the router.
2522  * If autoconfiguration was never started on this interface before in.ndpd
2523  * was killed, then in.ndpd should refrain from configuring prefixes, even if
2524  * there is a valid link-local on this interface, created by ipadm (identified
2525  * if there is a valid addrobj name).
2526  */
2527 static int
2528 phyint_check_ipadm_intfid(struct phyint *pi)
2529 {
2530         ipadm_status_t          status;
2531         ipadm_addr_info_t       *addrinfo;
2532         struct ifaddrs          *ifap;
2533         ipadm_addr_info_t       *ainfop;
2534         struct sockaddr_in6     *sin6;
2535         ipadm_handle_t          iph;
2536 
2537         if (ipadm_open(&iph, 0) != IPADM_SUCCESS) {
2538                 logmsg(LOG_ERR, "could not open handle to libipadm\n");
2539                 return (-1);
2540         }
2541 
2542         status = ipadm_addr_info(iph, pi->pi_name, &addrinfo,
2543             IPADM_OPT_ZEROADDR, LIFC_NOXMIT|LIFC_TEMPORARY);
2544         if (status != IPADM_SUCCESS) {
2545                 ipadm_close(iph);
2546                 return (-1);
2547         }
2548         pi->pi_autoconf = _B_TRUE;
2549         for (ainfop = addrinfo; ainfop != NULL; ainfop = IA_NEXT(ainfop)) {
2550                 ifap = &ainfop->ia_ifa;
2551                 if (ifap->ifa_addr->sa_family != AF_INET6 ||
2552                     ainfop->ia_state == IFA_DISABLED)
2553                         continue;
2554                 sin6 = (struct sockaddr_in6 *)ifap->ifa_addr;
2555                 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
2556                         if (ainfop->ia_atype == IPADM_ADDR_IPV6_ADDRCONF) {
2557                                 pi->pi_token = sin6->sin6_addr;
2558                                 pi->pi_token._S6_un._S6_u32[0] = 0;
2559                                 pi->pi_token._S6_un._S6_u32[1] = 0;
2560                                 pi->pi_autoconf = _B_TRUE;
2561                                 (void) strlcpy(pi->pi_ipadm_aobjname,
2562                                     ainfop->ia_aobjname,
2563                                     sizeof (pi->pi_ipadm_aobjname));
2564                                 break;
2565                         }
2566                         /*
2567                          * If IFF_NOLINKLOCAL is set, then the link-local
2568                          * was created using ipadm. Do not autoconfigure until
2569                          * ipadm is explicitly used for autoconfiguration.
2570                          */
2571                         if (ifap->ifa_flags & IFF_NOLINKLOCAL)
2572                                 pi->pi_autoconf = _B_FALSE;
2573                 } else if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
2574                     strrchr(ifap->ifa_name, ':') == NULL) {
2575                         /* The interface was created using ipadm. */
2576                         pi->pi_autoconf = _B_FALSE;
2577                 }
2578         }
2579         ipadm_free_addr_info(addrinfo);
2580         if (!pi->pi_autoconf) {
2581                 pi->pi_token = in6addr_any;
2582                 pi->pi_token_length = 0;
2583         }
2584         ipadm_close(iph);
2585         return (0);
2586 }