1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2013 by Delphix. All rights reserved.
24 * Copyright (c) 2016-2017, Chris Fraire <cfraire@me.com>.
25 */
26
27 /*
28 * This file contains functions for address management such as creating
29 * an address, deleting an address, enabling an address, disabling an
30 * address, bringing an address down or up, setting/getting properties
31 * on an address object and listing address information
32 * for all addresses in active as well as persistent configuration.
33 */
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <sys/param.h>
37 #include <netdb.h>
38 #include <inet/ip.h>
39 #include <string.h>
40 #include <strings.h>
41 #include <assert.h>
42 #include <sys/sockio.h>
43 #include <errno.h>
280 continue;
281 if (nvlist_exists(anvl, IPADM_NVP_IPV4ADDR) ||
282 nvlist_exists(anvl, IPADM_NVP_IPV6ADDR))
283 break;
284 }
285 if (nvp == NULL)
286 goto fail;
287 for (nvp = nvlist_next_nvpair(anvl, NULL);
288 nvp != NULL; nvp = nvlist_next_nvpair(anvl, nvp)) {
289 name = nvpair_name(nvp);
290 if (strcmp(name, IPADM_NVP_IPV4ADDR) == 0) {
291 af = AF_INET;
292 break;
293 } else if (strcmp(name, IPADM_NVP_IPV6ADDR) == 0) {
294 af = AF_INET6;
295 break;
296 }
297 }
298 assert(af != AF_UNSPEC);
299 if (nvpair_value_nvlist(nvp, &nvladdr) != 0 ||
300 nvlist_lookup_string(nvladdr, IPADM_NVP_IPADDRHNAME, &sname) != 0 ||
301 ipadm_set_addr(ipaddr, sname, af) != IPADM_SUCCESS) {
302 goto fail;
303 }
304 nvlist_free(onvl);
305 return (IPADM_SUCCESS);
306 fail:
307 nvlist_free(onvl);
308 return (IPADM_NOTFOUND);
309 }
310
311 /*
312 * For the given `addrobj->ipadm_lifnum' and `addrobj->ipadm_af', this function
313 * fills in the address objname, the address type and the ipadm_flags.
314 */
315 ipadm_status_t
316 i_ipadm_get_lif2addrobj(ipadm_handle_t iph, ipadm_addrobj_t addrobj)
317 {
318 ipmgmt_aobjop_arg_t larg;
319 ipmgmt_aobjop_rval_t rval, *rvalp;
320 int err;
321
322 larg.ia_cmd = IPMGMT_CMD_LIF2ADDROBJ;
323 (void) strlcpy(larg.ia_ifname, addrobj->ipadm_ifname,
366 * daemon's aobjmap (active configuration). This API is called by in.ndpd to
367 * remove addrobjs when auto-configured prefixes or dhcpv6 addresses are
368 * removed.
369 */
370 ipadm_status_t
371 ipadm_delete_aobjname(ipadm_handle_t iph, const char *ifname, sa_family_t af,
372 const char *aobjname, ipadm_addr_type_t atype, int lnum)
373 {
374 struct ipadm_addrobj_s aobj;
375
376 i_ipadm_init_addr(&aobj, ifname, aobjname, atype);
377 aobj.ipadm_af = af;
378 aobj.ipadm_lifnum = lnum;
379 return (i_ipadm_delete_addrobj(iph, &aobj, IPADM_OPT_ACTIVE));
380 }
381
382 /*
383 * Gets all the addresses from active configuration and populates the
384 * address information in `addrinfo'.
385 */
386 static ipadm_status_t
387 i_ipadm_active_addr_info(ipadm_handle_t iph, const char *ifname,
388 ipadm_addr_info_t **addrinfo, uint32_t ipadm_flags, int64_t lifc_flags)
389 {
390 ipadm_status_t status;
391 struct ifaddrs *ifap, *ifa;
392 ipadm_addr_info_t *curr, *prev = NULL;
393 struct ifaddrs *cifaddr;
394 struct lifreq lifr;
395 int sock;
396 uint64_t flags;
397 char cifname[LIFNAMSIZ];
398 struct sockaddr_in6 *sin6;
399 struct ipadm_addrobj_s ipaddr;
400 char *sep;
401 int lnum;
402
403 retry:
404 *addrinfo = NULL;
405
406 /* Get all the configured addresses */
1696 if (!(pdp->ipd_flags & IPADMPROP_MULVAL) &&
1697 (pflags & (IPADM_OPT_APPEND|IPADM_OPT_REMOVE))) {
1698 return (IPADM_INVALID_ARG);
1699 }
1700
1701 /*
1702 * For the given aobjname, get the addrobj it represents and
1703 * set the property value for that object.
1704 */
1705 i_ipadm_init_addr(&ipaddr, "", aobjname, IPADM_ADDR_NONE);
1706 if ((status = i_ipadm_get_addrobj(iph, &ipaddr)) != IPADM_SUCCESS)
1707 return (status);
1708
1709 if (!(ipaddr.ipadm_flags & IPMGMT_ACTIVE))
1710 return (IPADM_OP_DISABLE_OBJ);
1711
1712 /* Persistent operation not allowed on a temporary object. */
1713 if ((pflags & IPADM_OPT_PERSIST) &&
1714 !(ipaddr.ipadm_flags & IPMGMT_PERSIST))
1715 return (IPADM_TEMPORARY_OBJ);
1716
1717 /*
1718 * Currently, setting an address property on an address object of type
1719 * IPADM_ADDR_IPV6_ADDRCONF is not supported. Supporting it involves
1720 * in.ndpd retrieving the address properties from ipmgmtd for given
1721 * address object and then setting them on auto-configured addresses,
1722 * whenever in.ndpd gets a new prefix. This will be supported in
1723 * future releases.
1724 */
1725 if (ipaddr.ipadm_atype == IPADM_ADDR_IPV6_ADDRCONF)
1726 return (IPADM_NOTSUP);
1727
1728 /*
1729 * Setting an address property on an address object that is
1730 * not present in active configuration is not supported.
1731 */
1732 if (!(ipaddr.ipadm_flags & IPMGMT_ACTIVE))
1733 return (IPADM_NOTSUP);
1734
1735 af = ipaddr.ipadm_af;
1736 if (reset) {
2392 char *aname, *cp;
2393 char ifname[IPADM_AOBJSIZ];
2394 ifspec_t ifsp;
2395
2396 if (ipaddr == NULL)
2397 return (IPADM_INVALID_ARG);
2398 *ipaddr = NULL;
2399
2400 if (aobjname == NULL || aobjname[0] == '\0')
2401 return (IPADM_INVALID_ARG);
2402
2403 if (strlcpy(ifname, aobjname, IPADM_AOBJSIZ) >= IPADM_AOBJSIZ)
2404 return (IPADM_INVALID_ARG);
2405
2406 if ((aname = strchr(ifname, '/')) != NULL)
2407 *aname++ = '\0';
2408
2409 /* Check if the interface name is valid. */
2410 if (!ifparse_ifspec(ifname, &ifsp))
2411 return (IPADM_INVALID_ARG);
2412
2413 /* Check if the given addrobj name is valid. */
2414 if (aname != NULL && !i_ipadm_is_user_aobjname_valid(aname))
2415 return (IPADM_INVALID_ARG);
2416
2417 if ((newaddr = calloc(1, sizeof (struct ipadm_addrobj_s))) == NULL)
2418 return (IPADM_NO_MEMORY);
2419
2420 /*
2421 * If the ifname has logical interface number, extract it and assign
2422 * it to `ipadm_lifnum'. Only applications with IPH_LEGACY set will do
2423 * this today. We will check for the validity later in
2424 * i_ipadm_validate_create_addr().
2425 */
2426 if (ifsp.ifsp_lunvalid) {
2427 newaddr->ipadm_lifnum = ifsp.ifsp_lun;
2428 cp = strchr(ifname, IPADM_LOGICAL_SEP);
2429 *cp = '\0';
2430 }
2431 (void) strlcpy(newaddr->ipadm_ifname, ifname,
2432 sizeof (newaddr->ipadm_ifname));
2433
2434 if (aname != NULL) {
2435 (void) snprintf(newaddr->ipadm_aobjname,
2436 sizeof (newaddr->ipadm_aobjname), "%s/%s", ifname, aname);
2578 iph->iph_sock6);
2579 if (ioctl(sock, SIOCLIFADDIF, (caddr_t)&lifr) < 0)
2580 return (ipadm_errno2status(errno));
2581 addr->ipadm_lifnum = i_ipadm_get_lnum(lifr.lifr_name);
2582 }
2583 return (IPADM_SUCCESS);
2584 }
2585
2586 /*
2587 * Reads all the address lines from the persistent DB into the nvlist `onvl',
2588 * when both `ifname' and `aobjname' are NULL. If an `ifname' is provided,
2589 * it returns all the addresses for the given interface `ifname'.
2590 * If an `aobjname' is specified, then the address line corresponding to
2591 * that name will be returned.
2592 */
2593 static ipadm_status_t
2594 i_ipadm_get_db_addr(ipadm_handle_t iph, const char *ifname,
2595 const char *aobjname, nvlist_t **onvl)
2596 {
2597 ipmgmt_getaddr_arg_t garg;
2598 ipmgmt_get_rval_t *rvalp;
2599 int err;
2600 size_t nvlsize;
2601 char *nvlbuf;
2602
2603 /* Populate the door_call argument structure */
2604 bzero(&garg, sizeof (garg));
2605 garg.ia_cmd = IPMGMT_CMD_GETADDR;
2606 if (aobjname != NULL)
2607 (void) strlcpy(garg.ia_aobjname, aobjname,
2608 sizeof (garg.ia_aobjname));
2609 if (ifname != NULL)
2610 (void) strlcpy(garg.ia_ifname, ifname, sizeof (garg.ia_ifname));
2611
2612 rvalp = malloc(sizeof (ipmgmt_get_rval_t));
2613 err = ipadm_door_call(iph, &garg, sizeof (garg), (void **)&rvalp,
2614 sizeof (*rvalp), B_TRUE);
2615 if (err == 0) {
2616 nvlsize = rvalp->ir_nvlsize;
2617 nvlbuf = (char *)rvalp + sizeof (ipmgmt_get_rval_t);
2618 err = nvlist_unpack(nvlbuf, nvlsize, onvl, NV_ENCODE_NATIVE);
2619 }
2620 free(rvalp);
2621 return (ipadm_errno2status(err));
2622 }
2623
2624 /*
2625 * Adds the IP address contained in the 'ipaddr' argument to the physical
2626 * interface represented by 'ifname' after doing the required validation.
2627 * If the interface does not exist, it is created before the address is
2628 * added.
2629 *
2630 * If IPH_LEGACY is set in iph_flags, flags has to be IPADM_OPT_ACTIVE
2631 * and a default addrobj name will be generated. Input `addr->ipadm_aobjname',
2632 * if provided, will be ignored and replaced with the newly generated name.
2633 * The interface name provided has to be a logical interface name that
2634 * already exists. No new logical interface will be added in this function.
2635 *
2636 * If IPADM_OPT_V46 is passed in the flags, then both IPv4 and IPv6 interfaces
2637 * are plumbed (if they haven't been already). Otherwise, just the interface
2638 * specified in `addr' is plumbed.
2639 */
2640 ipadm_status_t
2641 ipadm_create_addr(ipadm_handle_t iph, ipadm_addrobj_t addr, uint32_t flags)
2642 {
2643 ipadm_status_t status;
2644 sa_family_t af;
2645 sa_family_t daf;
2646 sa_family_t other_af;
2647 boolean_t created_af = B_FALSE;
2648 boolean_t created_other_af = B_FALSE;
2649 ipadm_addr_type_t type;
2650 char *ifname = addr->ipadm_ifname;
2651 boolean_t legacy = (iph->iph_flags & IPH_LEGACY);
2652 boolean_t aobjfound;
2653 boolean_t is_6to4;
2654 struct lifreq lifr;
2655 uint64_t ifflags;
2656 boolean_t is_boot = (iph->iph_flags & IPH_IPMGMTD);
2657
2658 /* check for solaris.network.interface.config authorization */
2659 if (!ipadm_check_auth())
2660 return (IPADM_EAUTH);
2661
2662 /* Validate the addrobj. This also fills in addr->ipadm_ifname. */
2663 status = i_ipadm_validate_create_addr(iph, addr, flags);
2664 if (status != IPADM_SUCCESS)
2665 return (status);
2666
2667 /*
2668 * For Legacy case, check if an addrobj already exists for the
2669 * given logical interface name. If one does not exist,
2670 * a default name will be generated and added to the daemon's
2671 * aobjmap.
2672 */
2673 if (legacy) {
2674 struct ipadm_addrobj_s ipaddr;
2675
2676 ipaddr = *addr;
2677 status = i_ipadm_get_lif2addrobj(iph, &ipaddr);
2678 if (status == IPADM_SUCCESS) {
2679 aobjfound = B_TRUE;
2680 /*
2681 * With IPH_LEGACY, modifying an address that is not
2682 * a static address will return with an error.
2683 */
2684 if (ipaddr.ipadm_atype != IPADM_ADDR_STATIC)
2685 return (IPADM_NOTSUP);
2686 /*
2781 }
2782 }
2783
2784 /*
2785 * For 6to4 interfaces, kernel configures a default link-local
2786 * address. We need to replace it, if the caller has provided
2787 * an address that is different from the default link-local.
2788 */
2789 if (status == IPADM_SUCCESS && is_6to4) {
2790 bzero(&lifr, sizeof (lifr));
2791 (void) strlcpy(lifr.lifr_name, addr->ipadm_ifname,
2792 sizeof (lifr.lifr_name));
2793 if (ioctl(iph->iph_sock6, SIOCGLIFADDR, &lifr) < 0) {
2794 status = ipadm_errno2status(errno);
2795 goto fail;
2796 }
2797 if (sockaddrcmp(&lifr.lifr_addr, &addr->ipadm_static_addr))
2798 return (IPADM_SUCCESS);
2799 }
2800
2801 /* Create the address. */
2802 type = addr->ipadm_atype;
2803 switch (type) {
2804 case IPADM_ADDR_STATIC:
2805 status = i_ipadm_create_addr(iph, addr, flags);
2806 break;
2807 case IPADM_ADDR_DHCP:
2808 status = i_ipadm_create_dhcp(iph, addr, flags);
2809 break;
2810 case IPADM_ADDR_IPV6_ADDRCONF:
2811 status = i_ipadm_create_ipv6addrs(iph, addr, flags);
2812 break;
2813 default:
2814 status = IPADM_INVALID_ARG;
2815 break;
2816 }
2817
2818 /*
2819 * If address was not created successfully, unplumb the interface
2820 * if it was plumbed implicitly in this function and remove the
2821 * addrobj created by the ipmgmtd daemon as a placeholder.
2822 * If IPH_LEGACY is set, then remove the addrobj only if it was
2823 * created in this function.
2824 */
2825 fail:
2826 if (status != IPADM_DHCP_IPC_TIMEOUT &&
2827 status != IPADM_SUCCESS) {
2828 if (!legacy) {
2829 if (created_af || created_other_af) {
2830 if (created_af) {
2831 (void) i_ipadm_delete_if(iph, ifname,
2832 af, flags);
2833 }
2834 if (created_other_af) {
2835 (void) i_ipadm_delete_if(iph, ifname,
2836 other_af, flags);
2837 }
2870 af = ipaddr->ipadm_af;
2871 sock = (af == AF_INET ? iph->iph_sock : iph->iph_sock6);
2872
2873 /* If prefixlen was not provided, get default prefixlen */
2874 if (ipaddr->ipadm_static_prefixlen == 0) {
2875 /* prefixlen was not provided, get default prefixlen */
2876 status = i_ipadm_get_default_prefixlen(
2877 &ipaddr->ipadm_static_addr,
2878 &ipaddr->ipadm_static_prefixlen);
2879 if (status != IPADM_SUCCESS)
2880 return (status);
2881 default_prefixlen = B_TRUE;
2882 }
2883 (void) plen2mask(ipaddr->ipadm_static_prefixlen, af,
2884 (struct sockaddr *)mask);
2885
2886 /*
2887 * Create a new logical interface if needed; otherwise, just
2888 * use the 0th logical interface.
2889 */
2890 retry:
2891 if (!(iph->iph_flags & IPH_LEGACY)) {
2892 status = i_ipadm_do_addif(iph, ipaddr);
2893 if (status != IPADM_SUCCESS)
2894 return (status);
2895 /*
2896 * We don't have to set the lifnum for IPH_INIT case, because
2897 * there is no placeholder created for the address object in
2898 * this case. For IPH_LEGACY, we don't do this because the
2899 * lifnum is given by the caller and it will be set in the
2900 * end while we call the i_ipadm_addr_persist().
2901 */
2902 if (!(iph->iph_flags & IPH_INIT)) {
2903 status = i_ipadm_setlifnum_addrobj(iph, ipaddr);
2904 if (status == IPADM_ADDROBJ_EXISTS)
2905 goto retry;
2906 if (status != IPADM_SUCCESS)
2907 return (status);
2908 }
2909 }
2910 i_ipadm_addrobj2lifname(ipaddr, lifr.lifr_name,
2911 sizeof (lifr.lifr_name));
2912 lifr.lifr_addr = *mask;
2913 if (ioctl(sock, SIOCSLIFNETMASK, (caddr_t)&lifr) < 0) {
2914 status = ipadm_errno2status(errno);
2915 goto ret;
2916 }
2917 lifr.lifr_addr = *addr;
2918 if (ioctl(sock, SIOCSLIFADDR, (caddr_t)&lifr) < 0) {
2919 status = ipadm_errno2status(errno);
2920 goto ret;
2921 }
2922 /* Set the destination address, if one is given. */
2923 if (daddr->ss_family != AF_UNSPEC) {
2924 lifr.lifr_addr = *daddr;
2925 if (ioctl(sock, SIOCSLIFDSTADDR, (caddr_t)&lifr) < 0) {
2926 status = ipadm_errno2status(errno);
2927 goto ret;
2928 }
2929 }
2930
2931 if (flags & IPADM_OPT_UP) {
2932 status = i_ipadm_set_flags(iph, lifr.lifr_name, af, IFF_UP, 0);
2933
2934 /*
2935 * IPADM_DAD_FOUND is a soft-error for create-addr.
2936 * No need to tear down the address.
2937 */
2938 if (status == IPADM_DAD_FOUND)
2939 status = IPADM_SUCCESS;
2940 }
2941
2942 if (status == IPADM_SUCCESS && !is_boot) {
2943 /*
2944 * For IPH_LEGACY, we might be modifying the address on
2945 * an address object that already exists e.g. by doing
2946 * "ifconfig bge0:1 <addr>; ifconfig bge0:1 <newaddr>"
2947 * So, we need to store the object only if it does not
2948 * already exist in ipmgmtd.
2949 */
2950 if (legacy) {
2951 bzero(&legacy_addr, sizeof (legacy_addr));
2952 (void) strlcpy(legacy_addr.ipadm_aobjname,
2953 ipaddr->ipadm_aobjname,
2954 sizeof (legacy_addr.ipadm_aobjname));
2955 status = i_ipadm_get_addrobj(iph, &legacy_addr);
2956 if (status == IPADM_SUCCESS &&
2957 legacy_addr.ipadm_lifnum >= 0) {
2958 return (status);
2959 }
2960 }
2961 status = i_ipadm_addr_persist(iph, ipaddr, default_prefixlen,
2962 flags, NULL);
2963 }
2964 ret:
2965 if (status != IPADM_SUCCESS && !legacy)
2966 (void) i_ipadm_delete_addr(iph, ipaddr);
2967 return (status);
2968 }
2969
2970 /*
2971 * Removes the address object identified by `aobjname' from both active and
2972 * persistent configuration. The address object will be removed from only
2973 * active configuration if IPH_LEGACY is set in `iph->iph_flags'.
2974 *
2975 * If the address type is IPADM_ADDR_STATIC or IPADM_ADDR_DHCP, the address
2976 * in the address object will be removed from the physical interface.
2977 * If the address type is IPADM_ADDR_DHCP, the flag IPADM_OPT_RELEASE specifies
2978 * whether the lease should be released. If IPADM_OPT_RELEASE is not
2979 * specified, the lease will be dropped. This option is not supported
2980 * for other address types.
2981 *
2982 * If the address type is IPADM_ADDR_IPV6_ADDRCONF, the link-local address and
2983 * all the autoconfigured addresses will be removed.
2984 * Finally, the address object is also removed from ipmgmtd's aobjmap and from
2985 * the persistent DB.
2986 */
3011 status = i_ipadm_get_addrobj(iph, &ipaddr);
3012 if (status != IPADM_SUCCESS)
3013 return (status);
3014
3015 if (release && ipaddr.ipadm_atype != IPADM_ADDR_DHCP)
3016 return (IPADM_NOTSUP);
3017 /*
3018 * If requested to delete just from active config but the address
3019 * is not in active config, return error.
3020 */
3021 if (!(ipaddr.ipadm_flags & IPMGMT_ACTIVE) &&
3022 (flags & IPADM_OPT_ACTIVE) && !(flags & IPADM_OPT_PERSIST)) {
3023 return (IPADM_NOTFOUND);
3024 }
3025
3026 /*
3027 * If address is present in active config, remove it from
3028 * kernel.
3029 */
3030 if (ipaddr.ipadm_flags & IPMGMT_ACTIVE) {
3031 switch (ipaddr.ipadm_atype) {
3032 case IPADM_ADDR_STATIC:
3033 status = i_ipadm_delete_addr(iph, &ipaddr);
3034 break;
3035 case IPADM_ADDR_DHCP:
3036 status = i_ipadm_delete_dhcp(iph, &ipaddr, release);
3037 break;
3038 case IPADM_ADDR_IPV6_ADDRCONF:
3039 status = i_ipadm_delete_ipv6addrs(iph, &ipaddr);
3040 break;
3041 default:
3042 /*
3043 * This is the case of address object name residing in
3044 * daemon's aobjmap (added by ADDROBJ_LOOKUPADD). Fall
3045 * through and delete that address object.
3046 */
3047 break;
3048 }
3049
3050 /*
3051 * If the address was previously deleted from the active
3052 * config, we will get a IPADM_ENXIO from kernel.
3053 * We will still proceed and purge the address information
3054 * in the DB.
3055 */
3056 if (status == IPADM_ENXIO)
3057 status = IPADM_SUCCESS;
3058 else if (status != IPADM_SUCCESS)
3059 return (status);
3060 }
3061
3062 if (!(ipaddr.ipadm_flags & IPMGMT_PERSIST) &&
3063 (flags & IPADM_OPT_PERSIST)) {
3064 flags &= ~IPADM_OPT_PERSIST;
3065 }
3066 status = i_ipadm_delete_addrobj(iph, &ipaddr, flags);
3067 if (status == IPADM_NOTFOUND)
3068 return (status);
3069 return (IPADM_SUCCESS);
3551 ipadm_status_t status;
3552 char lifname[LIFNAMSIZ];
3553
3554 /* check for solaris.network.interface.config authorization */
3555 if (!ipadm_check_auth())
3556 return (IPADM_EAUTH);
3557
3558 /* validate input */
3559 if (aobjname == NULL || strlcpy(ipaddr->ipadm_aobjname, aobjname,
3560 IPADM_AOBJSIZ) >= IPADM_AOBJSIZ) {
3561 return (IPADM_INVALID_ARG);
3562 }
3563
3564 /* Retrieve the address object information. */
3565 status = i_ipadm_get_addrobj(iph, ipaddr);
3566 if (status != IPADM_SUCCESS)
3567 return (status);
3568
3569 if (!(ipaddr->ipadm_flags & IPMGMT_ACTIVE))
3570 return (IPADM_OP_DISABLE_OBJ);
3571 if ((ipadm_flags & IPADM_OPT_PERSIST) &&
3572 !(ipaddr->ipadm_flags & IPMGMT_PERSIST))
3573 return (IPADM_TEMPORARY_OBJ);
3574 if (ipaddr->ipadm_atype == IPADM_ADDR_IPV6_ADDRCONF ||
3575 (ipaddr->ipadm_atype == IPADM_ADDR_DHCP &&
3576 (ipadm_flags & IPADM_OPT_PERSIST)))
3577 return (IPADM_NOTSUP);
3578
3579 i_ipadm_addrobj2lifname(ipaddr, lifname, sizeof (lifname));
3580 return (i_ipadm_get_flags(iph, lifname, ipaddr->ipadm_af, ifflags));
3581 }
3582
3583 /*
3584 * Marks the address in the address object `aobjname' up. This operation is
3585 * not supported for an address object of type IPADM_ADDR_IPV6_ADDRCONF.
3586 * For an address object of type IPADM_ADDR_DHCP, this operation can
3587 * only be temporary and no updates will be made to the persistent DB.
3588 */
3589 ipadm_status_t
3590 ipadm_up_addr(ipadm_handle_t iph, const char *aobjname, uint32_t ipadm_flags)
3591 {
3592 struct ipadm_addrobj_s ipaddr;
3593 ipadm_status_t status;
3594 uint64_t flags;
3595 char lifname[LIFNAMSIZ];
3596
3597 status = i_ipadm_updown_common(iph, aobjname, &ipaddr, ipadm_flags,
3598 &flags);
3599 if (status != IPADM_SUCCESS)
3786 uint64_t ifflags = 0;
3787 boolean_t p_exists;
3788 boolean_t af_exists, other_af_exists, a_exists;
3789
3790 if (ipaddr == NULL || flags == 0 || flags == IPADM_OPT_PERSIST ||
3791 (flags & ~(IPADM_COMMON_OPT_MASK|IPADM_OPT_UP|IPADM_OPT_V46))) {
3792 return (IPADM_INVALID_ARG);
3793 }
3794
3795 if (ipaddr->ipadm_af == AF_UNSPEC)
3796 return (IPADM_BAD_ADDR);
3797
3798 if (!legacy && ipaddr->ipadm_lifnum != 0)
3799 return (IPADM_INVALID_ARG);
3800
3801 if (legacy && ipaddr->ipadm_atype != IPADM_ADDR_STATIC)
3802 return (IPADM_NOTSUP);
3803
3804 ifname = ipaddr->ipadm_ifname;
3805
3806 if (i_ipadm_is_ipmp(iph, ifname) || i_ipadm_is_under_ipmp(iph, ifname))
3807 return (IPADM_NOTSUP);
3808
3809 af = ipaddr->ipadm_af;
3810 af_exists = ipadm_if_enabled(iph, ifname, af);
3811 /*
3812 * For legacy case, interfaces are not implicitly plumbed. We need to
3813 * check if the interface exists in the active configuration.
3814 */
3815 if (legacy && !af_exists)
3816 return (IPADM_ENXIO);
3817
3818 other_af = (af == AF_INET ? AF_INET6 : AF_INET);
3819 other_af_exists = ipadm_if_enabled(iph, ifname, other_af);
3820 /*
3821 * Check if one of the v4 or the v6 interfaces exists in the
3822 * active configuration. An interface is considered disabled only
3823 * if both v4 and v6 are not active.
3824 */
3825 a_exists = (af_exists || other_af_exists);
3826
3827 /* Check if interface exists in the persistent configuration. */
3828 status = i_ipadm_if_pexists(iph, ifname, af, &p_exists);
3829 if (status != IPADM_SUCCESS)
3830 return (status);
3831 if (!a_exists && p_exists)
3832 return (IPADM_OP_DISABLE_OBJ);
3833 if ((flags & IPADM_OPT_PERSIST) && a_exists && !p_exists) {
3834 /*
3835 * If address has to be created persistently,
3836 * and the interface does not exist in the persistent
3837 * store but in active config, fail.
3838 */
3839 return (IPADM_TEMPORARY_OBJ);
3840 }
3841 if (af_exists) {
3842 status = i_ipadm_get_flags(iph, ifname, af, &ifflags);
3843 if (status != IPADM_SUCCESS)
3844 return (status);
3845 }
3846
3847 /* Perform validation steps (4) and (5) */
3848 islo = i_ipadm_is_loopback(ifname);
3849 isvni = i_ipadm_is_vni(ifname);
3850 switch (ipaddr->ipadm_atype) {
3851 case IPADM_ADDR_STATIC:
3852 if ((islo || isvni) && ipaddr->ipadm_static_dname[0] != '\0')
3853 return (IPADM_INVALID_ARG);
3854 /* Check for a valid src address */
3855 if (!legacy && sockaddrunspec(
3856 (struct sockaddr *)&ipaddr->ipadm_static_addr))
3857 return (IPADM_BAD_ADDR);
3858 break;
3859 case IPADM_ADDR_DHCP:
3860 if (islo || (ifflags & IFF_VRRP))
|
1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2013 by Delphix. All rights reserved.
25 * Copyright 2016 Nexenta Systems, Inc.
26 * Copyright (c) 2016-2017, Chris Fraire <cfraire@me.com>.
27 */
28
29 /*
30 * This file contains functions for address management such as creating
31 * an address, deleting an address, enabling an address, disabling an
32 * address, bringing an address down or up, setting/getting properties
33 * on an address object and listing address information
34 * for all addresses in active as well as persistent configuration.
35 */
36 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <sys/param.h>
39 #include <netdb.h>
40 #include <inet/ip.h>
41 #include <string.h>
42 #include <strings.h>
43 #include <assert.h>
44 #include <sys/sockio.h>
45 #include <errno.h>
282 continue;
283 if (nvlist_exists(anvl, IPADM_NVP_IPV4ADDR) ||
284 nvlist_exists(anvl, IPADM_NVP_IPV6ADDR))
285 break;
286 }
287 if (nvp == NULL)
288 goto fail;
289 for (nvp = nvlist_next_nvpair(anvl, NULL);
290 nvp != NULL; nvp = nvlist_next_nvpair(anvl, nvp)) {
291 name = nvpair_name(nvp);
292 if (strcmp(name, IPADM_NVP_IPV4ADDR) == 0) {
293 af = AF_INET;
294 break;
295 } else if (strcmp(name, IPADM_NVP_IPV6ADDR) == 0) {
296 af = AF_INET6;
297 break;
298 }
299 }
300 assert(af != AF_UNSPEC);
301 if (nvpair_value_nvlist(nvp, &nvladdr) != 0 ||
302 nvlist_lookup_string(nvladdr, IPADM_NVP_IPADDRHNAME, &sname) != 0)
303 goto fail;
304
305 if (ipadm_set_addr(ipaddr, sname, af) != IPADM_SUCCESS)
306 goto fail;
307
308 nvlist_free(onvl);
309 return (IPADM_SUCCESS);
310 fail:
311 nvlist_free(onvl);
312 return (IPADM_NOTFOUND);
313 }
314
315 /*
316 * For the given `addrobj->ipadm_lifnum' and `addrobj->ipadm_af', this function
317 * fills in the address objname, the address type and the ipadm_flags.
318 */
319 ipadm_status_t
320 i_ipadm_get_lif2addrobj(ipadm_handle_t iph, ipadm_addrobj_t addrobj)
321 {
322 ipmgmt_aobjop_arg_t larg;
323 ipmgmt_aobjop_rval_t rval, *rvalp;
324 int err;
325
326 larg.ia_cmd = IPMGMT_CMD_LIF2ADDROBJ;
327 (void) strlcpy(larg.ia_ifname, addrobj->ipadm_ifname,
370 * daemon's aobjmap (active configuration). This API is called by in.ndpd to
371 * remove addrobjs when auto-configured prefixes or dhcpv6 addresses are
372 * removed.
373 */
374 ipadm_status_t
375 ipadm_delete_aobjname(ipadm_handle_t iph, const char *ifname, sa_family_t af,
376 const char *aobjname, ipadm_addr_type_t atype, int lnum)
377 {
378 struct ipadm_addrobj_s aobj;
379
380 i_ipadm_init_addr(&aobj, ifname, aobjname, atype);
381 aobj.ipadm_af = af;
382 aobj.ipadm_lifnum = lnum;
383 return (i_ipadm_delete_addrobj(iph, &aobj, IPADM_OPT_ACTIVE));
384 }
385
386 /*
387 * Gets all the addresses from active configuration and populates the
388 * address information in `addrinfo'.
389 */
390 ipadm_status_t
391 i_ipadm_active_addr_info(ipadm_handle_t iph, const char *ifname,
392 ipadm_addr_info_t **addrinfo, uint32_t ipadm_flags, int64_t lifc_flags)
393 {
394 ipadm_status_t status;
395 struct ifaddrs *ifap, *ifa;
396 ipadm_addr_info_t *curr, *prev = NULL;
397 struct ifaddrs *cifaddr;
398 struct lifreq lifr;
399 int sock;
400 uint64_t flags;
401 char cifname[LIFNAMSIZ];
402 struct sockaddr_in6 *sin6;
403 struct ipadm_addrobj_s ipaddr;
404 char *sep;
405 int lnum;
406
407 retry:
408 *addrinfo = NULL;
409
410 /* Get all the configured addresses */
1700 if (!(pdp->ipd_flags & IPADMPROP_MULVAL) &&
1701 (pflags & (IPADM_OPT_APPEND|IPADM_OPT_REMOVE))) {
1702 return (IPADM_INVALID_ARG);
1703 }
1704
1705 /*
1706 * For the given aobjname, get the addrobj it represents and
1707 * set the property value for that object.
1708 */
1709 i_ipadm_init_addr(&ipaddr, "", aobjname, IPADM_ADDR_NONE);
1710 if ((status = i_ipadm_get_addrobj(iph, &ipaddr)) != IPADM_SUCCESS)
1711 return (status);
1712
1713 if (!(ipaddr.ipadm_flags & IPMGMT_ACTIVE))
1714 return (IPADM_OP_DISABLE_OBJ);
1715
1716 /* Persistent operation not allowed on a temporary object. */
1717 if ((pflags & IPADM_OPT_PERSIST) &&
1718 !(ipaddr.ipadm_flags & IPMGMT_PERSIST))
1719 return (IPADM_TEMPORARY_OBJ);
1720 /*
1721 * Currently, setting an address property on an address object of type
1722 * IPADM_ADDR_IPV6_ADDRCONF is not supported. Supporting it involves
1723 * in.ndpd retrieving the address properties from ipmgmtd for given
1724 * address object and then setting them on auto-configured addresses,
1725 * whenever in.ndpd gets a new prefix. This will be supported in
1726 * future releases.
1727 */
1728 if (ipaddr.ipadm_atype == IPADM_ADDR_IPV6_ADDRCONF)
1729 return (IPADM_NOTSUP);
1730
1731 /*
1732 * Setting an address property on an address object that is
1733 * not present in active configuration is not supported.
1734 */
1735 if (!(ipaddr.ipadm_flags & IPMGMT_ACTIVE))
1736 return (IPADM_NOTSUP);
1737
1738 af = ipaddr.ipadm_af;
1739 if (reset) {
2395 char *aname, *cp;
2396 char ifname[IPADM_AOBJSIZ];
2397 ifspec_t ifsp;
2398
2399 if (ipaddr == NULL)
2400 return (IPADM_INVALID_ARG);
2401 *ipaddr = NULL;
2402
2403 if (aobjname == NULL || aobjname[0] == '\0')
2404 return (IPADM_INVALID_ARG);
2405
2406 if (strlcpy(ifname, aobjname, IPADM_AOBJSIZ) >= IPADM_AOBJSIZ)
2407 return (IPADM_INVALID_ARG);
2408
2409 if ((aname = strchr(ifname, '/')) != NULL)
2410 *aname++ = '\0';
2411
2412 /* Check if the interface name is valid. */
2413 if (!ifparse_ifspec(ifname, &ifsp))
2414 return (IPADM_INVALID_ARG);
2415 /* Check if the given addrobj name is valid. */
2416 if (aname != NULL && !i_ipadm_is_user_aobjname_valid(aname))
2417 return (IPADM_INVALID_ARG);
2418 if ((newaddr = calloc(1, sizeof (struct ipadm_addrobj_s))) == NULL)
2419 return (IPADM_NO_MEMORY);
2420
2421 /*
2422 * If the ifname has logical interface number, extract it and assign
2423 * it to `ipadm_lifnum'. Only applications with IPH_LEGACY set will do
2424 * this today. We will check for the validity later in
2425 * i_ipadm_validate_create_addr().
2426 */
2427 if (ifsp.ifsp_lunvalid) {
2428 newaddr->ipadm_lifnum = ifsp.ifsp_lun;
2429 cp = strchr(ifname, IPADM_LOGICAL_SEP);
2430 *cp = '\0';
2431 }
2432 (void) strlcpy(newaddr->ipadm_ifname, ifname,
2433 sizeof (newaddr->ipadm_ifname));
2434
2435 if (aname != NULL) {
2436 (void) snprintf(newaddr->ipadm_aobjname,
2437 sizeof (newaddr->ipadm_aobjname), "%s/%s", ifname, aname);
2579 iph->iph_sock6);
2580 if (ioctl(sock, SIOCLIFADDIF, (caddr_t)&lifr) < 0)
2581 return (ipadm_errno2status(errno));
2582 addr->ipadm_lifnum = i_ipadm_get_lnum(lifr.lifr_name);
2583 }
2584 return (IPADM_SUCCESS);
2585 }
2586
2587 /*
2588 * Reads all the address lines from the persistent DB into the nvlist `onvl',
2589 * when both `ifname' and `aobjname' are NULL. If an `ifname' is provided,
2590 * it returns all the addresses for the given interface `ifname'.
2591 * If an `aobjname' is specified, then the address line corresponding to
2592 * that name will be returned.
2593 */
2594 static ipadm_status_t
2595 i_ipadm_get_db_addr(ipadm_handle_t iph, const char *ifname,
2596 const char *aobjname, nvlist_t **onvl)
2597 {
2598 ipmgmt_getaddr_arg_t garg;
2599
2600 /* Populate the door_call argument structure */
2601 bzero(&garg, sizeof (garg));
2602 garg.ia_cmd = IPMGMT_CMD_GETADDR;
2603 if (aobjname != NULL)
2604 (void) strlcpy(garg.ia_aobjname, aobjname,
2605 sizeof (garg.ia_aobjname));
2606 if (ifname != NULL)
2607 (void) strlcpy(garg.ia_ifname, ifname, sizeof (garg.ia_ifname));
2608
2609 return (i_ipadm_call_ipmgmtd(iph, (void *) &garg, sizeof (garg), onvl));
2610 }
2611
2612 /*
2613 * Adds the IP address contained in the 'ipaddr' argument to the physical
2614 * interface represented by 'ifname' after doing the required validation.
2615 * If the interface does not exist, it is created before the address is
2616 * added.
2617 *
2618 * If IPH_LEGACY is set in iph_flags, flags has to be IPADM_OPT_ACTIVE
2619 * and a default addrobj name will be generated. Input `addr->ipadm_aobjname',
2620 * if provided, will be ignored and replaced with the newly generated name.
2621 * The interface name provided has to be a logical interface name that
2622 * already exists. No new logical interface will be added in this function.
2623 *
2624 * If IPADM_OPT_V46 is passed in the flags, then both IPv4 and IPv6 interfaces
2625 * are plumbed (if they haven't been already). Otherwise, just the interface
2626 * specified in `addr' is plumbed.
2627 */
2628 ipadm_status_t
2629 ipadm_create_addr(ipadm_handle_t iph, ipadm_addrobj_t addr, uint32_t flags)
2630 {
2631 ipadm_status_t status;
2632 sa_family_t af;
2633 sa_family_t daf;
2634 sa_family_t other_af;
2635 boolean_t created_af = B_FALSE;
2636 boolean_t created_other_af = B_FALSE;
2637 ipadm_addr_type_t type;
2638 char *ifname = addr->ipadm_ifname;
2639 boolean_t legacy = (iph->iph_flags & IPH_LEGACY);
2640 boolean_t aobjfound;
2641 boolean_t is_6to4;
2642 struct lifreq lifr;
2643 uint64_t ifflags;
2644 boolean_t is_boot = (iph->iph_flags & IPH_IPMGMTD);
2645 boolean_t is_ipmp;
2646 char gifname[LIFGRNAMSIZ];
2647
2648 /* check for solaris.network.interface.config authorization */
2649 if (!ipadm_check_auth())
2650 return (IPADM_EAUTH);
2651
2652 /* Validate the addrobj. This also fills in addr->ipadm_ifname. */
2653 status = i_ipadm_validate_create_addr(iph, addr, flags);
2654 if (status != IPADM_SUCCESS)
2655 return (status);
2656 /*
2657 * For Legacy case, check if an addrobj already exists for the
2658 * given logical interface name. If one does not exist,
2659 * a default name will be generated and added to the daemon's
2660 * aobjmap.
2661 */
2662 if (legacy) {
2663 struct ipadm_addrobj_s ipaddr;
2664
2665 ipaddr = *addr;
2666 status = i_ipadm_get_lif2addrobj(iph, &ipaddr);
2667 if (status == IPADM_SUCCESS) {
2668 aobjfound = B_TRUE;
2669 /*
2670 * With IPH_LEGACY, modifying an address that is not
2671 * a static address will return with an error.
2672 */
2673 if (ipaddr.ipadm_atype != IPADM_ADDR_STATIC)
2674 return (IPADM_NOTSUP);
2675 /*
2770 }
2771 }
2772
2773 /*
2774 * For 6to4 interfaces, kernel configures a default link-local
2775 * address. We need to replace it, if the caller has provided
2776 * an address that is different from the default link-local.
2777 */
2778 if (status == IPADM_SUCCESS && is_6to4) {
2779 bzero(&lifr, sizeof (lifr));
2780 (void) strlcpy(lifr.lifr_name, addr->ipadm_ifname,
2781 sizeof (lifr.lifr_name));
2782 if (ioctl(iph->iph_sock6, SIOCGLIFADDR, &lifr) < 0) {
2783 status = ipadm_errno2status(errno);
2784 goto fail;
2785 }
2786 if (sockaddrcmp(&lifr.lifr_addr, &addr->ipadm_static_addr))
2787 return (IPADM_SUCCESS);
2788 }
2789
2790 /*
2791 * If interface is an IPMP group member, move it out of the group before
2792 * performing any operations on it.
2793 */
2794 if ((is_ipmp = i_ipadm_is_under_ipmp(iph, addr->ipadm_ifname))) {
2795 (void) i_ipadm_get_groupname_active(iph, addr->ipadm_ifname,
2796 gifname, sizeof (gifname));
2797 (void) i_ipadm_set_groupname_active(iph, addr->ipadm_ifname,
2798 "");
2799 }
2800
2801 /* Create the address. */
2802 type = addr->ipadm_atype;
2803 switch (type) {
2804 case IPADM_ADDR_STATIC:
2805 status = i_ipadm_create_addr(iph, addr, flags);
2806 break;
2807 case IPADM_ADDR_DHCP:
2808 status = i_ipadm_create_dhcp(iph, addr, flags);
2809 break;
2810 case IPADM_ADDR_IPV6_ADDRCONF:
2811 status = i_ipadm_create_ipv6addrs(iph, addr, flags);
2812 break;
2813 default:
2814 status = IPADM_INVALID_ARG;
2815 break;
2816 }
2817
2818 /* Move the underlying IPMP interface back to the group */
2819 if (is_ipmp) {
2820 (void) i_ipadm_set_groupname_active(iph, addr->ipadm_ifname,
2821 gifname);
2822 }
2823
2824 /*
2825 * If address was not created successfully, unplumb the interface
2826 * if it was plumbed implicitly in this function and remove the
2827 * addrobj created by the ipmgmtd daemon as a placeholder.
2828 * If IPH_LEGACY is set, then remove the addrobj only if it was
2829 * created in this function.
2830 */
2831 fail:
2832 if (status != IPADM_DHCP_IPC_TIMEOUT &&
2833 status != IPADM_SUCCESS) {
2834 if (!legacy) {
2835 if (created_af || created_other_af) {
2836 if (created_af) {
2837 (void) i_ipadm_delete_if(iph, ifname,
2838 af, flags);
2839 }
2840 if (created_other_af) {
2841 (void) i_ipadm_delete_if(iph, ifname,
2842 other_af, flags);
2843 }
2876 af = ipaddr->ipadm_af;
2877 sock = (af == AF_INET ? iph->iph_sock : iph->iph_sock6);
2878
2879 /* If prefixlen was not provided, get default prefixlen */
2880 if (ipaddr->ipadm_static_prefixlen == 0) {
2881 /* prefixlen was not provided, get default prefixlen */
2882 status = i_ipadm_get_default_prefixlen(
2883 &ipaddr->ipadm_static_addr,
2884 &ipaddr->ipadm_static_prefixlen);
2885 if (status != IPADM_SUCCESS)
2886 return (status);
2887 default_prefixlen = B_TRUE;
2888 }
2889 (void) plen2mask(ipaddr->ipadm_static_prefixlen, af,
2890 (struct sockaddr *)mask);
2891
2892 /*
2893 * Create a new logical interface if needed; otherwise, just
2894 * use the 0th logical interface.
2895 */
2896 if (!(iph->iph_flags & IPH_LEGACY)) {
2897 status = i_ipadm_do_addif(iph, ipaddr);
2898 if (status != IPADM_SUCCESS)
2899 return (status);
2900 }
2901 i_ipadm_addrobj2lifname(ipaddr, lifr.lifr_name,
2902 sizeof (lifr.lifr_name));
2903 lifr.lifr_addr = *mask;
2904 if (ioctl(sock, SIOCSLIFNETMASK, (caddr_t)&lifr) < 0) {
2905 status = ipadm_errno2status(errno);
2906 goto ret;
2907 }
2908 lifr.lifr_addr = *addr;
2909 if (ioctl(sock, SIOCSLIFADDR, (caddr_t)&lifr) < 0) {
2910 status = ipadm_errno2status(errno);
2911 goto ret;
2912 }
2913 /* Set the destination address, if one is given. */
2914 if (daddr->ss_family != AF_UNSPEC) {
2915 lifr.lifr_addr = *daddr;
2916 if (ioctl(sock, SIOCSLIFDSTADDR, (caddr_t)&lifr) < 0) {
2917 status = ipadm_errno2status(errno);
2918 goto ret;
2919 }
2920 }
2921
2922 if (flags & IPADM_OPT_UP) {
2923 uint32_t iff_flags = IFF_UP;
2924
2925 /*
2926 * Set the NOFAILOVER flag only on underlying IPMP interface
2927 * and not the IPMP group interface itself.
2928 */
2929 if (i_ipadm_is_under_ipmp(iph, lifr.lifr_name) &&
2930 !i_ipadm_is_ipmp(iph, lifr.lifr_name))
2931 iff_flags |= IFF_NOFAILOVER;
2932 status = i_ipadm_set_flags(iph, lifr.lifr_name,
2933 af, iff_flags, 0);
2934
2935 /*
2936 * IPADM_DAD_FOUND is a soft-error for create-addr.
2937 * No need to tear down the address.
2938 */
2939 if (status == IPADM_DAD_FOUND)
2940 status = IPADM_SUCCESS;
2941 }
2942
2943 if (status == IPADM_SUCCESS && !is_boot) {
2944 /*
2945 * For IPH_LEGACY, we might be modifying the address on
2946 * an address object that already exists e.g. by doing
2947 * "ifconfig bge0:1 <addr>; ifconfig bge0:1 <newaddr>"
2948 * So, we need to store the object only if it does not
2949 * already exist in ipmgmtd.
2950 */
2951 if (legacy) {
2952 bzero(&legacy_addr, sizeof (legacy_addr));
2953 (void) strlcpy(legacy_addr.ipadm_aobjname,
2954 ipaddr->ipadm_aobjname,
2955 sizeof (legacy_addr.ipadm_aobjname));
2956 status = i_ipadm_get_addrobj(iph, &legacy_addr);
2957 if (status == IPADM_SUCCESS &&
2958 legacy_addr.ipadm_lifnum >= 0) {
2959 return (status);
2960 }
2961 }
2962 status = i_ipadm_addr_persist(iph, ipaddr, default_prefixlen,
2963 flags, NULL);
2964 }
2965 ret:
2966 if (status != IPADM_SUCCESS && !legacy)
2967 (void) i_ipadm_delete_addr(iph, ipaddr);
2968
2969 return (status);
2970 }
2971
2972 /*
2973 * Removes the address object identified by `aobjname' from both active and
2974 * persistent configuration. The address object will be removed from only
2975 * active configuration if IPH_LEGACY is set in `iph->iph_flags'.
2976 *
2977 * If the address type is IPADM_ADDR_STATIC or IPADM_ADDR_DHCP, the address
2978 * in the address object will be removed from the physical interface.
2979 * If the address type is IPADM_ADDR_DHCP, the flag IPADM_OPT_RELEASE specifies
2980 * whether the lease should be released. If IPADM_OPT_RELEASE is not
2981 * specified, the lease will be dropped. This option is not supported
2982 * for other address types.
2983 *
2984 * If the address type is IPADM_ADDR_IPV6_ADDRCONF, the link-local address and
2985 * all the autoconfigured addresses will be removed.
2986 * Finally, the address object is also removed from ipmgmtd's aobjmap and from
2987 * the persistent DB.
2988 */
3013 status = i_ipadm_get_addrobj(iph, &ipaddr);
3014 if (status != IPADM_SUCCESS)
3015 return (status);
3016
3017 if (release && ipaddr.ipadm_atype != IPADM_ADDR_DHCP)
3018 return (IPADM_NOTSUP);
3019 /*
3020 * If requested to delete just from active config but the address
3021 * is not in active config, return error.
3022 */
3023 if (!(ipaddr.ipadm_flags & IPMGMT_ACTIVE) &&
3024 (flags & IPADM_OPT_ACTIVE) && !(flags & IPADM_OPT_PERSIST)) {
3025 return (IPADM_NOTFOUND);
3026 }
3027
3028 /*
3029 * If address is present in active config, remove it from
3030 * kernel.
3031 */
3032 if (ipaddr.ipadm_flags & IPMGMT_ACTIVE) {
3033 boolean_t is_ipmp;
3034 char gifname[LIFGRNAMSIZ];
3035
3036 /*
3037 * If interface is an IPMP group member, move it out of the
3038 * group before performing any operations on it.
3039 */
3040 if ((is_ipmp = i_ipadm_is_under_ipmp(iph,
3041 ipaddr.ipadm_ifname))) {
3042 (void) i_ipadm_get_groupname_active(iph,
3043 ipaddr.ipadm_ifname, gifname, sizeof (gifname));
3044 (void) i_ipadm_set_groupname_active(iph,
3045 ipaddr.ipadm_ifname, "");
3046 }
3047
3048 switch (ipaddr.ipadm_atype) {
3049 case IPADM_ADDR_STATIC:
3050 status = i_ipadm_delete_addr(iph, &ipaddr);
3051 break;
3052 case IPADM_ADDR_DHCP:
3053 status = i_ipadm_delete_dhcp(iph, &ipaddr, release);
3054 break;
3055 case IPADM_ADDR_IPV6_ADDRCONF:
3056 status = i_ipadm_delete_ipv6addrs(iph, &ipaddr);
3057 break;
3058 default:
3059 /*
3060 * This is the case of address object name residing in
3061 * daemon's aobjmap (added by ADDROBJ_LOOKUPADD). Fall
3062 * through and delete that address object.
3063 */
3064 break;
3065 }
3066
3067 /* Move the underlying IPMP interface back to the group */
3068 if (is_ipmp) {
3069 (void) i_ipadm_set_groupname_active(iph,
3070 ipaddr.ipadm_ifname, gifname);
3071 }
3072
3073 /*
3074 * If the address was previously deleted from the active
3075 * config, we will get a IPADM_ENXIO from kernel.
3076 * We will still proceed and purge the address information
3077 * in the DB.
3078 */
3079 if (status == IPADM_ENXIO)
3080 status = IPADM_SUCCESS;
3081 else if (status != IPADM_SUCCESS)
3082 return (status);
3083 }
3084
3085 if (!(ipaddr.ipadm_flags & IPMGMT_PERSIST) &&
3086 (flags & IPADM_OPT_PERSIST)) {
3087 flags &= ~IPADM_OPT_PERSIST;
3088 }
3089 status = i_ipadm_delete_addrobj(iph, &ipaddr, flags);
3090 if (status == IPADM_NOTFOUND)
3091 return (status);
3092 return (IPADM_SUCCESS);
3574 ipadm_status_t status;
3575 char lifname[LIFNAMSIZ];
3576
3577 /* check for solaris.network.interface.config authorization */
3578 if (!ipadm_check_auth())
3579 return (IPADM_EAUTH);
3580
3581 /* validate input */
3582 if (aobjname == NULL || strlcpy(ipaddr->ipadm_aobjname, aobjname,
3583 IPADM_AOBJSIZ) >= IPADM_AOBJSIZ) {
3584 return (IPADM_INVALID_ARG);
3585 }
3586
3587 /* Retrieve the address object information. */
3588 status = i_ipadm_get_addrobj(iph, ipaddr);
3589 if (status != IPADM_SUCCESS)
3590 return (status);
3591
3592 if (!(ipaddr->ipadm_flags & IPMGMT_ACTIVE))
3593 return (IPADM_OP_DISABLE_OBJ);
3594
3595 if ((ipadm_flags & IPADM_OPT_PERSIST) &&
3596 !(ipaddr->ipadm_flags & IPMGMT_PERSIST))
3597 return (IPADM_TEMPORARY_OBJ);
3598
3599 if (ipaddr->ipadm_atype == IPADM_ADDR_IPV6_ADDRCONF ||
3600 (ipaddr->ipadm_atype == IPADM_ADDR_DHCP &&
3601 (ipadm_flags & IPADM_OPT_PERSIST)))
3602 return (IPADM_NOTSUP);
3603
3604 i_ipadm_addrobj2lifname(ipaddr, lifname, sizeof (lifname));
3605
3606 return (i_ipadm_get_flags(iph, lifname, ipaddr->ipadm_af, ifflags));
3607 }
3608
3609 /*
3610 * Marks the address in the address object `aobjname' up. This operation is
3611 * not supported for an address object of type IPADM_ADDR_IPV6_ADDRCONF.
3612 * For an address object of type IPADM_ADDR_DHCP, this operation can
3613 * only be temporary and no updates will be made to the persistent DB.
3614 */
3615 ipadm_status_t
3616 ipadm_up_addr(ipadm_handle_t iph, const char *aobjname, uint32_t ipadm_flags)
3617 {
3618 struct ipadm_addrobj_s ipaddr;
3619 ipadm_status_t status;
3620 uint64_t flags;
3621 char lifname[LIFNAMSIZ];
3622
3623 status = i_ipadm_updown_common(iph, aobjname, &ipaddr, ipadm_flags,
3624 &flags);
3625 if (status != IPADM_SUCCESS)
3812 uint64_t ifflags = 0;
3813 boolean_t p_exists;
3814 boolean_t af_exists, other_af_exists, a_exists;
3815
3816 if (ipaddr == NULL || flags == 0 || flags == IPADM_OPT_PERSIST ||
3817 (flags & ~(IPADM_COMMON_OPT_MASK|IPADM_OPT_UP|IPADM_OPT_V46))) {
3818 return (IPADM_INVALID_ARG);
3819 }
3820
3821 if (ipaddr->ipadm_af == AF_UNSPEC)
3822 return (IPADM_BAD_ADDR);
3823
3824 if (!legacy && ipaddr->ipadm_lifnum != 0)
3825 return (IPADM_INVALID_ARG);
3826
3827 if (legacy && ipaddr->ipadm_atype != IPADM_ADDR_STATIC)
3828 return (IPADM_NOTSUP);
3829
3830 ifname = ipaddr->ipadm_ifname;
3831
3832 /*
3833 * Do not go further when we are under ipmp.
3834 * The interface is plumbed up and we are going to add
3835 * NOFAILOVER address to make in.mpathd happy.
3836 */
3837 if (i_ipadm_is_under_ipmp(iph, ifname))
3838 return (IPADM_SUCCESS);
3839
3840 af = ipaddr->ipadm_af;
3841 af_exists = ipadm_if_enabled(iph, ifname, af);
3842 /*
3843 * For legacy case, interfaces are not implicitly plumbed. We need to
3844 * check if the interface exists in the active configuration.
3845 */
3846 if (legacy && !af_exists)
3847 return (IPADM_ENXIO);
3848
3849 other_af = (af == AF_INET ? AF_INET6 : AF_INET);
3850 other_af_exists = ipadm_if_enabled(iph, ifname, other_af);
3851 /*
3852 * Check if one of the v4 or the v6 interfaces exists in the
3853 * active configuration. An interface is considered disabled only
3854 * if both v4 and v6 are not active.
3855 */
3856 a_exists = (af_exists || other_af_exists);
3857
3858 /* Check if interface exists in the persistent configuration. */
3859 status = i_ipadm_if_pexists(iph, ifname, af, &p_exists);
3860 if (status != IPADM_SUCCESS)
3861 return (status);
3862
3863 if (!a_exists && p_exists)
3864 return (IPADM_OP_DISABLE_OBJ);
3865
3866 if (af_exists) {
3867 status = i_ipadm_get_flags(iph, ifname, af, &ifflags);
3868 if (status != IPADM_SUCCESS)
3869 return (status);
3870 }
3871
3872 /* Perform validation steps (4) and (5) */
3873 islo = i_ipadm_is_loopback(ifname);
3874 isvni = i_ipadm_is_vni(ifname);
3875 switch (ipaddr->ipadm_atype) {
3876 case IPADM_ADDR_STATIC:
3877 if ((islo || isvni) && ipaddr->ipadm_static_dname[0] != '\0')
3878 return (IPADM_INVALID_ARG);
3879 /* Check for a valid src address */
3880 if (!legacy && sockaddrunspec(
3881 (struct sockaddr *)&ipaddr->ipadm_static_addr))
3882 return (IPADM_BAD_ADDR);
3883 break;
3884 case IPADM_ADDR_DHCP:
3885 if (islo || (ifflags & IFF_VRRP))
|