Print this page
Commit IPMP changes


 213  * Retrieves the static address (IPv4 or IPv6) for the given address object
 214  * in `ipaddr' from persistent DB.
 215  */
 216 static ipadm_status_t
 217 i_ipadm_get_static_addr_db(ipadm_handle_t iph, ipadm_addrobj_t ipaddr)
 218 {
 219         ipadm_status_t          status;
 220         nvlist_t                *onvl;
 221         nvlist_t                *anvl = NULL;
 222         nvlist_t                *nvladdr;
 223         nvpair_t                *nvp;
 224         char                    *name;
 225         char                    *aobjname = ipaddr->ipadm_aobjname;
 226         char                    *sname;
 227         sa_family_t             af = AF_UNSPEC;
 228 
 229         /*
 230          * Get the address line in the nvlist `onvl' from ipmgmtd daemon.
 231          */
 232         status = i_ipadm_get_db_addr(iph, NULL, aobjname, &onvl);
 233         if (status != IPADM_SUCCESS)
 234                 return (status);

 235         /*
 236          * Walk through the nvlist `onvl' to extract the IPADM_NVP_IPV4ADDR
 237          * or the IPADM_NVP_IPV6ADDR name-value pair.
 238          */
 239         for (nvp = nvlist_next_nvpair(onvl, NULL); nvp != NULL;
 240             nvp = nvlist_next_nvpair(onvl, NULL)) {
 241                 if (nvpair_value_nvlist(nvp, &anvl) != 0)
 242                         continue;
 243                 if (nvlist_exists(anvl, IPADM_NVP_IPV4ADDR) ||
 244                     nvlist_exists(anvl, IPADM_NVP_IPV6ADDR))
 245                         break;
 246         }
 247         if (nvp == NULL)
 248                 goto fail;
 249         for (nvp = nvlist_next_nvpair(anvl, NULL);
 250             nvp != NULL; nvp = nvlist_next_nvpair(anvl, nvp)) {
 251                 name = nvpair_name(nvp);
 252                 if (strcmp(name, IPADM_NVP_IPV4ADDR) == 0) {
 253                         af = AF_INET;
 254                         break;
 255                 } else if (strcmp(name, IPADM_NVP_IPV6ADDR) == 0) {
 256                         af = AF_INET6;
 257                         break;
 258                 }
 259         }
 260         assert(af != AF_UNSPEC);
 261         if (nvpair_value_nvlist(nvp, &nvladdr) != 0 ||
 262             nvlist_lookup_string(nvladdr, IPADM_NVP_IPADDRHNAME, &sname) != 0 ||
 263             ipadm_set_addr(ipaddr, sname, af) != IPADM_SUCCESS) {
 264                 goto fail;



 265         }
 266         nvlist_free(onvl);
 267         return (IPADM_SUCCESS);
 268 fail:
 269         nvlist_free(onvl);
 270         return (IPADM_NOTFOUND);
 271 }
 272 
 273 /*
 274  * For the given `addrobj->ipadm_lifnum' and `addrobj->ipadm_af', this function
 275  * fills in the address objname, the address type and the ipadm_flags.
 276  */
 277 ipadm_status_t
 278 i_ipadm_get_lif2addrobj(ipadm_handle_t iph, ipadm_addrobj_t addrobj)
 279 {
 280         ipmgmt_aobjop_arg_t     larg;
 281         ipmgmt_aobjop_rval_t    rval, *rvalp;
 282         int                     err;
 283 
 284         larg.ia_cmd = IPMGMT_CMD_LIF2ADDROBJ;


1496         if (!(pdp->ipd_flags & IPADMPROP_MULVAL) &&
1497             (pflags & (IPADM_OPT_APPEND|IPADM_OPT_REMOVE))) {
1498                 return (IPADM_INVALID_ARG);
1499         }
1500 
1501         /*
1502          * For the given aobjname, get the addrobj it represents and
1503          * set the property value for that object.
1504          */
1505         i_ipadm_init_addr(&ipaddr, "", aobjname, IPADM_ADDR_NONE);
1506         if ((status = i_ipadm_get_addrobj(iph, &ipaddr)) != IPADM_SUCCESS)
1507                 return (status);
1508 
1509         if (!(ipaddr.ipadm_flags & IPMGMT_ACTIVE))
1510                 return (IPADM_OP_DISABLE_OBJ);
1511 
1512         /* Persistent operation not allowed on a temporary object. */
1513         if ((pflags & IPADM_OPT_PERSIST) &&
1514             !(ipaddr.ipadm_flags & IPMGMT_PERSIST))
1515                 return (IPADM_TEMPORARY_OBJ);
1516 
1517         /*
1518          * Currently, setting an address property on an address object of type
1519          * IPADM_ADDR_IPV6_ADDRCONF is not supported. Supporting it involves
1520          * in.ndpd retrieving the address properties from ipmgmtd for given
1521          * address object and then setting them on auto-configured addresses,
1522          * whenever in.ndpd gets a new prefix. This will be supported in
1523          * future releases.
1524          */
1525         if (ipaddr.ipadm_atype == IPADM_ADDR_IPV6_ADDRCONF)
1526                 return (IPADM_NOTSUP);
1527 
1528         /*
1529          * Setting an address property on an address object that is
1530          * not present in active configuration is not supported.
1531          */
1532         if (!(ipaddr.ipadm_flags & IPMGMT_ACTIVE))
1533                 return (IPADM_NOTSUP);
1534 
1535         af = ipaddr.ipadm_af;
1536         if (reset) {


2015                         err = nvpair_value_string(nvp, &sname);
2016                 else if (strcmp(name, IPADM_NVP_IPDADDRHNAME) == 0)
2017                         err = nvpair_value_string(nvp, &dname);
2018                 if (err != 0)
2019                         return (ipadm_errno2status(err));
2020         }
2021 
2022         if (strcmp(upstr, "yes") == 0)
2023                 flags |= IPADM_OPT_UP;
2024 
2025         /* build the address object from the above information */
2026         i_ipadm_init_addr(&ipaddr, ifname, aobjname, IPADM_ADDR_STATIC);
2027         if (prefixlenstr != NULL && atoi(prefixlenstr) > 0) {
2028                 if (asprintf(&cidraddr, "%s/%s", sname, prefixlenstr) == -1)
2029                         return (IPADM_NO_MEMORY);
2030                 status = ipadm_set_addr(&ipaddr, cidraddr, af);
2031                 free(cidraddr);
2032         } else {
2033                 status = ipadm_set_addr(&ipaddr, sname, af);
2034         }
2035         if (status != IPADM_SUCCESS)
2036                 return (status);
2037 
2038         if (dname != NULL) {
2039                 status = ipadm_set_dst_addr(&ipaddr, dname, af);
2040                 if (status != IPADM_SUCCESS)
2041                         return (status);
2042         }
2043         return (i_ipadm_create_addr(iph, &ipaddr, flags));
2044 }
2045 
2046 /*
2047  * Creates a dhcp address on the interface `ifname' based on the
2048  * IPADM_ADDR_DHCP address object parameters from the nvlist `nvl'.
2049  */
2050 ipadm_status_t
2051 i_ipadm_enable_dhcp(ipadm_handle_t iph, const char *ifname, nvlist_t *nvl)
2052 {
2053         int32_t                 wait;
2054         boolean_t               primary;
2055         nvlist_t                *nvdhcp;
2056         nvpair_t                *nvp;


2161         ipadm_addrobj_t newaddr;
2162         ipadm_status_t  status;
2163         char            *aname, *cp;
2164         char            ifname[IPADM_AOBJSIZ];
2165         ifspec_t        ifsp;
2166 
2167         if (ipaddr == NULL)
2168                 return (IPADM_INVALID_ARG);
2169         *ipaddr = NULL;
2170 
2171         if (aobjname == NULL || aobjname[0] == '\0')
2172                 return (IPADM_INVALID_ARG);
2173 
2174         if (strlcpy(ifname, aobjname, IPADM_AOBJSIZ) >= IPADM_AOBJSIZ)
2175                 return (IPADM_INVALID_ARG);
2176 
2177         if ((aname = strchr(ifname, '/')) != NULL)
2178                 *aname++ = '\0';
2179 
2180         /* Check if the interface name is valid. */
2181         if (!ifparse_ifspec(ifname, &ifsp))
2182                 return (IPADM_INVALID_ARG);
2183 
2184         /* Check if the given addrobj name is valid. */
2185         if (aname != NULL && !i_ipadm_is_user_aobjname_valid(aname))
2186                 return (IPADM_INVALID_ARG);
2187 
2188         if ((newaddr = calloc(1, sizeof (struct ipadm_addrobj_s))) == NULL)
2189                 return (IPADM_NO_MEMORY);
2190 
2191         /*
2192          * If the ifname has logical interface number, extract it and assign
2193          * it to `ipadm_lifnum'. Only applications with IPH_LEGACY set will do
2194          * this today. We will check for the validity later in
2195          * i_ipadm_validate_create_addr().
2196          */
2197         if (ifsp.ifsp_lunvalid) {
2198                 newaddr->ipadm_lifnum = ifsp.ifsp_lun;
2199                 cp = strchr(ifname, IPADM_LOGICAL_SEP);
2200                 *cp = '\0';
2201         }
2202         (void) strlcpy(newaddr->ipadm_ifname, ifname,
2203             sizeof (newaddr->ipadm_ifname));
2204 
2205         if (aname != NULL) {
2206                 (void) snprintf(newaddr->ipadm_aobjname,
2207                     sizeof (newaddr->ipadm_aobjname), "%s/%s", ifname, aname);


2349                     iph->iph_sock6);
2350                 if (ioctl(sock, SIOCLIFADDIF, (caddr_t)&lifr) < 0)
2351                         return (ipadm_errno2status(errno));
2352                 addr->ipadm_lifnum = i_ipadm_get_lnum(lifr.lifr_name);
2353         }
2354         return (IPADM_SUCCESS);
2355 }
2356 
2357 /*
2358  * Reads all the address lines from the persistent DB into the nvlist `onvl',
2359  * when both `ifname' and `aobjname' are NULL. If an `ifname' is provided,
2360  * it returns all the addresses for the given interface `ifname'.
2361  * If an `aobjname' is specified, then the address line corresponding to
2362  * that name will be returned.
2363  */
2364 static ipadm_status_t
2365 i_ipadm_get_db_addr(ipadm_handle_t iph, const char *ifname,
2366     const char *aobjname, nvlist_t **onvl)
2367 {
2368         ipmgmt_getaddr_arg_t    garg;
2369         ipmgmt_get_rval_t       *rvalp;
2370         int                     err;
2371         size_t                  nvlsize;
2372         char                    *nvlbuf;
2373 
2374         /* Populate the door_call argument structure */
2375         bzero(&garg, sizeof (garg));
2376         garg.ia_cmd = IPMGMT_CMD_GETADDR;
2377         if (aobjname != NULL)
2378                 (void) strlcpy(garg.ia_aobjname, aobjname,
2379                     sizeof (garg.ia_aobjname));
2380         if (ifname != NULL)
2381                 (void) strlcpy(garg.ia_ifname, ifname, sizeof (garg.ia_ifname));
2382 
2383         rvalp = malloc(sizeof (ipmgmt_get_rval_t));
2384         err = ipadm_door_call(iph, &garg, sizeof (garg), (void **)&rvalp,
2385             sizeof (*rvalp), B_TRUE);
2386         if (err == 0) {
2387                 nvlsize = rvalp->ir_nvlsize;
2388                 nvlbuf = (char *)rvalp + sizeof (ipmgmt_get_rval_t);
2389                 err = nvlist_unpack(nvlbuf, nvlsize, onvl, NV_ENCODE_NATIVE);
2390         }
2391         free(rvalp);
2392         return (ipadm_errno2status(err));
2393 }
2394 
2395 /*
2396  * Adds the IP address contained in the 'ipaddr' argument to the physical
2397  * interface represented by 'ifname' after doing the required validation.
2398  * If the interface does not exist, it is created before the address is
2399  * added.
2400  *
2401  * If IPH_LEGACY is set in iph_flags, flags has to be IPADM_OPT_ACTIVE
2402  * and a default addrobj name will be generated. Input `addr->ipadm_aobjname',
2403  * if provided, will be ignored and replaced with the newly generated name.
2404  * The interface name provided has to be a logical interface name that
2405  * already exists. No new logical interface will be added in this function.
2406  *
2407  * If IPADM_OPT_V46 is passed in the flags, then both IPv4 and IPv6 interfaces
2408  * are plumbed (if they haven't been already).  Otherwise, just the interface
2409  * specified in `addr' is plumbed.
2410  */
2411 ipadm_status_t
2412 ipadm_create_addr(ipadm_handle_t iph, ipadm_addrobj_t addr, uint32_t flags)


2415         sa_family_t             af;
2416         sa_family_t             daf;
2417         sa_family_t             other_af;
2418         boolean_t               created_af = B_FALSE;
2419         boolean_t               created_other_af = B_FALSE;
2420         ipadm_addr_type_t       type;
2421         char                    *ifname = addr->ipadm_ifname;
2422         boolean_t               legacy = (iph->iph_flags & IPH_LEGACY);
2423         boolean_t               aobjfound;
2424         boolean_t               is_6to4;
2425         struct lifreq           lifr;
2426         uint64_t                ifflags;
2427         boolean_t               is_boot = (iph->iph_flags & IPH_IPMGMTD);
2428 
2429         /* check for solaris.network.interface.config authorization */
2430         if (!ipadm_check_auth())
2431                 return (IPADM_EAUTH);
2432 
2433         /* Validate the addrobj. This also fills in addr->ipadm_ifname. */
2434         status = i_ipadm_validate_create_addr(iph, addr, flags);
2435         if (status != IPADM_SUCCESS)
2436                 return (status);
2437 
2438         /*
2439          * For Legacy case, check if an addrobj already exists for the
2440          * given logical interface name. If one does not exist,
2441          * a default name will be generated and added to the daemon's
2442          * aobjmap.
2443          */
2444         if (legacy) {
2445                 struct ipadm_addrobj_s  ipaddr;
2446 
2447                 ipaddr = *addr;
2448                 status = i_ipadm_get_lif2addrobj(iph, &ipaddr);
2449                 if (status == IPADM_SUCCESS) {
2450                         aobjfound = B_TRUE;
2451                         /*
2452                          * With IPH_LEGACY, modifying an address that is not
2453                          * a static address will return with an error.
2454                          */
2455                         if (ipaddr.ipadm_atype != IPADM_ADDR_STATIC)
2456                                 return (IPADM_NOTSUP);
2457                         /*


2464                         aobjfound = B_FALSE;
2465                 } else {
2466                         return (status);
2467                 }
2468         }
2469 
2470         af = addr->ipadm_af;
2471         /*
2472          * Create a placeholder for this address object in the daemon.
2473          * Skip this step if we are booting a zone (and therefore being called
2474          * from ipmgmtd itself), and, for IPH_LEGACY case if the
2475          * addrobj already exists.
2476          *
2477          * Note that the placeholder is not needed in the NGZ boot case,
2478          * when zoneadmd has itself applied the "allowed-ips" property to clamp
2479          * down any interface configuration, so the namespace for the interface
2480          * is fully controlled by the GZ.
2481          */
2482         if (!is_boot && (!legacy || !aobjfound)) {
2483                 status = i_ipadm_lookupadd_addrobj(iph, addr);
2484                 if (status != IPADM_SUCCESS)
2485                         return (status);
2486         }

2487 
2488         is_6to4 = i_ipadm_is_6to4(iph, ifname);
2489         /* Plumb the IP interfaces if necessary */
2490         status = i_ipadm_create_if(iph, ifname, af, flags);
2491         if (status != IPADM_SUCCESS && status != IPADM_IF_EXISTS) {
2492                 (void) i_ipadm_delete_addrobj(iph, addr, IPADM_OPT_ACTIVE);
2493                 return (status);
2494         }
2495         if (status == IPADM_SUCCESS)
2496                 created_af = B_TRUE;
2497         if (!is_6to4 && !legacy && (flags & IPADM_OPT_V46)) {
2498                 other_af = (af == AF_INET ? AF_INET6 : AF_INET);
2499                 status = i_ipadm_create_if(iph, ifname, other_af, flags);
2500                 if (status != IPADM_SUCCESS && status != IPADM_IF_EXISTS) {
2501                         (void) i_ipadm_delete_if(iph, ifname, af, flags);
2502                         return (status);
2503                 }
2504                 if (status == IPADM_SUCCESS)
2505                         created_other_af = B_TRUE;
2506         }


2614                 }
2615         }
2616 
2617         return (status);
2618 }
2619 
2620 /*
2621  * Creates the static address in `ipaddr' in kernel. After successfully
2622  * creating it, it updates the ipmgmtd daemon's aobjmap with the logical
2623  * interface information.
2624  */
2625 static ipadm_status_t
2626 i_ipadm_create_addr(ipadm_handle_t iph, ipadm_addrobj_t ipaddr, uint32_t flags)
2627 {
2628         struct lifreq                   lifr;
2629         ipadm_status_t                  status = IPADM_SUCCESS;
2630         int                             sock;
2631         struct sockaddr_storage         m, *mask = &m;
2632         const struct sockaddr_storage   *addr = &ipaddr->ipadm_static_addr;
2633         const struct sockaddr_storage   *daddr = &ipaddr->ipadm_static_dst_addr;

2634         sa_family_t                     af;
2635         boolean_t                       legacy = (iph->iph_flags & IPH_LEGACY);
2636         struct ipadm_addrobj_s          legacy_addr;
2637         boolean_t                       default_prefixlen = B_FALSE;
2638         boolean_t                       is_boot;
2639 
2640         is_boot = ((iph->iph_flags & IPH_IPMGMTD) != 0);
2641         af = ipaddr->ipadm_af;
2642         sock = (af == AF_INET ? iph->iph_sock : iph->iph_sock6);
2643 
2644         /* If prefixlen was not provided, get default prefixlen */
2645         if (ipaddr->ipadm_static_prefixlen == 0) {
2646                 /* prefixlen was not provided, get default prefixlen */
2647                 status = i_ipadm_get_default_prefixlen(
2648                     &ipaddr->ipadm_static_addr,
2649                     &ipaddr->ipadm_static_prefixlen);
2650                 if (status != IPADM_SUCCESS)
2651                         return (status);
2652                 default_prefixlen = B_TRUE;
2653         }


2683         lifr.lifr_addr = *mask;
2684         if (ioctl(sock, SIOCSLIFNETMASK, (caddr_t)&lifr) < 0) {
2685                 status = ipadm_errno2status(errno);
2686                 goto ret;
2687         }
2688         lifr.lifr_addr = *addr;
2689         if (ioctl(sock, SIOCSLIFADDR, (caddr_t)&lifr) < 0) {
2690                 status = ipadm_errno2status(errno);
2691                 goto ret;
2692         }
2693         /* Set the destination address, if one is given. */
2694         if (daddr->ss_family != AF_UNSPEC) {
2695                 lifr.lifr_addr = *daddr;
2696                 if (ioctl(sock, SIOCSLIFDSTADDR, (caddr_t)&lifr) < 0) {
2697                         status = ipadm_errno2status(errno);
2698                         goto ret;
2699                 }
2700         }
2701 
2702         if (flags & IPADM_OPT_UP) {
2703                 status = i_ipadm_set_flags(iph, lifr.lifr_name, af, IFF_UP, 0);



2704 
2705                 /*
2706                  * IPADM_DAD_FOUND is a soft-error for create-addr.
2707                  * No need to tear down the address.
2708                  */
2709                 if (status == IPADM_DAD_FOUND)
2710                         status = IPADM_SUCCESS;
2711         }
2712 
2713         if (status == IPADM_SUCCESS && !is_boot) {
2714                 /*
2715                  * For IPH_LEGACY, we might be modifying the address on
2716                  * an address object that already exists e.g. by doing
2717                  * "ifconfig bge0:1 <addr>; ifconfig bge0:1 <newaddr>"
2718                  * So, we need to store the object only if it does not
2719                  * already exist in ipmgmtd.
2720                  */
2721                 if (legacy) {
2722                         bzero(&legacy_addr, sizeof (legacy_addr));
2723                         (void) strlcpy(legacy_addr.ipadm_aobjname,


3186         ipadm_status_t  status;
3187         char            lifname[LIFNAMSIZ];
3188 
3189         /* check for solaris.network.interface.config authorization */
3190         if (!ipadm_check_auth())
3191                 return (IPADM_EAUTH);
3192 
3193         /* validate input */
3194         if (aobjname == NULL || strlcpy(ipaddr->ipadm_aobjname, aobjname,
3195             IPADM_AOBJSIZ) >= IPADM_AOBJSIZ) {
3196                 return (IPADM_INVALID_ARG);
3197         }
3198 
3199         /* Retrieve the address object information. */
3200         status = i_ipadm_get_addrobj(iph, ipaddr);
3201         if (status != IPADM_SUCCESS)
3202                 return (status);
3203 
3204         if (!(ipaddr->ipadm_flags & IPMGMT_ACTIVE))
3205                 return (IPADM_OP_DISABLE_OBJ);

3206         if ((ipadm_flags & IPADM_OPT_PERSIST) &&
3207             !(ipaddr->ipadm_flags & IPMGMT_PERSIST))
3208                 return (IPADM_TEMPORARY_OBJ);

3209         if (ipaddr->ipadm_atype == IPADM_ADDR_IPV6_ADDRCONF ||
3210             (ipaddr->ipadm_atype == IPADM_ADDR_DHCP &&
3211             (ipadm_flags & IPADM_OPT_PERSIST)))
3212                 return (IPADM_NOTSUP);
3213 
3214         i_ipadm_addrobj2lifname(ipaddr, lifname, sizeof (lifname));

3215         return (i_ipadm_get_flags(iph, lifname, ipaddr->ipadm_af, ifflags));
3216 }
3217 
3218 /*
3219  * Marks the address in the address object `aobjname' up. This operation is
3220  * not supported for an address object of type IPADM_ADDR_IPV6_ADDRCONF.
3221  * For an address object of type IPADM_ADDR_DHCP, this operation can
3222  * only be temporary and no updates will be made to the persistent DB.
3223  */
3224 ipadm_status_t
3225 ipadm_up_addr(ipadm_handle_t iph, const char *aobjname, uint32_t ipadm_flags)
3226 {
3227         struct ipadm_addrobj_s ipaddr;
3228         ipadm_status_t  status;
3229         uint64_t        flags;
3230         char            lifname[LIFNAMSIZ];
3231 
3232         status = i_ipadm_updown_common(iph, aobjname, &ipaddr, ipadm_flags,
3233             &flags);
3234         if (status != IPADM_SUCCESS)


3406         uint64_t                ifflags = 0;
3407         boolean_t               p_exists;
3408         boolean_t               af_exists, other_af_exists, a_exists;
3409 
3410         if (ipaddr == NULL || flags == 0 || flags == IPADM_OPT_PERSIST ||
3411             (flags & ~(IPADM_COMMON_OPT_MASK|IPADM_OPT_UP|IPADM_OPT_V46))) {
3412                 return (IPADM_INVALID_ARG);
3413         }
3414 
3415         if (ipaddr->ipadm_af == AF_UNSPEC)
3416                 return (IPADM_BAD_ADDR);
3417 
3418         if (!legacy && ipaddr->ipadm_lifnum != 0)
3419                 return (IPADM_INVALID_ARG);
3420 
3421         if (legacy && ipaddr->ipadm_atype != IPADM_ADDR_STATIC)
3422                 return (IPADM_NOTSUP);
3423 
3424         ifname = ipaddr->ipadm_ifname;
3425 
3426         if (i_ipadm_is_ipmp(iph, ifname) || i_ipadm_is_under_ipmp(iph, ifname))
3427                 return (IPADM_NOTSUP);





3428 
3429         af = ipaddr->ipadm_af;
3430         af_exists = ipadm_if_enabled(iph, ifname, af);
3431         /*
3432          * For legacy case, interfaces are not implicitly plumbed. We need to
3433          * check if the interface exists in the active configuration.
3434          */
3435         if (legacy && !af_exists)
3436                 return (IPADM_ENXIO);
3437 
3438         other_af = (af == AF_INET ? AF_INET6 : AF_INET);
3439         other_af_exists = ipadm_if_enabled(iph, ifname, other_af);
3440         /*
3441          * Check if one of the v4 or the v6 interfaces exists in the
3442          * active configuration. An interface is considered disabled only
3443          * if both v4 and v6 are not active.
3444          */
3445         a_exists = (af_exists || other_af_exists);
3446 
3447         /* Check if interface exists in the persistent configuration. */
3448         status = i_ipadm_if_pexists(iph, ifname, af, &p_exists);
3449         if (status != IPADM_SUCCESS)
3450                 return (status);

3451         if (!a_exists && p_exists)
3452                 return (IPADM_OP_DISABLE_OBJ);
3453         if ((flags & IPADM_OPT_PERSIST) && a_exists && !p_exists) {
3454                 /*
3455                  * If address has to be created persistently,
3456                  * and the interface does not exist in the persistent
3457                  * store but in active config, fail.
3458                  */
3459                 return (IPADM_TEMPORARY_OBJ);
3460         }
3461         if (af_exists) {
3462                 status = i_ipadm_get_flags(iph, ifname, af, &ifflags);
3463                 if (status != IPADM_SUCCESS)
3464                         return (status);
3465         }
3466 
3467         /* Perform validation steps (4) and (5) */
3468         islo = i_ipadm_is_loopback(ifname);
3469         isvni = i_ipadm_is_vni(ifname);
3470         switch (ipaddr->ipadm_atype) {
3471         case IPADM_ADDR_STATIC:
3472                 if ((islo || isvni) && ipaddr->ipadm_static_dname[0] != '\0')
3473                         return (IPADM_INVALID_ARG);
3474                 /* Check for a valid src address */
3475                 if (!legacy && sockaddrunspec(
3476                     (struct sockaddr *)&ipaddr->ipadm_static_addr))
3477                         return (IPADM_BAD_ADDR);
3478                 break;
3479         case IPADM_ADDR_DHCP:
3480                 if (islo || (ifflags & IFF_VRRP))




 213  * Retrieves the static address (IPv4 or IPv6) for the given address object
 214  * in `ipaddr' from persistent DB.
 215  */
 216 static ipadm_status_t
 217 i_ipadm_get_static_addr_db(ipadm_handle_t iph, ipadm_addrobj_t ipaddr)
 218 {
 219         ipadm_status_t          status;
 220         nvlist_t                *onvl;
 221         nvlist_t                *anvl = NULL;
 222         nvlist_t                *nvladdr;
 223         nvpair_t                *nvp;
 224         char                    *name;
 225         char                    *aobjname = ipaddr->ipadm_aobjname;
 226         char                    *sname;
 227         sa_family_t             af = AF_UNSPEC;
 228 
 229         /*
 230          * Get the address line in the nvlist `onvl' from ipmgmtd daemon.
 231          */
 232         status = i_ipadm_get_db_addr(iph, NULL, aobjname, &onvl);
 233         if (status != IPADM_SUCCESS) {
 234                 return (status);
 235         }
 236         /*
 237          * Walk through the nvlist `onvl' to extract the IPADM_NVP_IPV4ADDR
 238          * or the IPADM_NVP_IPV6ADDR name-value pair.
 239          */
 240         for (nvp = nvlist_next_nvpair(onvl, NULL); nvp != NULL;
 241             nvp = nvlist_next_nvpair(onvl, NULL)) {
 242                 if (nvpair_value_nvlist(nvp, &anvl) != 0)
 243                         continue;
 244                 if (nvlist_exists(anvl, IPADM_NVP_IPV4ADDR) ||
 245                     nvlist_exists(anvl, IPADM_NVP_IPV6ADDR))
 246                         break;
 247         }
 248         if (nvp == NULL)
 249                 goto fail;
 250         for (nvp = nvlist_next_nvpair(anvl, NULL);
 251             nvp != NULL; nvp = nvlist_next_nvpair(anvl, nvp)) {
 252                 name = nvpair_name(nvp);
 253                 if (strcmp(name, IPADM_NVP_IPV4ADDR) == 0) {
 254                         af = AF_INET;
 255                         break;
 256                 } else if (strcmp(name, IPADM_NVP_IPV6ADDR) == 0) {
 257                         af = AF_INET6;
 258                         break;
 259                 }
 260         }
 261         assert(af != AF_UNSPEC);
 262         if (nvpair_value_nvlist(nvp, &nvladdr) != 0 ||
 263             nvlist_lookup_string(nvladdr, IPADM_NVP_IPADDRHNAME, &sname) != 0)

 264                 goto fail;
 265 
 266         if (ipadm_set_addr(ipaddr, sname, af) != IPADM_SUCCESS) {
 267                 goto fail;
 268         }
 269         nvlist_free(onvl);
 270         return (IPADM_SUCCESS);
 271 fail:
 272         nvlist_free(onvl);
 273         return (IPADM_NOTFOUND);
 274 }
 275 
 276 /*
 277  * For the given `addrobj->ipadm_lifnum' and `addrobj->ipadm_af', this function
 278  * fills in the address objname, the address type and the ipadm_flags.
 279  */
 280 ipadm_status_t
 281 i_ipadm_get_lif2addrobj(ipadm_handle_t iph, ipadm_addrobj_t addrobj)
 282 {
 283         ipmgmt_aobjop_arg_t     larg;
 284         ipmgmt_aobjop_rval_t    rval, *rvalp;
 285         int                     err;
 286 
 287         larg.ia_cmd = IPMGMT_CMD_LIF2ADDROBJ;


1499         if (!(pdp->ipd_flags & IPADMPROP_MULVAL) &&
1500             (pflags & (IPADM_OPT_APPEND|IPADM_OPT_REMOVE))) {
1501                 return (IPADM_INVALID_ARG);
1502         }
1503 
1504         /*
1505          * For the given aobjname, get the addrobj it represents and
1506          * set the property value for that object.
1507          */
1508         i_ipadm_init_addr(&ipaddr, "", aobjname, IPADM_ADDR_NONE);
1509         if ((status = i_ipadm_get_addrobj(iph, &ipaddr)) != IPADM_SUCCESS)
1510                 return (status);
1511 
1512         if (!(ipaddr.ipadm_flags & IPMGMT_ACTIVE))
1513                 return (IPADM_OP_DISABLE_OBJ);
1514 
1515         /* Persistent operation not allowed on a temporary object. */
1516         if ((pflags & IPADM_OPT_PERSIST) &&
1517             !(ipaddr.ipadm_flags & IPMGMT_PERSIST))
1518                 return (IPADM_TEMPORARY_OBJ);

1519         /*
1520          * Currently, setting an address property on an address object of type
1521          * IPADM_ADDR_IPV6_ADDRCONF is not supported. Supporting it involves
1522          * in.ndpd retrieving the address properties from ipmgmtd for given
1523          * address object and then setting them on auto-configured addresses,
1524          * whenever in.ndpd gets a new prefix. This will be supported in
1525          * future releases.
1526          */
1527         if (ipaddr.ipadm_atype == IPADM_ADDR_IPV6_ADDRCONF)
1528                 return (IPADM_NOTSUP);
1529 
1530         /*
1531          * Setting an address property on an address object that is
1532          * not present in active configuration is not supported.
1533          */
1534         if (!(ipaddr.ipadm_flags & IPMGMT_ACTIVE))
1535                 return (IPADM_NOTSUP);
1536 
1537         af = ipaddr.ipadm_af;
1538         if (reset) {


2017                         err = nvpair_value_string(nvp, &sname);
2018                 else if (strcmp(name, IPADM_NVP_IPDADDRHNAME) == 0)
2019                         err = nvpair_value_string(nvp, &dname);
2020                 if (err != 0)
2021                         return (ipadm_errno2status(err));
2022         }
2023 
2024         if (strcmp(upstr, "yes") == 0)
2025                 flags |= IPADM_OPT_UP;
2026 
2027         /* build the address object from the above information */
2028         i_ipadm_init_addr(&ipaddr, ifname, aobjname, IPADM_ADDR_STATIC);
2029         if (prefixlenstr != NULL && atoi(prefixlenstr) > 0) {
2030                 if (asprintf(&cidraddr, "%s/%s", sname, prefixlenstr) == -1)
2031                         return (IPADM_NO_MEMORY);
2032                 status = ipadm_set_addr(&ipaddr, cidraddr, af);
2033                 free(cidraddr);
2034         } else {
2035                 status = ipadm_set_addr(&ipaddr, sname, af);
2036         }
2037 //      if (status != IPADM_SUCCESS)
2038 //              return (status);
2039 
2040         if (dname != NULL) {
2041                 status = ipadm_set_dst_addr(&ipaddr, dname, af);
2042                 if (status != IPADM_SUCCESS)
2043                         return (status);
2044         }
2045         return (i_ipadm_create_addr(iph, &ipaddr, flags));
2046 }
2047 
2048 /*
2049  * Creates a dhcp address on the interface `ifname' based on the
2050  * IPADM_ADDR_DHCP address object parameters from the nvlist `nvl'.
2051  */
2052 ipadm_status_t
2053 i_ipadm_enable_dhcp(ipadm_handle_t iph, const char *ifname, nvlist_t *nvl)
2054 {
2055         int32_t                 wait;
2056         boolean_t               primary;
2057         nvlist_t                *nvdhcp;
2058         nvpair_t                *nvp;


2163         ipadm_addrobj_t newaddr;
2164         ipadm_status_t  status;
2165         char            *aname, *cp;
2166         char            ifname[IPADM_AOBJSIZ];
2167         ifspec_t        ifsp;
2168 
2169         if (ipaddr == NULL)
2170                 return (IPADM_INVALID_ARG);
2171         *ipaddr = NULL;
2172 
2173         if (aobjname == NULL || aobjname[0] == '\0')
2174                 return (IPADM_INVALID_ARG);
2175 
2176         if (strlcpy(ifname, aobjname, IPADM_AOBJSIZ) >= IPADM_AOBJSIZ)
2177                 return (IPADM_INVALID_ARG);
2178 
2179         if ((aname = strchr(ifname, '/')) != NULL)
2180                 *aname++ = '\0';
2181 
2182         /* Check if the interface name is valid. */
2183         if (!ifparse_ifspec(ifname, &ifsp)) {
2184                 return (IPADM_INVALID_ARG);
2185         }
2186         /* Check if the given addrobj name is valid. */
2187         if (aname != NULL && !i_ipadm_is_user_aobjname_valid(aname)) {
2188                 return (IPADM_INVALID_ARG);
2189         }
2190         if ((newaddr = calloc(1, sizeof (struct ipadm_addrobj_s))) == NULL)
2191                 return (IPADM_NO_MEMORY);
2192 
2193         /*
2194          * If the ifname has logical interface number, extract it and assign
2195          * it to `ipadm_lifnum'. Only applications with IPH_LEGACY set will do
2196          * this today. We will check for the validity later in
2197          * i_ipadm_validate_create_addr().
2198          */
2199         if (ifsp.ifsp_lunvalid) {
2200                 newaddr->ipadm_lifnum = ifsp.ifsp_lun;
2201                 cp = strchr(ifname, IPADM_LOGICAL_SEP);
2202                 *cp = '\0';
2203         }
2204         (void) strlcpy(newaddr->ipadm_ifname, ifname,
2205             sizeof (newaddr->ipadm_ifname));
2206 
2207         if (aname != NULL) {
2208                 (void) snprintf(newaddr->ipadm_aobjname,
2209                     sizeof (newaddr->ipadm_aobjname), "%s/%s", ifname, aname);


2351                     iph->iph_sock6);
2352                 if (ioctl(sock, SIOCLIFADDIF, (caddr_t)&lifr) < 0)
2353                         return (ipadm_errno2status(errno));
2354                 addr->ipadm_lifnum = i_ipadm_get_lnum(lifr.lifr_name);
2355         }
2356         return (IPADM_SUCCESS);
2357 }
2358 
2359 /*
2360  * Reads all the address lines from the persistent DB into the nvlist `onvl',
2361  * when both `ifname' and `aobjname' are NULL. If an `ifname' is provided,
2362  * it returns all the addresses for the given interface `ifname'.
2363  * If an `aobjname' is specified, then the address line corresponding to
2364  * that name will be returned.
2365  */
2366 static ipadm_status_t
2367 i_ipadm_get_db_addr(ipadm_handle_t iph, const char *ifname,
2368     const char *aobjname, nvlist_t **onvl)
2369 {
2370         ipmgmt_getaddr_arg_t    garg;




2371 
2372         /* Populate the door_call argument structure */
2373         bzero(&garg, sizeof (garg));
2374         garg.ia_cmd = IPMGMT_CMD_GETADDR;
2375         if (aobjname != NULL)
2376                 (void) strlcpy(garg.ia_aobjname, aobjname,
2377                     sizeof (garg.ia_aobjname));
2378         if (ifname != NULL)
2379                 (void) strlcpy(garg.ia_ifname, ifname, sizeof (garg.ia_ifname));
2380 
2381         return (i_ipadm_call_ipmgmtd(iph, (void *) &garg, sizeof (garg), onvl));









2382 }
2383 
2384 /*
2385  * Adds the IP address contained in the 'ipaddr' argument to the physical
2386  * interface represented by 'ifname' after doing the required validation.
2387  * If the interface does not exist, it is created before the address is
2388  * added.
2389  *
2390  * If IPH_LEGACY is set in iph_flags, flags has to be IPADM_OPT_ACTIVE
2391  * and a default addrobj name will be generated. Input `addr->ipadm_aobjname',
2392  * if provided, will be ignored and replaced with the newly generated name.
2393  * The interface name provided has to be a logical interface name that
2394  * already exists. No new logical interface will be added in this function.
2395  *
2396  * If IPADM_OPT_V46 is passed in the flags, then both IPv4 and IPv6 interfaces
2397  * are plumbed (if they haven't been already).  Otherwise, just the interface
2398  * specified in `addr' is plumbed.
2399  */
2400 ipadm_status_t
2401 ipadm_create_addr(ipadm_handle_t iph, ipadm_addrobj_t addr, uint32_t flags)


2404         sa_family_t             af;
2405         sa_family_t             daf;
2406         sa_family_t             other_af;
2407         boolean_t               created_af = B_FALSE;
2408         boolean_t               created_other_af = B_FALSE;
2409         ipadm_addr_type_t       type;
2410         char                    *ifname = addr->ipadm_ifname;
2411         boolean_t               legacy = (iph->iph_flags & IPH_LEGACY);
2412         boolean_t               aobjfound;
2413         boolean_t               is_6to4;
2414         struct lifreq           lifr;
2415         uint64_t                ifflags;
2416         boolean_t               is_boot = (iph->iph_flags & IPH_IPMGMTD);
2417 
2418         /* check for solaris.network.interface.config authorization */
2419         if (!ipadm_check_auth())
2420                 return (IPADM_EAUTH);
2421 
2422         /* Validate the addrobj. This also fills in addr->ipadm_ifname. */
2423         status = i_ipadm_validate_create_addr(iph, addr, flags);
2424         if (status != IPADM_SUCCESS) {
2425                 return (status);
2426         }
2427         /*
2428          * For Legacy case, check if an addrobj already exists for the
2429          * given logical interface name. If one does not exist,
2430          * a default name will be generated and added to the daemon's
2431          * aobjmap.
2432          */
2433         if (legacy) {
2434                 struct ipadm_addrobj_s  ipaddr;
2435 
2436                 ipaddr = *addr;
2437                 status = i_ipadm_get_lif2addrobj(iph, &ipaddr);
2438                 if (status == IPADM_SUCCESS) {
2439                         aobjfound = B_TRUE;
2440                         /*
2441                          * With IPH_LEGACY, modifying an address that is not
2442                          * a static address will return with an error.
2443                          */
2444                         if (ipaddr.ipadm_atype != IPADM_ADDR_STATIC)
2445                                 return (IPADM_NOTSUP);
2446                         /*


2453                         aobjfound = B_FALSE;
2454                 } else {
2455                         return (status);
2456                 }
2457         }
2458 
2459         af = addr->ipadm_af;
2460         /*
2461          * Create a placeholder for this address object in the daemon.
2462          * Skip this step if we are booting a zone (and therefore being called
2463          * from ipmgmtd itself), and, for IPH_LEGACY case if the
2464          * addrobj already exists.
2465          *
2466          * Note that the placeholder is not needed in the NGZ boot case,
2467          * when zoneadmd has itself applied the "allowed-ips" property to clamp
2468          * down any interface configuration, so the namespace for the interface
2469          * is fully controlled by the GZ.
2470          */
2471         if (!is_boot && (!legacy || !aobjfound)) {
2472                 status = i_ipadm_lookupadd_addrobj(iph, addr);
2473                 if (status != IPADM_SUCCESS) {
2474                         return (status);
2475                 }
2476         }
2477 
2478         is_6to4 = i_ipadm_is_6to4(iph, ifname);
2479         /* Plumb the IP interfaces if necessary */
2480         status = i_ipadm_create_if(iph, ifname, af, flags);
2481         if (status != IPADM_SUCCESS && status != IPADM_IF_EXISTS) {
2482                 (void) i_ipadm_delete_addrobj(iph, addr, IPADM_OPT_ACTIVE);
2483                 return (status);
2484         }
2485         if (status == IPADM_SUCCESS)
2486                 created_af = B_TRUE;
2487         if (!is_6to4 && !legacy && (flags & IPADM_OPT_V46)) {
2488                 other_af = (af == AF_INET ? AF_INET6 : AF_INET);
2489                 status = i_ipadm_create_if(iph, ifname, other_af, flags);
2490                 if (status != IPADM_SUCCESS && status != IPADM_IF_EXISTS) {
2491                         (void) i_ipadm_delete_if(iph, ifname, af, flags);
2492                         return (status);
2493                 }
2494                 if (status == IPADM_SUCCESS)
2495                         created_other_af = B_TRUE;
2496         }


2604                 }
2605         }
2606 
2607         return (status);
2608 }
2609 
2610 /*
2611  * Creates the static address in `ipaddr' in kernel. After successfully
2612  * creating it, it updates the ipmgmtd daemon's aobjmap with the logical
2613  * interface information.
2614  */
2615 static ipadm_status_t
2616 i_ipadm_create_addr(ipadm_handle_t iph, ipadm_addrobj_t ipaddr, uint32_t flags)
2617 {
2618         struct lifreq                   lifr;
2619         ipadm_status_t                  status = IPADM_SUCCESS;
2620         int                             sock;
2621         struct sockaddr_storage         m, *mask = &m;
2622         const struct sockaddr_storage   *addr = &ipaddr->ipadm_static_addr;
2623         const struct sockaddr_storage   *daddr = &ipaddr->ipadm_static_dst_addr;
2624         uint32_t                        iff_flags = IFF_UP;
2625         sa_family_t                     af;
2626         boolean_t                       legacy = (iph->iph_flags & IPH_LEGACY);
2627         struct ipadm_addrobj_s          legacy_addr;
2628         boolean_t                       default_prefixlen = B_FALSE;
2629         boolean_t                       is_boot;
2630 
2631         is_boot = ((iph->iph_flags & IPH_IPMGMTD) != 0);
2632         af = ipaddr->ipadm_af;
2633         sock = (af == AF_INET ? iph->iph_sock : iph->iph_sock6);
2634 
2635         /* If prefixlen was not provided, get default prefixlen */
2636         if (ipaddr->ipadm_static_prefixlen == 0) {
2637                 /* prefixlen was not provided, get default prefixlen */
2638                 status = i_ipadm_get_default_prefixlen(
2639                     &ipaddr->ipadm_static_addr,
2640                     &ipaddr->ipadm_static_prefixlen);
2641                 if (status != IPADM_SUCCESS)
2642                         return (status);
2643                 default_prefixlen = B_TRUE;
2644         }


2674         lifr.lifr_addr = *mask;
2675         if (ioctl(sock, SIOCSLIFNETMASK, (caddr_t)&lifr) < 0) {
2676                 status = ipadm_errno2status(errno);
2677                 goto ret;
2678         }
2679         lifr.lifr_addr = *addr;
2680         if (ioctl(sock, SIOCSLIFADDR, (caddr_t)&lifr) < 0) {
2681                 status = ipadm_errno2status(errno);
2682                 goto ret;
2683         }
2684         /* Set the destination address, if one is given. */
2685         if (daddr->ss_family != AF_UNSPEC) {
2686                 lifr.lifr_addr = *daddr;
2687                 if (ioctl(sock, SIOCSLIFDSTADDR, (caddr_t)&lifr) < 0) {
2688                         status = ipadm_errno2status(errno);
2689                         goto ret;
2690                 }
2691         }
2692 
2693         if (flags & IPADM_OPT_UP) {
2694                 if (i_ipadm_is_under_ipmp(iph, lifr.lifr_name)) {
2695                         iff_flags |= IFF_NOFAILOVER;
2696                 }
2697                 status = i_ipadm_set_flags(iph, lifr.lifr_name, af, iff_flags, 0);
2698 
2699                 /*
2700                  * IPADM_DAD_FOUND is a soft-error for create-addr.
2701                  * No need to tear down the address.
2702                  */
2703                 if (status == IPADM_DAD_FOUND)
2704                         status = IPADM_SUCCESS;
2705         }
2706 
2707         if (status == IPADM_SUCCESS && !is_boot) {
2708                 /*
2709                  * For IPH_LEGACY, we might be modifying the address on
2710                  * an address object that already exists e.g. by doing
2711                  * "ifconfig bge0:1 <addr>; ifconfig bge0:1 <newaddr>"
2712                  * So, we need to store the object only if it does not
2713                  * already exist in ipmgmtd.
2714                  */
2715                 if (legacy) {
2716                         bzero(&legacy_addr, sizeof (legacy_addr));
2717                         (void) strlcpy(legacy_addr.ipadm_aobjname,


3180         ipadm_status_t  status;
3181         char            lifname[LIFNAMSIZ];
3182 
3183         /* check for solaris.network.interface.config authorization */
3184         if (!ipadm_check_auth())
3185                 return (IPADM_EAUTH);
3186 
3187         /* validate input */
3188         if (aobjname == NULL || strlcpy(ipaddr->ipadm_aobjname, aobjname,
3189             IPADM_AOBJSIZ) >= IPADM_AOBJSIZ) {
3190                 return (IPADM_INVALID_ARG);
3191         }
3192 
3193         /* Retrieve the address object information. */
3194         status = i_ipadm_get_addrobj(iph, ipaddr);
3195         if (status != IPADM_SUCCESS)
3196                 return (status);
3197 
3198         if (!(ipaddr->ipadm_flags & IPMGMT_ACTIVE))
3199                 return (IPADM_OP_DISABLE_OBJ);
3200 
3201         if ((ipadm_flags & IPADM_OPT_PERSIST) &&
3202             !(ipaddr->ipadm_flags & IPMGMT_PERSIST))
3203                 return (IPADM_TEMPORARY_OBJ);
3204 
3205         if (ipaddr->ipadm_atype == IPADM_ADDR_IPV6_ADDRCONF ||
3206             (ipaddr->ipadm_atype == IPADM_ADDR_DHCP &&
3207             (ipadm_flags & IPADM_OPT_PERSIST)))
3208                 return (IPADM_NOTSUP);
3209 
3210         i_ipadm_addrobj2lifname(ipaddr, lifname, sizeof (lifname));
3211 
3212         return (i_ipadm_get_flags(iph, lifname, ipaddr->ipadm_af, ifflags));
3213 }
3214 
3215 /*
3216  * Marks the address in the address object `aobjname' up. This operation is
3217  * not supported for an address object of type IPADM_ADDR_IPV6_ADDRCONF.
3218  * For an address object of type IPADM_ADDR_DHCP, this operation can
3219  * only be temporary and no updates will be made to the persistent DB.
3220  */
3221 ipadm_status_t
3222 ipadm_up_addr(ipadm_handle_t iph, const char *aobjname, uint32_t ipadm_flags)
3223 {
3224         struct ipadm_addrobj_s ipaddr;
3225         ipadm_status_t  status;
3226         uint64_t        flags;
3227         char            lifname[LIFNAMSIZ];
3228 
3229         status = i_ipadm_updown_common(iph, aobjname, &ipaddr, ipadm_flags,
3230             &flags);
3231         if (status != IPADM_SUCCESS)


3403         uint64_t                ifflags = 0;
3404         boolean_t               p_exists;
3405         boolean_t               af_exists, other_af_exists, a_exists;
3406 
3407         if (ipaddr == NULL || flags == 0 || flags == IPADM_OPT_PERSIST ||
3408             (flags & ~(IPADM_COMMON_OPT_MASK|IPADM_OPT_UP|IPADM_OPT_V46))) {
3409                 return (IPADM_INVALID_ARG);
3410         }
3411 
3412         if (ipaddr->ipadm_af == AF_UNSPEC)
3413                 return (IPADM_BAD_ADDR);
3414 
3415         if (!legacy && ipaddr->ipadm_lifnum != 0)
3416                 return (IPADM_INVALID_ARG);
3417 
3418         if (legacy && ipaddr->ipadm_atype != IPADM_ADDR_STATIC)
3419                 return (IPADM_NOTSUP);
3420 
3421         ifname = ipaddr->ipadm_ifname;
3422 
3423         /*
3424          * do not go furhter when we are under ipmp. 
3425          * The interface is plumbed up and we are going to add
3426          * NOFAILOVER address to make in.mpathd happy.
3427          */ 
3428         if (i_ipadm_is_under_ipmp(iph, ifname))
3429                 return (IPADM_SUCCESS);
3430 
3431         af = ipaddr->ipadm_af;
3432         af_exists = ipadm_if_enabled(iph, ifname, af);
3433         /*
3434          * For legacy case, interfaces are not implicitly plumbed. We need to
3435          * check if the interface exists in the active configuration.
3436          */
3437         if (legacy && !af_exists)
3438                 return (IPADM_ENXIO);
3439 
3440         other_af = (af == AF_INET ? AF_INET6 : AF_INET);
3441         other_af_exists = ipadm_if_enabled(iph, ifname, other_af);
3442         /*
3443          * Check if one of the v4 or the v6 interfaces exists in the
3444          * active configuration. An interface is considered disabled only
3445          * if both v4 and v6 are not active.
3446          */
3447         a_exists = (af_exists || other_af_exists);
3448 
3449         /* Check if interface exists in the persistent configuration. */
3450         status = i_ipadm_if_pexists(iph, ifname, af, &p_exists);
3451         if (status != IPADM_SUCCESS)
3452                 return (status);
3453 
3454         if (!a_exists && p_exists)
3455                 return (IPADM_OP_DISABLE_OBJ);
3456 







3457         if (af_exists) {
3458                 status = i_ipadm_get_flags(iph, ifname, af, &ifflags);
3459                 if (status != IPADM_SUCCESS)
3460                         return (status);
3461         }
3462 
3463         /* Perform validation steps (4) and (5) */
3464         islo = i_ipadm_is_loopback(ifname);
3465         isvni = i_ipadm_is_vni(ifname);
3466         switch (ipaddr->ipadm_atype) {
3467         case IPADM_ADDR_STATIC:
3468                 if ((islo || isvni) && ipaddr->ipadm_static_dname[0] != '\0')
3469                         return (IPADM_INVALID_ARG);
3470                 /* Check for a valid src address */
3471                 if (!legacy && sockaddrunspec(
3472                     (struct sockaddr *)&ipaddr->ipadm_static_addr))
3473                         return (IPADM_BAD_ADDR);
3474                 break;
3475         case IPADM_ADDR_DHCP:
3476                 if (islo || (ifflags & IFF_VRRP))