Print this page
    
OS-4335 ipadm_door_call should work in a branded zone without chroot
OS-4336 ipmgmtd should work in a branded zone without chroot
Reviewed by: Robert Mustacchi <rm@joyent.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c
          +++ new/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  
    | 
      ↓ open down ↓ | 
    13 lines elided | 
    
      ↑ open up ↑ | 
  
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
       24 + * Copyright 2015 Joyent, Inc.
  24   25   */
  25   26  
  26   27  /*
  27   28   * The ipmgmtd daemon is started by ip-interface-management SMF service. This
  28   29   * daemon is used to manage, mapping of 'address object' to 'interface name' and
  29   30   * 'logical interface number', on which the address is created. It also provides
  30   31   * a means to update the ipadm persistent data-store.
  31   32   *
  32   33   * The daemon tracks the <addrobj, lifname> mapping in-memory using a linked
  33   34   * list `aobjmap'. Access to this list is synchronized using a readers-writers
  34   35   * lock. The active <addrobj, lifname> mapping is kept in
  35   36   * /etc/svc/volatile/ipadm/aobjmap.conf cache file, so that the mapping can be
  36   37   * recovered when ipmgmtd exits for some reason (e.g., when ipmgmtd is restarted
  37   38   * using svcadm or accidentally killed).
  38   39   *
  39   40   * Today, the persistent configuration of interfaces, addresses and protocol
  40   41   * properties is kept in /etc/ipadm/ipadm.conf. The access to the persistent
  41   42   * data store is synchronized using reader-writers lock `ipmgmt_dbconf_lock'.
  42   43   *
  43   44   * The communication between the library, libipadm.so and the daemon, is through
  44   45   * doors RPC. The library interacts with the daemon using the commands defined
  45   46   * by `ipmgmt_door_cmd_type_t'. Further any 'write' operation would require
  46   47   * the `NETWORK_INTERFACE_CONFIG_AUTH' authorization.
  47   48   *
  48   49   * On reboot, the aforementioned SMF service starts the daemon before any other
  49   50   * networking service that configures network IP interfaces is started.
  50   51   * Afterwards, the network/physical SMF script instantiates the persisted
  51   52   * network interfaces, interface properties and addresses.
  52   53   */
  53   54  
  54   55  #include <errno.h>
  55   56  #include <fcntl.h>
  56   57  #include <priv_utils.h>
  57   58  #include <signal.h>
  58   59  #include <stdlib.h>
  59   60  #include <stdio.h>
  60   61  #include <strings.h>
  61   62  #include <sys/param.h>
  62   63  #include <sys/stat.h>
  63   64  #include <unistd.h>
  64   65  #include "ipmgmt_impl.h"
  65   66  #include <zone.h>
  66   67  #include <libipadm.h>
  67   68  #include <libdladm.h>
  68   69  #include <libdllink.h>
  69   70  #include <net/route.h>
  70   71  #include <ipadm_ipmgmt.h>
  71   72  #include <sys/brand.h>
  72   73  
  73   74  const char              *progname;
  74   75  
  75   76  /* readers-writers lock for reading/writing daemon data store */
  76   77  pthread_rwlock_t        ipmgmt_dbconf_lock = PTHREAD_RWLOCK_INITIALIZER;
  77   78  
  78   79  /* tracks address object to {ifname|logical number|interface id} mapping */
  79   80  ipmgmt_aobjmap_list_t   aobjmap;
  80   81  
  81   82  /* used to communicate failure to parent process, which spawned the daemon */
  82   83  static int              pfds[2];
  83   84  
  84   85  /* file descriptor to IPMGMT_DOOR */
  85   86  static int              ipmgmt_door_fd = -1;
  86   87  
  87   88  static void             ipmgmt_exit(int);
  88   89  static int              ipmgmt_init();
  89   90  static int              ipmgmt_init_privileges();
  90   91  static void             ipmgmt_ngz_persist_if();
  91   92  
  92   93  static ipadm_handle_t iph;
  93   94  typedef struct ipmgmt_pif_s {
  94   95          struct ipmgmt_pif_s     *pif_next;
  95   96          char                    pif_ifname[LIFNAMSIZ];
  96   97          boolean_t               pif_v4;
  97   98          boolean_t               pif_v6;
  
    | 
      ↓ open down ↓ | 
    64 lines elided | 
    
      ↑ open up ↑ | 
  
  98   99  } ipmgmt_pif_t;
  99  100  
 100  101  static ipmgmt_pif_t *ngz_pifs;
 101  102  
 102  103  static int
 103  104  ipmgmt_db_init()
 104  105  {
 105  106          int             fd, err, scferr;
 106  107          scf_resources_t res;
 107  108          boolean_t       upgrade = B_TRUE;
      109 +        char            aobjpath[MAXPATHLEN];
 108  110  
 109  111          /*
 110  112           * Check to see if we need to upgrade the data-store. We need to
 111  113           * upgrade, if the version of the data-store does not match with
 112  114           * IPADM_DB_VERSION. Further, if we cannot determine the current
 113  115           * version of the data-store, we always err on the side of caution
 114  116           * and upgrade the data-store to current version.
 115  117           */
 116  118          if ((scferr = ipmgmt_create_scf_resources(IPMGMTD_FMRI, &res)) == 0)
 117  119                  upgrade = ipmgmt_needs_upgrade(&res);
 118  120          if (upgrade) {
 119  121                  err = ipmgmt_db_walk(ipmgmt_db_upgrade, NULL, IPADM_DB_WRITE);
 120  122                  if (err != 0) {
 121  123                          ipmgmt_log(LOG_ERR, "could not upgrade the "
 122  124                              "ipadm data-store: %s", strerror(err));
 123  125                          err = 0;
 124  126                  } else {
 125  127                          /*
 126  128                           * upgrade was success, let's update SCF with the
  
    | 
      ↓ open down ↓ | 
    9 lines elided | 
    
      ↑ open up ↑ | 
  
 127  129                           * current data-store version number.
 128  130                           */
 129  131                          if (scferr == 0)
 130  132                                  ipmgmt_update_dbver(&res);
 131  133                  }
 132  134          }
 133  135          if (scferr == 0)
 134  136                  ipmgmt_release_scf_resources(&res);
 135  137  
 136  138          /* creates the address object data store, if it doesn't exist */
 137      -        if ((fd = open(ADDROBJ_MAPPING_DB_FILE, O_CREAT|O_RDONLY,
 138      -            IPADM_FILE_MODE)) == -1) {
      139 +        ipmgmt_path(IPADM_PATH_ADDROBJ_MAP_DB, aobjpath, sizeof (aobjpath));
      140 +        if ((fd = open(aobjpath, O_CREAT|O_RDONLY, IPADM_FILE_MODE)) == -1) {
 139  141                  err = errno;
 140      -                ipmgmt_log(LOG_ERR, "could not open %s: %s",
 141      -                    ADDROBJ_MAPPING_DB_FILE, strerror(err));
      142 +                ipmgmt_log(LOG_ERR, "could not open %s: %s", aobjpath,
      143 +                    strerror(err));
 142  144                  return (err);
 143  145          }
 144  146          (void) close(fd);
 145  147  
 146  148          aobjmap.aobjmap_head = NULL;
 147  149          (void) pthread_rwlock_init(&aobjmap.aobjmap_rwlock, NULL);
 148  150  
 149  151          /*
 150  152           * If the daemon is recovering from a crash or restart, read the
 151  153           * address object to logical interface mapping and build an in-memory
 152  154           * representation of the mapping. That is, build `aobjmap' structure
 153  155           * from address object data store.
 154  156           */
 155      -        if ((err = ipadm_rw_db(ipmgmt_aobjmap_init, NULL,
 156      -            ADDROBJ_MAPPING_DB_FILE, 0, IPADM_DB_READ)) != 0) {
      157 +        if ((err = ipadm_rw_db(ipmgmt_aobjmap_init, NULL, aobjpath, 0,
      158 +            IPADM_DB_READ)) != 0) {
 157  159                  /* if there was nothing to initialize, it's fine */
 158  160                  if (err != ENOENT)
 159  161                          return (err);
 160  162                  err = 0;
 161  163          }
 162  164  
 163  165          ipmgmt_ngz_persist_if(); /* create persistent interface info for NGZ */
 164  166  
 165  167          return (err);
 166  168  }
 167  169  
      170 +static const char *
      171 +ipmgmt_door_path()
      172 +{
      173 +        static char door[MAXPATHLEN];
      174 +        static boolean_t init_done = B_FALSE;
      175 +
      176 +        if (!init_done) {
      177 +                const char *zroot = zone_get_nroot();
      178 +
      179 +                /*
      180 +                 * If this is a branded zone, make sure we use the "/native"
      181 +                 * prefix for the door path:
      182 +                 */
      183 +                (void) snprintf(door, sizeof (door), "%s%s", zroot != NULL ?
      184 +                    zroot : "", IPMGMT_DOOR);
      185 +
      186 +                init_done = B_TRUE;
      187 +        }
      188 +
      189 +        return (door);
      190 +}
      191 +
 168  192  static int
 169  193  ipmgmt_door_init()
 170  194  {
 171  195          int fd;
 172  196          int err;
      197 +        const char *door = ipmgmt_door_path();
 173  198  
 174      -        /* create the door file for ipmgmtd */
 175      -        if ((fd = open(IPMGMT_DOOR, O_CREAT|O_RDONLY, IPADM_FILE_MODE)) == -1) {
      199 +        /*
      200 +         * Create the door file for ipmgmtd.
      201 +         */
      202 +        if ((fd = open(door, O_CREAT | O_RDONLY, IPADM_FILE_MODE)) == -1) {
 176  203                  err = errno;
 177      -                ipmgmt_log(LOG_ERR, "could not open %s: %s",
 178      -                    IPMGMT_DOOR, strerror(err));
      204 +                ipmgmt_log(LOG_ERR, "could not open %s: %s", door,
      205 +                    strerror(err));
 179  206                  return (err);
 180  207          }
 181  208          (void) close(fd);
 182  209  
 183  210          if ((ipmgmt_door_fd = door_create(ipmgmt_handler, NULL,
 184  211              DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) == -1) {
 185  212                  err = errno;
 186  213                  ipmgmt_log(LOG_ERR, "failed to create door: %s", strerror(err));
 187  214                  return (err);
 188  215          }
      216 +
 189  217          /*
 190  218           * fdetach first in case a previous daemon instance exited
 191  219           * ungracefully.
 192  220           */
 193      -        (void) fdetach(IPMGMT_DOOR);
 194      -        if (fattach(ipmgmt_door_fd, IPMGMT_DOOR) != 0) {
      221 +        (void) fdetach(door);
      222 +        if (fattach(ipmgmt_door_fd, door) != 0) {
 195  223                  err = errno;
 196      -                ipmgmt_log(LOG_ERR, "failed to attach door to %s: %s",
 197      -                    IPMGMT_DOOR, strerror(err));
      224 +                ipmgmt_log(LOG_ERR, "failed to attach door to %s: %s", door,
      225 +                    strerror(err));
 198  226                  goto fail;
 199  227          }
 200  228          return (0);
 201  229  fail:
 202  230          (void) door_revoke(ipmgmt_door_fd);
 203  231          ipmgmt_door_fd = -1;
 204  232          return (err);
 205  233  }
 206  234  
 207  235  static void
 208  236  ipmgmt_door_fini()
 209  237  {
      238 +        const char *door = ipmgmt_door_path();
      239 +
 210  240          if (ipmgmt_door_fd == -1)
 211  241                  return;
 212  242  
 213      -        (void) fdetach(IPMGMT_DOOR);
      243 +        (void) fdetach(door);
 214  244          if (door_revoke(ipmgmt_door_fd) == -1) {
 215  245                  ipmgmt_log(LOG_ERR, "failed to revoke access to door %s: %s",
 216      -                    IPMGMT_DOOR, strerror(errno));
      246 +                    door, strerror(errno));
 217  247          }
 218  248  }
 219  249  
 220  250  static int
 221  251  ipmgmt_init()
 222  252  {
 223  253          int err;
 224  254  
 225  255          if (signal(SIGTERM, ipmgmt_exit) == SIG_ERR ||
 226  256              signal(SIGINT, ipmgmt_exit) == SIG_ERR) {
 227  257                  err = errno;
 228  258                  ipmgmt_log(LOG_ERR, "signal() for SIGTERM/INT failed: %s",
 229  259                      strerror(err));
 230  260                  return (err);
 231  261          }
 232  262          if ((err = ipmgmt_db_init()) != 0 || (err = ipmgmt_door_init()) != 0)
 233  263                  return (err);
 234  264          return (0);
 235  265  }
 236  266  
 237  267  /*
 238  268   * This is called by the child process to inform the parent process to
 239  269   * exit with the given return value.
 240  270   */
 241  271  static void
 242  272  ipmgmt_inform_parent_exit(int rv)
 243  273  {
 244  274          if (write(pfds[1], &rv, sizeof (int)) != sizeof (int)) {
 245  275                  ipmgmt_log(LOG_WARNING,
 246  276                      "failed to inform parent process of status: %s",
 247  277                      strerror(errno));
 248  278                  (void) close(pfds[1]);
 249  279                  exit(EXIT_FAILURE);
 250  280          }
 251  281          (void) close(pfds[1]);
 252  282  }
 253  283  
 254  284  /*ARGSUSED*/
 255  285  static void
 256  286  ipmgmt_exit(int signo)
 257  287  {
 258  288          (void) close(pfds[1]);
 259  289          ipmgmt_door_fini();
 260  290          exit(EXIT_FAILURE);
 261  291  }
 262  292  
 263  293  /*
 264  294   * On the first reboot after installation of an ipkg zone,
 265  295   * ipmgmt_persist_if_cb() is used in non-global zones to track the interfaces
 266  296   * that have IP address configuration assignments from the global zone.
 267  297   * Persistent configuration for the interfaces is created on the first boot
 268  298   * by ipmgmtd, and the addresses assigned to the interfaces by the GZ
 269  299   * will be subsequently configured when the interface is enabled.
 270  300   * Note that ipmgmt_persist_if_cb() only sets up a list of interfaces
 271  301   * that need to be persisted- the actual update of the ipadm data-store happens
 272  302   * in ipmgmt_persist_if() after the appropriate privs/uid state has been set up.
 273  303   */
 274  304  static void
 275  305  ipmgmt_persist_if_cb(char *ifname, boolean_t v4, boolean_t v6)
 276  306  {
 277  307          ipmgmt_pif_t *pif;
 278  308  
 279  309          pif = calloc(1, sizeof (*pif));
 280  310          if (pif == NULL) {
 281  311                  ipmgmt_log(LOG_WARNING,
 282  312                      "Could not allocate memory to configure %s", ifname);
 283  313                  return;
 284  314          }
 285  315          (void) strlcpy(pif->pif_ifname, ifname, sizeof (pif->pif_ifname));
 286  316          pif->pif_v4 = v4;
 287  317          pif->pif_v6 = v6;
 288  318          pif->pif_next = ngz_pifs;
 289  319          ngz_pifs = pif;
 290  320  }
 291  321  
 292  322  /*
 293  323   * ipmgmt_ngz_init() initializes exclusive-IP stack non-global zones by
 294  324   * extracting configuration that has been saved in the kernel and applying
 295  325   * it at zone boot.
 296  326   */
 297  327  static void
 298  328  ipmgmt_ngz_init()
 299  329  {
 300  330          zoneid_t zoneid;
 301  331          boolean_t firstboot = B_TRUE, s10c = B_FALSE;
 302  332          char brand[MAXNAMELEN];
 303  333          ipadm_status_t ipstatus;
 304  334  
 305  335          zoneid = getzoneid();
 306  336          if (zoneid != GLOBAL_ZONEID) {
 307  337  
 308  338                  if (zone_getattr(zoneid, ZONE_ATTR_BRAND, brand,
 309  339                      sizeof (brand)) < 0) {
 310  340                          ipmgmt_log(LOG_ERR, "Could not get brand name");
 311  341                          return;
 312  342                  }
 313  343                  /*
 314  344                   * firstboot is always true for S10C zones, where ipadm is not
 315  345                   * available for restoring persistent configuration.
 316  346                   */
 317  347                  if (strcmp(brand, NATIVE_BRAND_NAME) == 0)
 318  348                          firstboot = ipmgmt_ngz_firstboot_postinstall();
 319  349                  else
 320  350                          s10c = B_TRUE;
 321  351  
 322  352                  if (!firstboot)
 323  353                          return;
 324  354  
 325  355                  ipstatus = ipadm_open(&iph, IPH_IPMGMTD);
 326  356                  if (ipstatus != IPADM_SUCCESS) {
 327  357                          ipmgmt_log(LOG_ERR, "could not open ipadm handle",
 328  358                              ipadm_status2str(ipstatus));
 329  359                          return;
 330  360                  }
 331  361                  /*
 332  362                   * Only pass down the callback to persist the interface
 333  363                   * for NATIVE (ipkg) zones.
 334  364                   */
 335  365                  (void) ipadm_init_net_from_gz(iph, NULL,
 336  366                      (s10c ? NULL : ipmgmt_persist_if_cb));
 337  367                  ipadm_close(iph);
 338  368          }
 339  369  }
 340  370  
 341  371  /*
 342  372   * Set the uid of this daemon to the "netadm" user. Finish the following
  
    | 
      ↓ open down ↓ | 
    116 lines elided | 
    
      ↑ open up ↑ | 
  
 343  373   * operations before setuid() because they need root privileges:
 344  374   *
 345  375   *    - create the /etc/svc/volatile/ipadm directory;
 346  376   *    - change its uid/gid to "netadm"/"netadm";
 347  377   */
 348  378  static int
 349  379  ipmgmt_init_privileges()
 350  380  {
 351  381          struct stat     statbuf;
 352  382          int             err;
      383 +        char            tmpfsdir[MAXPATHLEN];
 353  384  
 354      -        /* create the IPADM_TMPFS_DIR directory */
 355      -        if (stat(IPADM_TMPFS_DIR, &statbuf) < 0) {
 356      -                if (mkdir(IPADM_TMPFS_DIR, (mode_t)0755) < 0) {
      385 +        /*
      386 +         * Create the volatile storage directory:
      387 +         */
      388 +        ipmgmt_path(IPADM_PATH_TMPFS_DIR, tmpfsdir, sizeof (tmpfsdir));
      389 +        if (stat(tmpfsdir, &statbuf) < 0) {
      390 +                if (mkdir(tmpfsdir, (mode_t)0755) < 0) {
 357  391                          err = errno;
 358  392                          goto fail;
 359  393                  }
 360  394          } else {
 361  395                  if ((statbuf.st_mode & S_IFMT) != S_IFDIR) {
 362  396                          err = ENOTDIR;
 363  397                          goto fail;
 364  398                  }
 365  399          }
 366  400  
 367      -        if ((chmod(IPADM_TMPFS_DIR, 0755) < 0) ||
 368      -            (chown(IPADM_TMPFS_DIR, UID_NETADM, GID_NETADM) < 0)) {
      401 +        if ((chmod(tmpfsdir, 0755) < 0) ||
      402 +            (chown(tmpfsdir, UID_NETADM, GID_NETADM) < 0)) {
 369  403                  err = errno;
 370  404                  goto fail;
 371  405          }
 372  406  
 373  407          /*
 374  408           * initialize any NGZ specific network information before dropping
 375  409           * privileges. We need these privileges to plumb IP interfaces handed
 376  410           * down from the GZ (for dlpi_open() etc.) and also to configure the
 377  411           * address itself (for any IPI_PRIV ioctls like SLIFADDR)
 378  412           */
 379  413          ipmgmt_ngz_init();
 380  414  
 381  415          /*
 382  416           * Apply all protocol module properties. We need to apply all protocol
 383  417           * properties before we drop root privileges.
 384  418           */
 385  419          ipmgmt_init_prop();
 386  420  
 387  421          /*
 388  422           * limit the privileges of this daemon and set the uid of this
 389  423           * daemon to UID_NETADM
 390  424           */
 391  425          if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, UID_NETADM,
 392  426              GID_NETADM, NULL) == -1) {
 393  427                  err = EPERM;
 394  428                  goto fail;
 395  429          }
 396  430  
 397  431          return (0);
 398  432  fail:
 399  433          (void) ipmgmt_log(LOG_ERR, "failed to initialize the daemon: %s",
 400  434              strerror(err));
 401  435          return (err);
 402  436  }
 403  437  
 404  438  /*
 405  439   * Keep the pfds fd open, close other fds.
 406  440   */
 407  441  /*ARGSUSED*/
 408  442  static int
 409  443  closefunc(void *arg, int fd)
 410  444  {
 411  445          if (fd != pfds[1])
 412  446                  (void) close(fd);
 413  447          return (0);
 414  448  }
 415  449  
 416  450  /*
 417  451   * We cannot use libc's daemon() because the door we create is associated with
 418  452   * the process ID. If we create the door before the call to daemon(), it will
 419  453   * be associated with the parent and it's incorrect. On the other hand if we
 420  454   * create the door later, after the call to daemon(), parent process exits
 421  455   * early and gives a false notion to SMF that 'ipmgmtd' is up and running,
 422  456   * which is incorrect. So, we have our own daemon() equivalent.
 423  457   */
 424  458  static boolean_t
 425  459  ipmgmt_daemonize(void)
 426  460  {
 427  461          pid_t pid;
 428  462          int rv;
 429  463  
 430  464          if (pipe(pfds) < 0) {
 431  465                  (void) fprintf(stderr, "%s: pipe() failed: %s\n",
 432  466                      progname, strerror(errno));
 433  467                  exit(EXIT_FAILURE);
 434  468          }
 435  469  
 436  470          if ((pid = fork()) == -1) {
 437  471                  (void) fprintf(stderr, "%s: fork() failed: %s\n",
 438  472                      progname, strerror(errno));
 439  473                  exit(EXIT_FAILURE);
 440  474          } else if (pid > 0) { /* Parent */
 441  475                  (void) close(pfds[1]);
 442  476  
 443  477                  /*
 444  478                   * Parent should not exit early, it should wait for the child
 445  479                   * to return Success/Failure. If the parent exits early, then
 446  480                   * SMF will think 'ipmgmtd' is up and would start all the
 447  481                   * depended services.
 448  482                   *
 449  483                   * If the child process exits unexpectedly, read() returns -1.
 450  484                   */
 451  485                  if (read(pfds[0], &rv, sizeof (int)) != sizeof (int)) {
 452  486                          (void) kill(pid, SIGKILL);
 453  487                          rv = EXIT_FAILURE;
 454  488                  }
 455  489  
 456  490                  (void) close(pfds[0]);
 457  491                  exit(rv);
 458  492          }
 459  493  
 460  494          /* Child */
 461  495          (void) close(pfds[0]);
 462  496          (void) setsid();
 463  497  
 464  498          /* close all files except pfds[1] */
 465  499          (void) fdwalk(closefunc, NULL);
 466  500          (void) chdir("/");
 467  501          openlog(progname, LOG_PID, LOG_DAEMON);
 468  502          return (B_TRUE);
 469  503  }
 470  504  
 471  505  int
 472  506  main(int argc, char *argv[])
 473  507  {
 474  508          int opt;
 475  509          boolean_t fg = B_FALSE;
 476  510  
 477  511          progname = strrchr(argv[0], '/');
 478  512          if (progname != NULL)
 479  513                  progname++;
 480  514          else
 481  515                  progname = argv[0];
 482  516  
 483  517          /* Process options */
 484  518          while ((opt = getopt(argc, argv, "f")) != EOF) {
 485  519                  switch (opt) {
 486  520                  case 'f':
 487  521                          fg = B_TRUE;
 488  522                          break;
 489  523                  default:
 490  524                          (void) fprintf(stderr, "Usage: %s [-f]\n", progname);
 491  525                          return (EXIT_FAILURE);
 492  526                  }
 493  527          }
 494  528  
 495  529          if (!fg && getenv("SMF_FMRI") == NULL) {
 496  530                  (void) fprintf(stderr,
 497  531                      "ipmgmtd is a smf(5) managed service and cannot be run "
 498  532                      "from the command line.\n");
 499  533                  return (EINVAL);
 500  534          }
 501  535  
 502  536          if (!fg && !ipmgmt_daemonize())
 503  537                  return (EXIT_FAILURE);
 504  538  
 505  539          if (ipmgmt_init_privileges() != 0)
 506  540                  goto child_out;
 507  541  
 508  542          if (ipmgmt_init() != 0)
 509  543                  goto child_out;
 510  544  
 511  545          /* Inform the parent process that it can successfully exit */
 512  546          ipmgmt_inform_parent_exit(EXIT_SUCCESS);
 513  547  
 514  548          for (;;)
 515  549                  (void) pause();
 516  550  
 517  551  child_out:
 518  552          /* return from main() forcibly exits an MT process */
 519  553          ipmgmt_inform_parent_exit(EXIT_FAILURE);
 520  554          return (EXIT_FAILURE);
 521  555  }
 522  556  
 523  557  /*
 524  558   * Return TRUE if `ifname' has persistent configuration for the `af' address
 525  559   * family in the datastore
 526  560   */
 527  561  static boolean_t
 528  562  ipmgmt_persist_if_exists(char *ifname, sa_family_t af)
 529  563  {
 530  564          ipmgmt_getif_cbarg_t cbarg;
 531  565          boolean_t exists = B_FALSE;
 532  566          ipadm_if_info_t *ifp;
 533  567  
 534  568          bzero(&cbarg, sizeof (cbarg));
 535  569          cbarg.cb_ifname = ifname;
 536  570          (void) ipmgmt_db_walk(ipmgmt_db_getif, &cbarg, IPADM_DB_READ);
 537  571          if ((ifp = cbarg.cb_ifinfo) != NULL) {
 538  572                  if ((af == AF_INET && (ifp->ifi_pflags & IFIF_IPV4)) ||
 539  573                      (af == AF_INET6 && (ifp->ifi_pflags & IFIF_IPV6))) {
 540  574                          exists = B_TRUE;
 541  575                  }
 542  576          }
 543  577          free(ifp);
 544  578          return (exists);
 545  579  }
 546  580  
 547  581  /*
 548  582   * Persist any NGZ interfaces assigned to us from the global zone if they do
 549  583   * not already exist in the persistent db. We need to
 550  584   * do this before any calls to ipadm_enable_if() can succeed (i.e.,
 551  585   * before opening up for door_calls), and after setuid to 'netadm' so that
 552  586   * the persistent db is created with the right permissions.
 553  587   */
 554  588  static void
 555  589  ipmgmt_ngz_persist_if()
 556  590  {
 557  591          ipmgmt_pif_t *pif, *next;
 558  592          ipmgmt_if_arg_t ifarg;
 559  593  
 560  594          for (pif = ngz_pifs; pif != NULL; pif = next) {
 561  595                  next = pif->pif_next;
 562  596                  bzero(&ifarg, sizeof (ifarg));
 563  597                  (void) strlcpy(ifarg.ia_ifname, pif->pif_ifname,
 564  598                      sizeof (ifarg.ia_ifname));
 565  599                  ifarg.ia_flags = IPMGMT_PERSIST;
 566  600                  if (pif->pif_v4 &&
 567  601                      !ipmgmt_persist_if_exists(pif->pif_ifname, AF_INET)) {
 568  602                          ifarg.ia_family = AF_INET;
 569  603                          (void) ipmgmt_persist_if(&ifarg);
 570  604                  }
 571  605                  if (pif->pif_v6 &&
 572  606                      !ipmgmt_persist_if_exists(pif->pif_ifname, AF_INET6)) {
 573  607                          ifarg.ia_family = AF_INET6;
 574  608                          (void) ipmgmt_persist_if(&ifarg);
 575  609                  }
 576  610                  free(pif);
 577  611          }
 578  612          ngz_pifs = NULL; /* no red herrings */
 579  613  }
  
    | 
      ↓ open down ↓ | 
    201 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX