Print this page
7388 Support DHCP Client FQDN. Allow IAID/DUID for all v4.

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c
          +++ new/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c
↓ 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 (c) 2016, Chris Fraire <cfraire@me.com>.
  24   25   */
  25   26  
  26   27  /*
  27   28   * Main door handler functions used by ipmgmtd to process the different door
  28   29   * call requests, issued by the library libipadm.so.
  29   30   */
  30   31  
  31   32  #include <alloca.h>
  32   33  #include <pwd.h>
  33   34  #include <auth_attr.h>
↓ open down ↓ 184 lines elided ↑ open up ↑
 218  219  /*
 219  220   * Helper function for ipmgmt_setaddr_handler().
 220  221   * It converts the nvlist_t, `nvl', to aobjmap node `nodep'.
 221  222   */
 222  223  static int
 223  224  i_ipmgmt_nvl2aobjnode(nvlist_t *nvl, ipmgmt_aobjmap_t *nodep)
 224  225  {
 225  226          char                    *aobjname = NULL, *ifname = NULL;
 226  227          int32_t                 lnum;
 227  228          nvlist_t                *nvladdr;
 228      -        struct sockaddr_storage addr;
 229      -        uint_t                  n;
 230  229          sa_family_t             af = AF_UNSPEC;
 231  230          ipadm_addr_type_t       addrtype = IPADM_ADDR_NONE;
 232  231          int                     err = 0;
 233  232  
 234  233          /*
 235  234           * Retrieve all the information needed to build '*nodep' from
 236  235           * nvlist_t nvl.
 237  236           */
 238  237          if ((err = nvlist_lookup_string(nvl, IPADM_NVP_AOBJNAME,
 239  238              &aobjname)) != 0 ||
 240  239              (err = nvlist_lookup_string(nvl, IPADM_NVP_IFNAME, &ifname)) != 0 ||
 241  240              (err = nvlist_lookup_int32(nvl, IPADM_NVP_LIFNUM, &lnum)) != 0) {
 242  241                  return (err);
 243  242          }
 244  243          if (nvlist_exists(nvl, IPADM_NVP_IPV4ADDR)) {
 245  244                  af = AF_INET;
 246  245                  addrtype = IPADM_ADDR_STATIC;
 247      -        } else if (nvlist_exists(nvl, IPADM_NVP_DHCP)) {
      246 +        } else if (nvlist_lookup_nvlist(nvl, IPADM_NVP_DHCP, &nvladdr) == 0) {
      247 +                char    *reqhost;
      248 +                boolean_t       primary;
      249 +
 248  250                  af = AF_INET;
 249  251                  addrtype = IPADM_ADDR_DHCP;
      252 +
      253 +                if (nvlist_lookup_boolean_value(nvladdr, IPADM_NVP_PRIMARY,
      254 +                    &primary) != 0)
      255 +                        return (EINVAL);
      256 +                nodep->ipmgmt_am_primary = primary;
      257 +
      258 +                /*
      259 +                 * ipmgmt_am_reqhost comes through in `nvl' for purposes of updating
      260 +                 * the cached representation, but it is persisted as a stand-alone
      261 +                 * DB line; so remove it after copying it.
      262 +                 */
      263 +                if (!nvlist_exists(nvl, IPADM_NVP_REQHOST)) {
      264 +                        *nodep->ipmgmt_am_reqhost = '\0';
      265 +                } else {
      266 +                        if ((err = nvlist_lookup_string(nvl, IPADM_NVP_REQHOST,
      267 +                            &reqhost)) != 0)
      268 +                                return (err);
      269 +
      270 +                        (void) strlcpy(nodep->ipmgmt_am_reqhost, reqhost,
      271 +                            sizeof (nodep->ipmgmt_am_reqhost));
      272 +                        (void) nvlist_remove(nvl, IPADM_NVP_REQHOST, DATA_TYPE_STRING);
      273 +                }
 250  274          } else if (nvlist_exists(nvl, IPADM_NVP_IPV6ADDR)) {
 251  275                  af = AF_INET6;
 252  276                  addrtype = IPADM_ADDR_STATIC;
 253  277          } else if (nvlist_lookup_nvlist(nvl, IPADM_NVP_INTFID, &nvladdr) == 0) {
 254      -                struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
      278 +                struct sockaddr_in6             sin6 = {0};
 255  279                  uint8_t *addr6;
 256  280                  uint32_t plen;
      281 +                uint_t n;
 257  282  
 258  283                  af = AF_INET6;
 259  284                  addrtype = IPADM_ADDR_IPV6_ADDRCONF;
 260  285                  if (nvlist_lookup_uint32(nvladdr, IPADM_NVP_PREFIXLEN,
 261  286                      &plen) != 0)
 262  287                          return (EINVAL);
 263  288                  if (plen != 0) {
 264  289                          if (nvlist_lookup_uint8_array(nvladdr,
 265  290                              IPADM_NVP_IPNUMADDR, &addr6, &n) != 0)
 266  291                                  return (EINVAL);
 267      -                        bcopy(addr6, &sin6->sin6_addr, n);
 268      -                } else {
 269      -                        bzero(&sin6->sin6_addr, sizeof (sin6->sin6_addr));
      292 +                        bcopy(addr6, &sin6.sin6_addr, n);
 270  293                  }
      294 +
      295 +                nodep->ipmgmt_am_linklocal = B_TRUE;
      296 +                nodep->ipmgmt_am_ifid = sin6;
 271  297          }
 272  298  
 273  299          /*
 274      -         * populate the `*nodep' with retrieved values.
      300 +         * populate the non-addrtype-specific `*nodep' with retrieved values.
 275  301           */
 276  302          (void) strlcpy(nodep->am_ifname, ifname, sizeof (nodep->am_ifname));
 277  303          (void) strlcpy(nodep->am_aobjname, aobjname,
 278  304              sizeof (nodep->am_aobjname));
 279  305          nodep->am_lnum = lnum;
 280  306          nodep->am_family = af;
 281  307          nodep->am_atype = addrtype;
 282      -        if (addrtype == IPADM_ADDR_IPV6_ADDRCONF) {
 283      -                nodep->am_linklocal = B_TRUE;
 284      -                nodep->am_ifid = addr;
 285      -        }
 286  308          nodep->am_next = NULL;
 287  309  
 288  310          /*
 289  311           * Do not store logical interface number in persistent store as it
 290  312           * takes different value on reboot. So remove it from `nvl'.
 291  313           */
 292  314          if (nvlist_exists(nvl, IPADM_NVP_LIFNUM))
 293  315                  (void) nvlist_remove(nvl, IPADM_NVP_LIFNUM, DATA_TYPE_INT32);
 294  316  
 295  317          return (0);
 296  318  }
 297  319  
 298  320  /*
 299  321   * Handles the door command IPMGMT_CMD_SETADDR. It adds a new address object
 300      - * node to the list `aobjmap' and then persists the address information in the
 301      - * DB.
      322 + * node to the list `aobjmap' and optionally persists the address
      323 + * information in the DB.
 302  324   */
 303  325  static void
 304  326  ipmgmt_setaddr_handler(void *argp)
 305  327  {
 306  328          ipmgmt_setaddr_arg_t    *sargp = argp;
 307  329          ipmgmt_retval_t         rval;
 308      -        ipmgmt_aobjmap_t        node;
      330 +        ipmgmt_aobjmap_t        node = {0};
 309  331          nvlist_t                *nvl = NULL;
 310  332          char                    *nvlbuf;
 311  333          size_t                  nvlsize = sargp->ia_nvlsize;
 312  334          uint32_t                flags = sargp->ia_flags;
 313  335          int                     err = 0;
 314  336  
 315  337          nvlbuf = (char *)argp + sizeof (ipmgmt_setaddr_arg_t);
 316  338          if ((err = nvlist_unpack(nvlbuf, nvlsize, &nvl, NV_ENCODE_NATIVE)) != 0)
 317  339                  goto ret;
 318  340          if (flags & (IPMGMT_ACTIVE|IPMGMT_INIT)) {
 319  341                  if ((err = i_ipmgmt_nvl2aobjnode(nvl, &node)) != 0)
 320  342                          goto ret;
 321  343                  if (flags & IPMGMT_INIT)
 322  344                          node.am_flags = (IPMGMT_ACTIVE|IPMGMT_PERSIST);
 323  345                  else
 324      -                        node.am_flags = flags;
      346 +                        node.am_flags = flags & ~IPMGMT_PROPS_ONLY;
 325  347                  if ((err = ipmgmt_aobjmap_op(&node, ADDROBJ_ADD)) != 0)
 326  348                          goto ret;
 327  349          }
 328      -        if (flags & IPMGMT_PERSIST) {
      350 +        if ((flags & IPMGMT_PERSIST) && !(flags & IPMGMT_PROPS_ONLY)) {
 329  351                  ipadm_dbwrite_cbarg_t   cb;
 330  352  
 331  353                  cb.dbw_nvl = nvl;
 332  354                  cb.dbw_flags = 0;
 333  355                  err = ipmgmt_db_walk(ipmgmt_db_add, &cb, IPADM_DB_WRITE);
 334  356          }
 335  357  ret:
 336  358          nvlist_free(nvl);
 337  359          rval.ir_err = err;
 338  360          (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 339  361  }
 340  362  
 341  363  /*
 342      - * Handles the door commands that modify the `aobjmap' structure.
      364 + * Handles the door commands that read or modify the `aobjmap' structure.
 343  365   *
 344  366   * IPMGMT_CMD_ADDROBJ_LOOKUPADD - places a stub address object in `aobjmap'
 345  367   *      after ensuring that the namespace is not taken. If required, also
 346  368   *      generates an `aobjname' for address object for the library to use.
 347  369   * IPMGMT_CMD_ADDROBJ_ADD - add/update address object in `aobjmap'
 348  370   * IPMGMT_CMD_LIF2ADDROBJ - given a logical interface, return address object
 349  371   *      associated with that logical interface.
 350  372   * IPMGMT_CMD_AOBJNAME2ADDROBJ - given an address object name return logical
 351  373   *      interface associated with that address object.
 352  374   */
↓ open down ↓ 81 lines elided ↑ open up ↑
 434  456                          if (strcmp(head->am_aobjname, aobjname) != 0)
 435  457                                  continue;
 436  458                          /*
 437  459                           * For an auto-configured interface, return
 438  460                           * the lifnum that has the link-local on it.
 439  461                           * Other logical interfaces were created for
 440  462                           * prefixes and dhcpv6 addresses and do not
 441  463                           * have am_ifid set.
 442  464                           */
 443  465                          if (head->am_atype != IPADM_ADDR_IPV6_ADDRCONF ||
 444      -                            head->am_linklocal) {
      466 +                            head->ipmgmt_am_linklocal) {
 445  467                                  break;
 446  468                          }
 447  469                  }
 448  470                  if (head == NULL) {
 449  471                          err = ENOENT;
 450  472                          (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock);
 451  473                          break;
 452  474                  }
 453  475                  (void) strlcpy(aobjrval.ir_ifname, head->am_ifname,
 454  476                      sizeof (aobjrval.ir_ifname));
 455  477                  aobjrval.ir_lnum = head->am_lnum;
 456  478                  aobjrval.ir_family = head->am_family;
 457  479                  aobjrval.ir_flags = head->am_flags;
 458  480                  aobjrval.ir_atype = head->am_atype;
 459      -                if (head->am_atype == IPADM_ADDR_IPV6_ADDRCONF &&
 460      -                    head->am_linklocal)
 461      -                        aobjrval.ir_ifid = head->am_ifid;
      481 +                (void) memcpy(&aobjrval.ir_atype_cache, &head->am_atype_cache,
      482 +                    sizeof (aobjrval.ir_atype_cache));
 462  483                  (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock);
 463  484                  break;
 464  485          case IPMGMT_CMD_LIF2ADDROBJ:
 465  486                  rsize = sizeof (ipmgmt_aobjop_rval_t);
 466  487                  rvalp = &aobjrval;
 467  488                  bzero(&aobjrval, sizeof (aobjrval));
 468  489                  if (ifname[0] == '\0') {
 469  490                          err = EINVAL;
 470  491                          break;
 471  492                  }
↓ open down ↓ 8 lines elided ↑ open up ↑
 480  501                  }
 481  502                  if (head == NULL) {
 482  503                          err = ENOENT;
 483  504                          (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock);
 484  505                          break;
 485  506                  }
 486  507                  (void) strlcpy(aobjrval.ir_aobjname, head->am_aobjname,
 487  508                      sizeof (aobjrval.ir_aobjname));
 488  509                  aobjrval.ir_atype = head->am_atype;
 489  510                  aobjrval.ir_flags = head->am_flags;
      511 +                (void) memcpy(&aobjrval.ir_atype_cache, &head->am_atype_cache,
      512 +                    sizeof (aobjrval.ir_atype_cache));
 490  513                  (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock);
 491  514                  break;
 492  515          default:
 493  516                  rsize = sizeof (ipmgmt_retval_t);
 494  517                  rvalp = &rval;
 495  518                  err = EINVAL;
 496  519          }
 497  520          ((ipmgmt_retval_t *)rvalp)->ir_err = err;
 498  521          (void) door_return((char *)rvalp, rsize, NULL, 0);
 499  522  }
↓ open down ↓ 365 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX