Print this page
NEX-9305 libipadm`ipadm_enable_addr() leaks addrnvl
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-8955 creating addresses on underlying IPMP links is broken
NEX-9102 deleting addresses from underlying IPMP interfaces leaves them down
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-6864 cannot create functional link-based IPMP interface
NEX-7793 unable to add/remove interface with existing address to/from IPMP group
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-3908 IPMP group can have only one IP address
Reviewed by: Gordon Ross <gwr@nexenta.com>
OS-161: Integrate IPMP changes (lint)
OS-161: Integrate IPMP changes

*** 16,28 **** --- 16,30 ---- * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ + /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright 2016 Nexenta Systems, Inc. * Copyright (c) 2016-2017, Chris Fraire <cfraire@me.com>. */ /* * This file contains functions for address management such as creating
*** 295,308 **** break; } } assert(af != AF_UNSPEC); if (nvpair_value_nvlist(nvp, &nvladdr) != 0 || ! nvlist_lookup_string(nvladdr, IPADM_NVP_IPADDRHNAME, &sname) != 0 || ! ipadm_set_addr(ipaddr, sname, af) != IPADM_SUCCESS) { goto fail; ! } nvlist_free(onvl); return (IPADM_SUCCESS); fail: nvlist_free(onvl); return (IPADM_NOTFOUND); --- 297,312 ---- break; } } assert(af != AF_UNSPEC); if (nvpair_value_nvlist(nvp, &nvladdr) != 0 || ! nvlist_lookup_string(nvladdr, IPADM_NVP_IPADDRHNAME, &sname) != 0) goto fail; ! ! if (ipadm_set_addr(ipaddr, sname, af) != IPADM_SUCCESS) ! goto fail; ! nvlist_free(onvl); return (IPADM_SUCCESS); fail: nvlist_free(onvl); return (IPADM_NOTFOUND);
*** 381,391 **** /* * Gets all the addresses from active configuration and populates the * address information in `addrinfo'. */ ! static ipadm_status_t i_ipadm_active_addr_info(ipadm_handle_t iph, const char *ifname, ipadm_addr_info_t **addrinfo, uint32_t ipadm_flags, int64_t lifc_flags) { ipadm_status_t status; struct ifaddrs *ifap, *ifa; --- 385,395 ---- /* * Gets all the addresses from active configuration and populates the * address information in `addrinfo'. */ ! ipadm_status_t i_ipadm_active_addr_info(ipadm_handle_t iph, const char *ifname, ipadm_addr_info_t **addrinfo, uint32_t ipadm_flags, int64_t lifc_flags) { ipadm_status_t status; struct ifaddrs *ifap, *ifa;
*** 1711,1721 **** /* Persistent operation not allowed on a temporary object. */ if ((pflags & IPADM_OPT_PERSIST) && !(ipaddr.ipadm_flags & IPMGMT_PERSIST)) return (IPADM_TEMPORARY_OBJ); - /* * Currently, setting an address property on an address object of type * IPADM_ADDR_IPV6_ADDRCONF is not supported. Supporting it involves * in.ndpd retrieving the address properties from ipmgmtd for given * address object and then setting them on auto-configured addresses, --- 1715,1724 ----
*** 2407,2421 **** *aname++ = '\0'; /* Check if the interface name is valid. */ if (!ifparse_ifspec(ifname, &ifsp)) return (IPADM_INVALID_ARG); - /* Check if the given addrobj name is valid. */ if (aname != NULL && !i_ipadm_is_user_aobjname_valid(aname)) return (IPADM_INVALID_ARG); - if ((newaddr = calloc(1, sizeof (struct ipadm_addrobj_s))) == NULL) return (IPADM_NO_MEMORY); /* * If the ifname has logical interface number, extract it and assign --- 2410,2422 ----
*** 2593,2606 **** static ipadm_status_t i_ipadm_get_db_addr(ipadm_handle_t iph, const char *ifname, const char *aobjname, nvlist_t **onvl) { ipmgmt_getaddr_arg_t garg; - ipmgmt_get_rval_t *rvalp; - int err; - size_t nvlsize; - char *nvlbuf; /* Populate the door_call argument structure */ bzero(&garg, sizeof (garg)); garg.ia_cmd = IPMGMT_CMD_GETADDR; if (aobjname != NULL) --- 2594,2603 ----
*** 2607,2626 **** (void) strlcpy(garg.ia_aobjname, aobjname, sizeof (garg.ia_aobjname)); if (ifname != NULL) (void) strlcpy(garg.ia_ifname, ifname, sizeof (garg.ia_ifname)); ! rvalp = malloc(sizeof (ipmgmt_get_rval_t)); ! err = ipadm_door_call(iph, &garg, sizeof (garg), (void **)&rvalp, ! sizeof (*rvalp), B_TRUE); ! if (err == 0) { ! nvlsize = rvalp->ir_nvlsize; ! nvlbuf = (char *)rvalp + sizeof (ipmgmt_get_rval_t); ! err = nvlist_unpack(nvlbuf, nvlsize, onvl, NV_ENCODE_NATIVE); ! } ! free(rvalp); ! return (ipadm_errno2status(err)); } /* * Adds the IP address contained in the 'ipaddr' argument to the physical * interface represented by 'ifname' after doing the required validation. --- 2604,2614 ---- (void) strlcpy(garg.ia_aobjname, aobjname, sizeof (garg.ia_aobjname)); if (ifname != NULL) (void) strlcpy(garg.ia_ifname, ifname, sizeof (garg.ia_ifname)); ! return (i_ipadm_call_ipmgmtd(iph, (void *) &garg, sizeof (garg), onvl)); } /* * Adds the IP address contained in the 'ipaddr' argument to the physical * interface represented by 'ifname' after doing the required validation.
*** 2652,2671 **** boolean_t aobjfound; boolean_t is_6to4; struct lifreq lifr; uint64_t ifflags; boolean_t is_boot = (iph->iph_flags & IPH_IPMGMTD); /* check for solaris.network.interface.config authorization */ if (!ipadm_check_auth()) return (IPADM_EAUTH); /* Validate the addrobj. This also fills in addr->ipadm_ifname. */ status = i_ipadm_validate_create_addr(iph, addr, flags); if (status != IPADM_SUCCESS) return (status); - /* * For Legacy case, check if an addrobj already exists for the * given logical interface name. If one does not exist, * a default name will be generated and added to the daemon's * aobjmap. --- 2640,2660 ---- boolean_t aobjfound; boolean_t is_6to4; struct lifreq lifr; uint64_t ifflags; boolean_t is_boot = (iph->iph_flags & IPH_IPMGMTD); + boolean_t is_ipmp; + char gifname[LIFGRNAMSIZ]; /* check for solaris.network.interface.config authorization */ if (!ipadm_check_auth()) return (IPADM_EAUTH); /* Validate the addrobj. This also fills in addr->ipadm_ifname. */ status = i_ipadm_validate_create_addr(iph, addr, flags); if (status != IPADM_SUCCESS) return (status); /* * For Legacy case, check if an addrobj already exists for the * given logical interface name. If one does not exist, * a default name will be generated and added to the daemon's * aobjmap.
*** 2796,2805 **** --- 2785,2805 ---- } if (sockaddrcmp(&lifr.lifr_addr, &addr->ipadm_static_addr)) return (IPADM_SUCCESS); } + /* + * If interface is an IPMP group member, move it out of the group before + * performing any operations on it. + */ + if ((is_ipmp = i_ipadm_is_under_ipmp(iph, addr->ipadm_ifname))) { + (void) i_ipadm_get_groupname_active(iph, addr->ipadm_ifname, + gifname, sizeof (gifname)); + (void) i_ipadm_set_groupname_active(iph, addr->ipadm_ifname, + ""); + } + /* Create the address. */ type = addr->ipadm_atype; switch (type) { case IPADM_ADDR_STATIC: status = i_ipadm_create_addr(iph, addr, flags);
*** 2813,2822 **** --- 2813,2828 ---- default: status = IPADM_INVALID_ARG; break; } + /* Move the underlying IPMP interface back to the group */ + if (is_ipmp) { + (void) i_ipadm_set_groupname_active(iph, addr->ipadm_ifname, + gifname); + } + /* * If address was not created successfully, unplumb the interface * if it was plumbed implicitly in this function and remove the * addrobj created by the ipmgmtd daemon as a placeholder. * If IPH_LEGACY is set, then remove the addrobj only if it was
*** 2885,2914 **** /* * Create a new logical interface if needed; otherwise, just * use the 0th logical interface. */ - retry: if (!(iph->iph_flags & IPH_LEGACY)) { status = i_ipadm_do_addif(iph, ipaddr); if (status != IPADM_SUCCESS) return (status); - /* - * We don't have to set the lifnum for IPH_INIT case, because - * there is no placeholder created for the address object in - * this case. For IPH_LEGACY, we don't do this because the - * lifnum is given by the caller and it will be set in the - * end while we call the i_ipadm_addr_persist(). - */ - if (!(iph->iph_flags & IPH_INIT)) { - status = i_ipadm_setlifnum_addrobj(iph, ipaddr); - if (status == IPADM_ADDROBJ_EXISTS) - goto retry; - if (status != IPADM_SUCCESS) - return (status); } - } i_ipadm_addrobj2lifname(ipaddr, lifr.lifr_name, sizeof (lifr.lifr_name)); lifr.lifr_addr = *mask; if (ioctl(sock, SIOCSLIFNETMASK, (caddr_t)&lifr) < 0) { status = ipadm_errno2status(errno); --- 2891,2905 ----
*** 2927,2939 **** goto ret; } } if (flags & IPADM_OPT_UP) { ! status = i_ipadm_set_flags(iph, lifr.lifr_name, af, IFF_UP, 0); /* * IPADM_DAD_FOUND is a soft-error for create-addr. * No need to tear down the address. */ if (status == IPADM_DAD_FOUND) status = IPADM_SUCCESS; --- 2918,2940 ---- goto ret; } } if (flags & IPADM_OPT_UP) { ! uint32_t iff_flags = IFF_UP; /* + * Set the NOFAILOVER flag only on underlying IPMP interface + * and not the IPMP group interface itself. + */ + if (i_ipadm_is_under_ipmp(iph, lifr.lifr_name) && + !i_ipadm_is_ipmp(iph, lifr.lifr_name)) + iff_flags |= IFF_NOFAILOVER; + status = i_ipadm_set_flags(iph, lifr.lifr_name, + af, iff_flags, 0); + + /* * IPADM_DAD_FOUND is a soft-error for create-addr. * No need to tear down the address. */ if (status == IPADM_DAD_FOUND) status = IPADM_SUCCESS;
*** 2962,2971 **** --- 2963,2973 ---- flags, NULL); } ret: if (status != IPADM_SUCCESS && !legacy) (void) i_ipadm_delete_addr(iph, ipaddr); + return (status); } /* * Removes the address object identified by `aobjname' from both active and
*** 3026,3035 **** --- 3028,3052 ---- /* * If address is present in active config, remove it from * kernel. */ if (ipaddr.ipadm_flags & IPMGMT_ACTIVE) { + boolean_t is_ipmp; + char gifname[LIFGRNAMSIZ]; + + /* + * If interface is an IPMP group member, move it out of the + * group before performing any operations on it. + */ + if ((is_ipmp = i_ipadm_is_under_ipmp(iph, + ipaddr.ipadm_ifname))) { + (void) i_ipadm_get_groupname_active(iph, + ipaddr.ipadm_ifname, gifname, sizeof (gifname)); + (void) i_ipadm_set_groupname_active(iph, + ipaddr.ipadm_ifname, ""); + } + switch (ipaddr.ipadm_atype) { case IPADM_ADDR_STATIC: status = i_ipadm_delete_addr(iph, &ipaddr); break; case IPADM_ADDR_DHCP:
*** 3045,3054 **** --- 3062,3077 ---- * through and delete that address object. */ break; } + /* Move the underlying IPMP interface back to the group */ + if (is_ipmp) { + (void) i_ipadm_set_groupname_active(iph, + ipaddr.ipadm_ifname, gifname); + } + /* * If the address was previously deleted from the active * config, we will get a IPADM_ENXIO from kernel. * We will still proceed and purge the address information * in the DB.
*** 3566,3584 **** --- 3589,3610 ---- if (status != IPADM_SUCCESS) return (status); if (!(ipaddr->ipadm_flags & IPMGMT_ACTIVE)) return (IPADM_OP_DISABLE_OBJ); + if ((ipadm_flags & IPADM_OPT_PERSIST) && !(ipaddr->ipadm_flags & IPMGMT_PERSIST)) return (IPADM_TEMPORARY_OBJ); + if (ipaddr->ipadm_atype == IPADM_ADDR_IPV6_ADDRCONF || (ipaddr->ipadm_atype == IPADM_ADDR_DHCP && (ipadm_flags & IPADM_OPT_PERSIST))) return (IPADM_NOTSUP); i_ipadm_addrobj2lifname(ipaddr, lifname, sizeof (lifname)); + return (i_ipadm_get_flags(iph, lifname, ipaddr->ipadm_af, ifflags)); } /* * Marks the address in the address object `aobjname' up. This operation is
*** 3801,3812 **** if (legacy && ipaddr->ipadm_atype != IPADM_ADDR_STATIC) return (IPADM_NOTSUP); ifname = ipaddr->ipadm_ifname; ! if (i_ipadm_is_ipmp(iph, ifname) || i_ipadm_is_under_ipmp(iph, ifname)) ! return (IPADM_NOTSUP); af = ipaddr->ipadm_af; af_exists = ipadm_if_enabled(iph, ifname, af); /* * For legacy case, interfaces are not implicitly plumbed. We need to --- 3827,3843 ---- if (legacy && ipaddr->ipadm_atype != IPADM_ADDR_STATIC) return (IPADM_NOTSUP); ifname = ipaddr->ipadm_ifname; ! /* ! * Do not go further when we are under ipmp. ! * The interface is plumbed up and we are going to add ! * NOFAILOVER address to make in.mpathd happy. ! */ ! if (i_ipadm_is_under_ipmp(iph, ifname)) ! return (IPADM_SUCCESS); af = ipaddr->ipadm_af; af_exists = ipadm_if_enabled(iph, ifname, af); /* * For legacy case, interfaces are not implicitly plumbed. We need to
*** 3826,3845 **** /* Check if interface exists in the persistent configuration. */ status = i_ipadm_if_pexists(iph, ifname, af, &p_exists); if (status != IPADM_SUCCESS) return (status); if (!a_exists && p_exists) return (IPADM_OP_DISABLE_OBJ); ! if ((flags & IPADM_OPT_PERSIST) && a_exists && !p_exists) { ! /* ! * If address has to be created persistently, ! * and the interface does not exist in the persistent ! * store but in active config, fail. ! */ ! return (IPADM_TEMPORARY_OBJ); ! } if (af_exists) { status = i_ipadm_get_flags(iph, ifname, af, &ifflags); if (status != IPADM_SUCCESS) return (status); } --- 3857,3870 ---- /* Check if interface exists in the persistent configuration. */ status = i_ipadm_if_pexists(iph, ifname, af, &p_exists); if (status != IPADM_SUCCESS) return (status); + if (!a_exists && p_exists) return (IPADM_OP_DISABLE_OBJ); ! if (af_exists) { status = i_ipadm_get_flags(iph, ifname, af, &ifflags); if (status != IPADM_SUCCESS) return (status); }