diff options
Diffstat (limited to 'usr/src/cmd')
| -rw-r--r-- | usr/src/cmd/Makefile.check | 3 | ||||
| -rw-r--r-- | usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile | 8 | ||||
| -rw-r--r-- | usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c | 290 | ||||
| -rw-r--r-- | usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h | 25 | ||||
| -rw-r--r-- | usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c | 27 | ||||
| -rw-r--r-- | usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c | 451 | ||||
| -rw-r--r-- | usr/src/cmd/cmd-inet/usr.lib/in.mpathd/Makefile | 17 | ||||
| -rw-r--r-- | usr/src/cmd/cmd-inet/usr.lib/in.mpathd/net-ipmp | 31 | ||||
| -rw-r--r-- | usr/src/cmd/cmd-inet/usr.lib/in.mpathd/network-ipmp.xml | 78 | ||||
| -rw-r--r-- | usr/src/cmd/cmd-inet/usr.sbin/ipadm/Makefile | 5 | ||||
| -rw-r--r-- | usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c | 333 | ||||
| -rw-r--r-- | usr/src/cmd/rcm_daemon/common/ip_rcm.c | 8 | ||||
| -rw-r--r-- | usr/src/cmd/svc/milestone/net-init | 16 | ||||
| -rw-r--r-- | usr/src/cmd/svc/milestone/net-physical | 42 | 
14 files changed, 1037 insertions, 297 deletions
| diff --git a/usr/src/cmd/Makefile.check b/usr/src/cmd/Makefile.check index a5e450b5ea..7d2fbe66c0 100644 --- a/usr/src/cmd/Makefile.check +++ b/usr/src/cmd/Makefile.check @@ -22,8 +22,8 @@  #  # Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.  # Copyright 2014 Garrett D'Amore <garrett@damore.org> -# Copyright 2017 Nexenta Systems, Inc.  # Copyright 2019 Peter Tribble +# Copyright 2021 Tintri by DDN, Inc. All rights reserved.  #  include ../Makefile.master @@ -86,6 +86,7 @@ MANIFEST_SUBDIRS=			\  	cmd-inet/usr.lib/in.daytimed	\  	cmd-inet/usr.lib/in.discardd	\  	cmd-inet/usr.lib/in.echod	\ +	cmd-inet/usr.lib/in.mpathd	\  	cmd-inet/usr.lib/in.ndpd	\  	cmd-inet/usr.lib/in.ripngd	\  	cmd-inet/usr.lib/in.timed	\ diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile b/usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile index f9ae4eacdc..1c32ce2ff1 100644 --- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile @@ -18,7 +18,10 @@  #  # CDDL HEADER END  # + +#  # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2021 Tintri by DDN, Inc. All rights reserved.  #  # Needed for ROOTFS_LIBDIR definition @@ -38,9 +41,6 @@ ROOTCFGDIR=		$(ROOTETC)/ipadm  ROOTCFGFILES=		$(CFGFILES:%=$(ROOTCFGDIR)/%)  ROOTMANIFESTDIR=	$(ROOTSVCNETWORK) -CERRWARN += -_gcc=-Wno-switch -CERRWARN += $(CNOWARN_UNINIT) -  $(ROOTCFGFILES)	:= OWNER= ipadm  $(ROOTCFGFILES)	:= GROUP= sys  $(ROOTCFGFILES)	:= FILEMODE= 644 @@ -85,4 +85,4 @@ $(ROOTCFGDIR):  $(ROOTCFGDIR)/%: $(ROOTCFGDIR) %  	$(INS.file) -include 	../../../Makefile.targ +include	../../../Makefile.targ diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c index 92e3f73f55..b446b2ffa4 100644 --- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c @@ -43,6 +43,9 @@  #include <libnvpair.h>  #include "ipmgmt_impl.h" + +static void ipmgmt_common_handler(char *, char *, db_wfunc_t *); +  /* Handler declaration for each door command */  typedef void ipmgmt_door_handler_t(void *argp); @@ -56,7 +59,8 @@ static ipmgmt_door_handler_t	ipmgmt_getaddr_handler,  				ipmgmt_resetif_handler,  				ipmgmt_resetprop_handler,  				ipmgmt_setaddr_handler, -				ipmgmt_setprop_handler; +				ipmgmt_setprop_handler, +				ipmgmt_ipmp_update_handler;  typedef struct ipmgmt_door_info_s {  	uint_t			idi_cmd; @@ -81,6 +85,7 @@ static ipmgmt_door_info_t i_ipmgmt_door_info_tbl[] = {  	{ IPMGMT_CMD_ADDROBJ_ADD,	B_TRUE,  ipmgmt_aobjop_handler },  	{ IPMGMT_CMD_AOBJNAME2ADDROBJ,	B_FALSE, ipmgmt_aobjop_handler },  	{ IPMGMT_CMD_LIF2ADDROBJ,	B_FALSE, ipmgmt_aobjop_handler }, +	{ IPMGMT_CMD_IPMP_UPDATE,	B_FALSE, ipmgmt_ipmp_update_handler},  	{ 0, 0, NULL },  }; @@ -593,6 +598,10 @@ ipmgmt_resetif_handler(void *argp)  	cbarg.cb_family = rargp->ia_family;  	cbarg.cb_ifname = rargp->ia_ifname; + +	cbarg.cb_ipv4exists = B_TRUE; +	cbarg.cb_ipv6exists = B_TRUE; +  	if (flags & IPMGMT_PERSIST)  		err = ipmgmt_db_walk(ipmgmt_db_resetif, &cbarg,  		    IPADM_DB_DELETE); @@ -654,59 +663,10 @@ ipmgmt_resetaddr_handler(void *argp)  static void  ipmgmt_getaddr_handler(void *argp)  { -	size_t			buflen, onvlsize; -	char			*buf, *onvlbuf; -	ipmgmt_getaddr_arg_t	*gargp = argp; -	ipmgmt_getaddr_cbarg_t	cbarg; -	ipmgmt_get_rval_t	rval, *rvalp = &rval; -	int			err = 0; - -	cbarg.cb_ifname = gargp->ia_ifname; -	cbarg.cb_aobjname = gargp->ia_aobjname; -	cbarg.cb_ocnt = 0; -	if (nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0) != 0) -		goto fail; -	err = ipmgmt_db_walk(ipmgmt_db_getaddr, &cbarg, IPADM_DB_READ); -	if (err == ENOENT && cbarg.cb_ocnt > 0) { -		/* -		 * If there is atleast one entry in the nvlist, -		 * do not return error. -		 */ -		err = 0; -	} -	if (err != 0) -		goto fail; - -	if ((err = nvlist_size(cbarg.cb_onvl, &onvlsize, -	    NV_ENCODE_NATIVE)) != 0) { -		goto fail; -	} - -	if (onvlsize > (UINT32_MAX - sizeof (ipmgmt_get_rval_t))) -		goto fail; - -	buflen = onvlsize + sizeof (ipmgmt_get_rval_t); -	/* -	 * We cannot use malloc() here because door_return never returns, and -	 * memory allocated by malloc() would get leaked. Use alloca() instead. -	 */ -	buf = alloca(buflen); -	onvlbuf = buf + sizeof (ipmgmt_get_rval_t); -	if ((err = nvlist_pack(cbarg.cb_onvl, &onvlbuf, &onvlsize, -	    NV_ENCODE_NATIVE, 0)) != 0) { -		goto fail; -	} -	nvlist_free(cbarg.cb_onvl); -	rvalp = (ipmgmt_get_rval_t *)(void *)buf; -	rvalp->ir_err = 0; -	rvalp->ir_nvlsize = onvlsize; +	ipmgmt_getaddr_arg_t    *gargp = argp; -	(void) door_return(buf, buflen, NULL, 0); -	return; -fail: -	nvlist_free(cbarg.cb_onvl); -	rvalp->ir_err = err; -	(void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0); +	ipmgmt_common_handler(gargp->ia_ifname, gargp->ia_aobjname, +	    ipmgmt_db_getaddr);  }  /* @@ -727,65 +687,20 @@ ipmgmt_resetprop_handler(void *argp)  }  /* - * Handles the door command IPMGMT_CMD_GETIF. It retrieves the name of all the - * persisted interfaces and the IP protocols (IPv4 or IPv6) they support. + * Handles the door command IPMGMT_CMD_GETIF. It retrieves the names of all + * persisted interfaces and the IP protocol families (IPv4 or IPv6) they + * support. Returns the info as a nvlist using door_return() from + * ipmgmt_common_handler().   */  static void  ipmgmt_getif_handler(void *argp)  { -	ipmgmt_getif_arg_t	*getif = argp; -	ipmgmt_getif_rval_t	*rvalp; -	ipmgmt_retval_t		rval; -	ipmgmt_getif_cbarg_t	cbarg; -	ipadm_if_info_list_t	*ifl, *curifl; -	ipadm_if_info_t		*ifp, *rifp; -	int			i, err = 0, count = 0; -	size_t			rbufsize; +	ipmgmt_getif_arg_t  *getif = argp;  	assert(getif->ia_cmd == IPMGMT_CMD_GETIF); -	bzero(&cbarg, sizeof (cbarg)); -	cbarg.cb_ifname = getif->ia_ifname; -	err = ipmgmt_db_walk(ipmgmt_db_getif, &cbarg, IPADM_DB_READ); -	if (err == ENOENT && cbarg.cb_ifinfo) { -		/* -		 * If there is atleast one entry in the nvlist, -		 * do not return error. -		 */ -		err = 0; -	} -	if (err != 0) { -		rval.ir_err = err; -		(void) door_return((char *)&rval, sizeof (rval), NULL, 0); -		return; -	} - -	/* allocate sufficient buffer to return the interface info */ -	for (ifl = cbarg.cb_ifinfo; ifl != NULL; ifl = ifl->ifil_next) -		++count; -	rbufsize = sizeof (*rvalp) + count * sizeof (*ifp); -	rvalp = alloca(rbufsize); -	bzero(rvalp, rbufsize); - -	rvalp->ir_ifcnt = count; -	rifp = rvalp->ir_ifinfo; -	ifl = cbarg.cb_ifinfo; - -	/* -	 * copy the interface info to buffer allocated on stack. The reason -	 * we do this is to avoid memory leak, as door_return() would never -	 * return -	 */ -	for (i = 0; i < count; i++) { -		ifp = &ifl->ifil_ifi; -		rifp = rvalp->ir_ifinfo + i; -		(void) bcopy(ifp, rifp, sizeof (*rifp)); -		curifl = ifl->ifil_next; -		free(ifl); -		ifl = curifl; -	} -	rvalp->ir_err = err; -	(void) door_return((char *)rvalp, rbufsize, NULL, 0); +	ipmgmt_common_handler(getif->ia_ifname, NULL, +	    ipmgmt_db_getif);  }  /* @@ -819,7 +734,7 @@ ipmgmt_initif_handler(void *argp)  	err = ipmgmt_db_walk(ipmgmt_db_initif, &cbarg, IPADM_DB_READ);  	if (err == ENOENT && cbarg.cb_ocnt > 0) {  		/* -		 * If there is atleast one entry in the nvlist, +		 * If there is at least one entry in the nvlist,  		 * do not return error.  		 */  		err = 0; @@ -863,10 +778,10 @@ int  ipmgmt_persist_if(ipmgmt_if_arg_t *sargp)  {  	ipadm_dbwrite_cbarg_t	cb; -	uint32_t		flags = sargp->ia_flags; -	nvlist_t		*nvl = NULL; -	int			err = 0; -	char			strval[IPMGMT_STRSIZE]; +	uint32_t	flags = sargp->ia_flags; +	nvlist_t	*nvl = NULL; +	char	strval[IPMGMT_STRSIZE]; +	int	err = 0;  	if (!(flags & IPMGMT_PERSIST) || sargp->ia_family == AF_UNSPEC ||  	    sargp->ia_ifname[0] == '\0') { @@ -875,16 +790,163 @@ ipmgmt_persist_if(ipmgmt_if_arg_t *sargp)  	}  	if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0)  		goto ret; +  	if ((err = nvlist_add_string(nvl, IPADM_NVP_IFNAME,  	    sargp->ia_ifname)) != 0)  		goto ret; -	(void) snprintf(strval, IPMGMT_STRSIZE, "%d", sargp->ia_family); -	if ((err = nvlist_add_string(nvl, IPADM_NVP_FAMILY, strval)) != 0) + +	if ((err = ipmgmt_update_family_nvp(nvl, sargp->ia_family, +	    IPMGMT_APPEND)) != 0)  		goto ret; + +	(void) snprintf(strval, IPMGMT_STRSIZE, "%d", sargp->ia_ifclass); +	if ((err = nvlist_add_string(nvl, IPADM_NVP_IFCLASS, strval)) != 0) +		goto ret; +  	cb.dbw_nvl = nvl; -	cb.dbw_flags = 0; -	err = ipmgmt_db_walk(ipmgmt_db_add, &cb, IPADM_DB_WRITE); +	cb.dbw_flags = IPMGMT_APPEND | IPMGMT_UPDATE_IF; +	err = ipmgmt_db_walk(ipmgmt_db_update_if, &cb, IPADM_DB_WRITE);  ret:  	nvlist_free(nvl);  	return (err);  } + +/* + * The helper for ipmgmt_getif_handler and ipmgmt_getaddr_handler + */ +static void +ipmgmt_common_handler(char *if_name, char *aobj_name, db_wfunc_t worker) +{ +	size_t			buflen, onvlsize; +	char			*buf, *onvlbuf; +	ipmgmt_get_cbarg_t	cbarg; +	ipmgmt_get_rval_t	rval, *rvalp = &rval; +	int			err = 0; + +	cbarg.cb_ifname = if_name; +	cbarg.cb_aobjname = aobj_name; +	cbarg.cb_ocnt = 0; + +	if (nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0) != 0) +		goto fail; + +	err = ipmgmt_db_walk(worker, &cbarg, IPADM_DB_READ); +	if (err == ENOENT && cbarg.cb_ocnt > 0) { +		/* +		 * If there is at least one entry in the nvlist, +		 * do not return error. +		 */ +		err = 0; +	} +	if (err != 0) +		goto fail; + +	if ((err = nvlist_size(cbarg.cb_onvl, &onvlsize, +	    NV_ENCODE_NATIVE)) != 0) +		goto fail; + +	if (onvlsize > (UINT32_MAX - sizeof (ipmgmt_get_rval_t))) +		goto fail; + +	buflen = onvlsize + sizeof (ipmgmt_get_rval_t); +	/* +	 * We cannot use malloc() here because door_return never returns, and +	 * memory allocated by malloc() would get leaked. Use alloca() instead. +	 */ +	buf = alloca(buflen); +	onvlbuf = buf + sizeof (ipmgmt_get_rval_t); +	if ((err = nvlist_pack(cbarg.cb_onvl, &onvlbuf, +	    &onvlsize, NV_ENCODE_NATIVE, 0)) != 0) +		goto fail; + +	nvlist_free(cbarg.cb_onvl); +	rvalp = (ipmgmt_get_rval_t *)(void *)buf; +	rvalp->ir_err = 0; +	rvalp->ir_nvlsize = onvlsize; + +	(void) door_return(buf, buflen, NULL, 0); + +fail: +	nvlist_free(cbarg.cb_onvl); +	rvalp->ir_err = err; +	(void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0); +} + +/* + * Handles the door command IPMGMT_CMD_IPMP_UPDATE + */ +static void +ipmgmt_ipmp_update_handler(void *argp) +{ +	ipmgmt_ipmp_update_arg_t *uargp = argp; +	ipmgmt_retval_t	rval; +	ipadm_dbwrite_cbarg_t	cb; + +	boolean_t	gif_exists; +	char		gifname[LIFNAMSIZ]; +	nvlist_t	*nvl = NULL; +	uint32_t	flags = uargp->ia_flags; +	int		err = 0; + +	assert(uargp->ia_cmd == IPMGMT_CMD_IPMP_UPDATE); + +	gif_exists = ipmgmt_persist_if_exists(uargp->ia_gifname, +	    AF_UNSPEC); + +	if (!ipmgmt_persist_if_exists(uargp->ia_mifname, AF_UNSPEC)) { +		err = EINVAL; +		goto ret; +	} + +	ipmgmt_get_group_interface(uargp->ia_mifname, gifname, LIFNAMSIZ); + +	if (flags & IPMGMT_APPEND) { +		/* Group interface should be available in the DB */ +		if (!gif_exists) { +			err = ENOENT; +			goto ret; +		} + +		if (gifname[0] != '\0') { +			err = EEXIST; +			goto ret; +		} +	} + +	if (flags & IPMGMT_REMOVE) { +		/* We cannot remove something that does not exist */ +		if (!gif_exists || gifname[0] == '\0') { +			err = ENOENT; +			goto ret; +		} +		if (strcmp(uargp->ia_gifname, gifname) != 0) { +			err = EINVAL; +			goto ret; +		} +	} + +	if (flags & IPMGMT_PERSIST) { +		if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0) +			goto ret; + +		if ((err = nvlist_add_string(nvl, IPADM_NVP_IFNAME, +		    uargp->ia_gifname)) != 0) +			goto ret; + +		if ((err = nvlist_add_string(nvl, IPADM_NVP_MIFNAMES, +		    uargp->ia_mifname)) != 0) +			goto ret; + +		if ((err = nvlist_add_string(nvl, IPADM_NVP_GIFNAME, +		    uargp->ia_gifname)) != 0) +			goto ret; + +		cb.dbw_nvl = nvl; +		cb.dbw_flags = flags | IPMGMT_UPDATE_IF | IPMGMT_UPDATE_IPMP; +		err = ipmgmt_db_walk(ipmgmt_db_update_if, &cb, IPADM_DB_WRITE); +	} +ret: +	nvlist_free(nvl); +	rval.ir_err = err; +	(void) door_return((char *)&rval, sizeof (rval), NULL, 0); +} diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h index 968fa77923..fe7e95a87e 100644 --- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h @@ -22,7 +22,7 @@  /*   * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.   * Copyright (c) 2016, Chris Fraire <cfraire@me.com>. - * Copyright 2021, Tintri by DDN. All rights reserved. + * Copyright 2021 Tintri by DDN, Inc. All rights reserved.   */  #ifndef	_IPMGMT_IMPL_H @@ -51,6 +51,8 @@ extern void	ipmgmt_log(int, const char *, ...);  extern int	ipmgmt_cpfile(const char *, const char *, boolean_t);  /* ipmgmt_persist.c */ +extern boolean_t ipmgmt_persist_if_exists(const char *, sa_family_t); +extern void ipmgmt_get_group_interface(const char *, char *, size_t);  /*   * following are the list of DB walker callback functions and the callback @@ -60,25 +62,22 @@ extern int	ipmgmt_cpfile(const char *, const char *, boolean_t);  extern db_wfunc_t	ipmgmt_db_getprop, ipmgmt_db_resetprop;  /* following functions take ipadm_dbwrite_cbarg_t as callback argument */ -extern db_wfunc_t	ipmgmt_db_add, ipmgmt_db_update; +extern db_wfunc_t	ipmgmt_db_add, ipmgmt_db_update, ipmgmt_db_update_if;  typedef struct { -	char			*cb_ifname; -	ipadm_if_info_list_t	*cb_ifinfo; -} ipmgmt_getif_cbarg_t; -extern db_wfunc_t	ipmgmt_db_getif; - -typedef struct { -	char		*cb_aobjname; -	char		*cb_ifname; +	char	*cb_ifname; +	char	*cb_aobjname;  	nvlist_t	*cb_onvl; -	int		cb_ocnt; -} ipmgmt_getaddr_cbarg_t; +	int	cb_ocnt; +} ipmgmt_get_cbarg_t; +extern db_wfunc_t	ipmgmt_db_getif;  extern db_wfunc_t	ipmgmt_db_getaddr;  typedef struct {  	sa_family_t	cb_family;  	char		*cb_ifname; +	boolean_t	cb_ipv4exists; +	boolean_t	cb_ipv6exists;  } ipmgmt_if_cbarg_t;  extern db_wfunc_t	ipmgmt_db_setif, ipmgmt_db_resetif; @@ -182,6 +181,8 @@ typedef struct scf_resources {  	scf_transaction_entry_t	*sr_ent;  } scf_resources_t; +extern int		ipmgmt_update_family_nvp(nvlist_t *, +			    sa_family_t, uint_t);  extern int		ipmgmt_db_walk(db_wfunc_t *, void *, ipadm_db_op_t);  extern int		ipmgmt_aobjmap_op(ipmgmt_aobjmap_t *, uint32_t);  extern boolean_t	ipmgmt_aobjmap_init(void *, nvlist_t *, char *, diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c index e3a8d3e817..3573ca40ca 100644 --- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c @@ -21,7 +21,7 @@  /*   * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2021, Tintri by DDN. All rights reserved. + * Copyright 2021 Tintri by DDN, Inc. All rights reserved.   */  /* @@ -522,31 +522,6 @@ child_out:  }  /* - * Return TRUE if `ifname' has persistent configuration for the `af' address - * family in the datastore - */ -static boolean_t -ipmgmt_persist_if_exists(char *ifname, sa_family_t af) -{ -	ipmgmt_getif_cbarg_t cbarg; -	boolean_t exists = B_FALSE; -	ipadm_if_info_t *ifp; - -	bzero(&cbarg, sizeof (cbarg)); -	cbarg.cb_ifname = ifname; -	(void) ipmgmt_db_walk(ipmgmt_db_getif, &cbarg, IPADM_DB_READ); -	if (cbarg.cb_ifinfo != NULL) { -		ifp = &cbarg.cb_ifinfo->ifil_ifi; -		if ((af == AF_INET && (ifp->ifi_pflags & IFIF_IPV4)) || -		    (af == AF_INET6 && (ifp->ifi_pflags & IFIF_IPV6))) { -			exists = B_TRUE; -		} -	} -	free(cbarg.cb_ifinfo); -	return (exists); -} - -/*   * Persist any NGZ interfaces assigned to us from the global zone if they do   * not already exist in the persistent db. We need to   * do this before any calls to ipadm_enable_if() can succeed (i.e., diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c index 5f9d24df7a..cf9e30e819 100644 --- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c @@ -24,7 +24,7 @@   * Copyright 2018 Joyent, Inc.   * Copyright 2016 Argo Technologie SA.   * Copyright (c) 2016-2017, Chris Fraire <cfraire@me.com>. - * Copyright 2021, Tintri by DDN. All rights reserved. + * Copyright 2021 Tintri by DDN, Inc. All rights reserved.   */  /* @@ -81,6 +81,161 @@ extern pthread_rwlock_t ipmgmt_dbconf_lock;  /* signifies whether volatile copy of data store is in use */  static boolean_t ipmgmt_rdonly_root = B_FALSE; +typedef int ipmgmt_if_updater_func_t(nvlist_t *, nvpair_t *, uint_t); + +static ipmgmt_if_updater_func_t ipmgmt_if_family_updater; +static ipmgmt_if_updater_func_t ipmgmt_if_groupmembers_updater; + +static int ipmgmt_get_ifinfo_nvl(const char *ifname, nvlist_t **if_info_nvl); + +typedef struct { +	const char	*name; +	ipmgmt_if_updater_func_t	*func; +} ipmgmt_if_updater_ent_t; + +static ipmgmt_if_updater_ent_t ipmgmt_if_updater_ent[] = { +	{IPADM_NVP_FAMILIES, ipmgmt_if_family_updater}, +	{IPADM_NVP_MIFNAMES, ipmgmt_if_groupmembers_updater}, +	{NULL, NULL} +}; + +static ipmgmt_if_updater_ent_t * +ipmgmt_find_if_field_updater(const char *field_name) +{ +	int i; + +	for (i = 0; ipmgmt_if_updater_ent[i].name != NULL; i++) { +		if (strcmp(field_name, ipmgmt_if_updater_ent[i].name) == 0) { +			break; +		} +	} + +	return (&ipmgmt_if_updater_ent[i]); +} + +static int +ipmgmt_if_groupmembers_updater(nvlist_t *db_nvl, nvpair_t *member_nvp, +    uint_t flags) +{ +	char	**members; +	char	*member; +	char	**out_members; +	uint_t  nelem = 0, cnt = 0; +	int	err; + +	if ((err = nvpair_value_string(member_nvp, &member)) != 0) +		return (err); + +	err = nvlist_lookup_string_array(db_nvl, IPADM_NVP_MIFNAMES, +	    &members, &nelem); + +	if (err != 0 && (flags & IPMGMT_REMOVE)) +		return (ENOENT); + +	/* +	 * Reserve one extra slot for IPMGMT_APPEND. +	 * Probably not worth conditionalizing. +	 */ +	out_members = calloc(nelem + 1, sizeof (char *)); +	if (out_members == NULL) +		return (ENOMEM); + +	while (nelem-- > 0) { +		if ((flags & IPMGMT_REMOVE) && +		    (strcmp(member, members[nelem]) == 0)) +			continue; + +		if ((out_members[cnt] = strdup(members[nelem])) == NULL) { +			err = ENOMEM; +			goto fail; +		} + +		cnt++; +	} + +	if (flags & IPMGMT_APPEND) { +		if ((out_members[cnt] = strdup(member)) == NULL) { +			err = ENOMEM; +			goto fail; +		} +		cnt++; +	} + +	if (cnt == 0) { +		err = nvlist_remove(db_nvl, IPADM_NVP_MIFNAMES, +		    DATA_TYPE_STRING_ARRAY); +	} else { +		err = nvlist_add_string_array(db_nvl, IPADM_NVP_MIFNAMES, +		    out_members, cnt); +	} + +fail: +	while (cnt--) +		free(out_members[cnt]); + +	free(out_members); + +	return (err); +} + +static int +ipmgmt_if_family_updater(nvlist_t *db_nvl, nvpair_t *families_nvp, uint_t flags) +{ +	uint16_t *families; +	uint_t  nelem = 0; +	int	err; + +	if ((err = nvpair_value_uint16_array(families_nvp, &families, +	    &nelem)) != 0) +		return (err); + +	return (ipmgmt_update_family_nvp(db_nvl, families[0], flags)); +} + +int +ipmgmt_update_family_nvp(nvlist_t *nvl, sa_family_t af, uint_t flags) +{ +	uint16_t	*families = NULL; +	uint16_t	out_families[2]; +	uint_t	nelem = 0, cnt; +	int	err; + +	err = nvlist_lookup_uint16_array(nvl, IPADM_NVP_FAMILIES, +	    &families, &nelem); +	if (err != 0 && (flags & IPMGMT_REMOVE)) { +		return (ENOENT); +	} + +	if (flags & IPMGMT_APPEND) { +		if (families != NULL) { +			if (nelem == 2 || families[0] == af) { +				return (EEXIST); +			} +			out_families[0] = families[0]; +			out_families[1] = af; +			cnt = 2; +		} else { +			out_families[0] = af; +			cnt = 1; +		} +	} else { +		assert(nelem == 1 || nelem == 2); +		cnt = 0; +		while (nelem-- > 0) { +			if (families[nelem] != af) { +				out_families[cnt] = families[nelem]; +				cnt++; +			} +		} +	} + +	if (cnt != 0) { +		return (nvlist_add_uint16_array(nvl, IPADM_NVP_FAMILIES, +		    out_families, cnt)); +	} +	return (nvlist_remove(nvl, IPADM_NVP_FAMILIES, DATA_TYPE_UINT16_ARRAY)); +} +  /*   * Checks if the database nvl, `db_nvl' contains and matches ALL of the passed   * in private nvpairs `proto', `ifname' & `aobjname'. @@ -329,7 +484,7 @@ boolean_t  ipmgmt_db_getaddr(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,      int *errp)  { -	ipmgmt_getaddr_cbarg_t	*cbarg = arg; +	ipmgmt_get_cbarg_t	*cbarg = arg;  	char		*db_aobjname = NULL;  	char		*db_ifname = NULL;  	nvlist_t	*db_addr = NULL; @@ -556,57 +711,130 @@ ipmgmt_db_update(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,  }  /* - * For the given `cbarg->cb_ifname' interface, retrieves any persistent - * interface information (used in 'ipadm show-if') + * This function is used to update a DB line that describes + * an interface, its family and group interface + *   */ -/* ARGSUSED */  boolean_t -ipmgmt_db_getif(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen, +ipmgmt_db_update_if(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,      int *errp)  { -	ipmgmt_getif_cbarg_t	*cbarg = arg; -	char			*ifname = cbarg->cb_ifname; -	char			*intf = NULL; -	ipadm_if_info_list_t	*ifl = NULL; -	ipadm_if_info_t		*ifp; -	sa_family_t		af; -	char			*afstr; +	ipadm_dbwrite_cbarg_t *cb = arg; +	ipmgmt_if_updater_ent_t *updater; +	nvlist_t	*in_nvl = cb->dbw_nvl; +	uint_t		flags = cb->dbw_flags; +	nvpair_t	*nvp; +	char		*name; +	char		*db_ifname; +	char		*gifname = NULL; +	char		*mifname = NULL;  	*errp = 0; -	if (nvlist_lookup_string(db_nvl, IPADM_NVP_FAMILY, &afstr) != 0 || -	    nvlist_lookup_string(db_nvl, IPADM_NVP_IFNAME, &intf) != 0 || -	    (ifname[0] != '\0' && strcmp(ifname, intf) != 0)) { + +	/* Only one flag */ +	if ((flags & (IPMGMT_APPEND | IPMGMT_REMOVE)) == 0 || +	    ((flags & IPMGMT_APPEND) && (flags & IPMGMT_REMOVE))) { +		*errp = EINVAL; +		return (B_FALSE); +	} + +	if (!nvlist_exists(db_nvl, IPADM_NVP_FAMILIES))  		return (B_TRUE); + +	if (nvlist_exists(db_nvl, IPADM_NVP_IFCLASS) && +	    nvlist_lookup_string(db_nvl, IPADM_NVP_IFNAME, &db_ifname) == 0 && +	    nvlist_lookup_string(in_nvl, IPADM_NVP_GIFNAME, &gifname) == 0 && +	    nvlist_lookup_string(in_nvl, IPADM_NVP_MIFNAMES, &mifname) == 0 && +	    strcmp(db_ifname, mifname) == 0) { +		if (flags & IPMGMT_APPEND) { +			if ((*errp = nvlist_add_string(db_nvl, +			    IPADM_NVP_GIFNAME, gifname)) != 0) +				return (B_FALSE); +		} else { +			if ((*errp = nvlist_remove(db_nvl, IPADM_NVP_GIFNAME, +			    DATA_TYPE_STRING)) != 0) +				return (B_FALSE); +		} +		cb->dbw_flags &= ~IPMGMT_UPDATE_IPMP; +		goto done;  	} -	af = atoi(afstr); -	for (ifl = cbarg->cb_ifinfo; ifl != NULL; ifl = ifl->ifil_next) { -		ifp = &ifl->ifil_ifi; -		if (strcmp(ifp->ifi_name, intf) == 0) -			break; + +	if (!ipmgmt_nvlist_intersects(db_nvl, in_nvl)) +		return (B_TRUE); + +	for (nvp = nvlist_next_nvpair(in_nvl, NULL); nvp != NULL; +	    nvp = nvlist_next_nvpair(in_nvl, nvp)) { +		name = nvpair_name(nvp); +		if (strcmp(name, IPADM_NVP_FAMILIES) != 0 && +		    strcmp(name, IPADM_NVP_MIFNAMES) != 0) +			continue; + +		updater = ipmgmt_find_if_field_updater(name); +		assert(updater != NULL); +		*errp = (*updater->func)(db_nvl, nvp, flags); +		if (*errp != 0) +			return (B_FALSE);  	} -	if (ifl == NULL) { -		ipadm_if_info_list_t *new; -		if ((new = calloc(1, sizeof (*new))) == NULL) { -			*errp = ENOMEM; -			return (B_FALSE); /* don't continue the walk */ -		} -		new->ifil_next = cbarg->cb_ifinfo; -		cbarg->cb_ifinfo = new; -		ifp = &new->ifil_ifi; -		(void) strlcpy(ifp->ifi_name, intf, sizeof (ifp->ifi_name)); +	cb->dbw_flags &= ~IPMGMT_UPDATE_IF; + +done: +	(void) memset(buf, 0, buflen); +	if (ipadm_nvlist2str(db_nvl, buf, buflen) == 0) { +		*errp = EOVERFLOW; +		return (B_FALSE);  	} -	if (af == AF_INET) { -		ifp->ifi_pflags |= IFIF_IPV4; -	} else { -		assert(af == AF_INET6); -		ifp->ifi_pflags |= IFIF_IPV6; +	/* we finished all operations, so do not continue */ +	if ((cb->dbw_flags & (IPMGMT_UPDATE_IF | IPMGMT_UPDATE_IPMP)) == 0) +		return (B_FALSE); + +	return (B_TRUE); +} + +/* + * For the given `cbarg->cb_ifname' interface, retrieve the nvlist that + * represents the persistent interface information. + * The nvlist contains: + *      IPADM_NVP_IFNAME + *      IPADM_NVP_FAMILIES + *      IPADM_NVP_IF_CLASS + * + * (used in 'ipadm show-if') + */ +/* ARGSUSED */ +boolean_t +ipmgmt_db_getif(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen, +    int *errp) +{ +	ipmgmt_get_cbarg_t *cbarg = arg; +	char		*ifname = cbarg->cb_ifname; +	nvpair_t	*nvp; +	char		*db_ifname = NULL; +	boolean_t	families = B_FALSE; + +	/* Parse db nvlist */ +	for (nvp = nvlist_next_nvpair(db_nvl, NULL); nvp != NULL; +	    nvp = nvlist_next_nvpair(db_nvl, nvp)) { +		if (strcmp(nvpair_name(nvp), IPADM_NVP_IFNAME) == 0) { +			(void) nvpair_value_string(nvp, &db_ifname); +		} else if (strcmp(nvpair_name(nvp), IPADM_NVP_FAMILIES) == 0) { +			families = B_TRUE; +		}  	} -	/* Terminate the walk if we found both v4 and v6 interfaces. */ -	if (ifname[0] != '\0' && (ifp->ifi_pflags & IFIF_IPV4) && -	    (ifp->ifi_pflags & IFIF_IPV6)) +	if (db_ifname == NULL || !families) +		return (B_TRUE); + +	if (ifname != NULL && ifname[0] != '\0' && +	    strcmp(ifname, db_ifname) != 0) +		return (B_TRUE); + +	*errp = nvlist_add_nvlist(cbarg->cb_onvl, db_ifname, db_nvl); +	if (*errp == 0) +		cbarg->cb_ocnt++; + +	if (ifname != NULL && ifname[0] != '\0')  		return (B_FALSE);  	return (B_TRUE); @@ -625,7 +853,6 @@ ipmgmt_db_resetif(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,  	boolean_t	isv6 = (cbarg->cb_family == AF_INET6);  	char		*ifname = cbarg->cb_ifname;  	char		*modstr = NULL; -	char		*afstr;  	char		*aobjname;  	uint_t		proto;  	ipmgmt_aobjmap_t *head; @@ -636,9 +863,31 @@ ipmgmt_db_resetif(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,  	if (!ipmgmt_nvlist_contains(db_nvl, NULL, ifname, NULL))  		return (B_TRUE); -	if (nvlist_lookup_string(db_nvl, IPADM_NVP_FAMILY, &afstr) == 0) { -		if (atoi(afstr) == cbarg->cb_family) +	if (nvlist_exists(db_nvl, IPADM_NVP_FAMILIES)) { + +		if ((*errp = ipmgmt_update_family_nvp(db_nvl, cbarg->cb_family, +		    IPMGMT_REMOVE)) != 0) { +			return (B_FALSE); +		} + +		if (cbarg->cb_family == AF_INET) { +			cbarg->cb_ipv4exists = B_FALSE; +		} else { +			assert(cbarg->cb_family == AF_INET6); +			cbarg->cb_ipv6exists = B_FALSE; +		} +		if (!nvlist_exists(db_nvl, IPADM_NVP_FAMILIES)) { +			cbarg->cb_ipv4exists = B_FALSE; +			cbarg->cb_ipv6exists = B_FALSE;  			goto delete; +		} +		/* Otherwise need to reconstruct this string */ +		(void) memset(buf, 0, buflen); +		if (ipadm_nvlist2str(db_nvl, buf, buflen) == 0) { +			/* buffer overflow */ +			*errp = EOVERFLOW; +			return (B_FALSE); +		}  		return (B_TRUE);  	} @@ -694,8 +943,8 @@ ipmgmt_db_resetif(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,  				goto delete;  			break;  		case MOD_PROTO_IP: -			/* this should never be the case, today */ -			assert(0); +			if (!cbarg->cb_ipv4exists && !cbarg->cb_ipv6exists) +				goto delete;  			break;  		}  	} @@ -895,7 +1144,7 @@ ipmgmt_aobjmap_op(ipmgmt_aobjmap_t *nodep, uint32_t op)  	ipmgmt_aobjmap_t	*head, *prev, *matched = NULL;  	boolean_t		update = B_TRUE;  	int			err = 0; -	ipadm_db_op_t		db_op; +	ipadm_db_op_t		db_op = IPADM_DB_READ;  	(void) pthread_rwlock_wrlock(&aobjmap.aobjmap_rwlock); @@ -1371,7 +1620,7 @@ ipmgmt_db_init(void *cbarg, nvlist_t *db_nvl, char *buf, size_t buflen,      int *errp)  {  	ipadm_handle_t	iph = cbarg; -	nvpair_t	*nvp, *pnvp; +	nvpair_t	*nvp, *pnvp = NULL;  	char		*strval = NULL, *name, *mod = NULL, *pname;  	char		tmpstr[IPMGMT_STRSIZE];  	uint_t		proto; @@ -1398,7 +1647,7 @@ ipmgmt_db_init(void *cbarg, nvlist_t *db_nvl, char *buf, size_t buflen,  		}  	} -	/* if we are here than we found a global property */ +	/* If we are here then we have found a global property */  	assert(mod != NULL);  	assert(nvpair_type(pnvp) == DATA_TYPE_STRING); @@ -1587,6 +1836,8 @@ ipmgmt_get_scfprop(scf_resources_t *res, const char *pgname, const char *pname,  	case SCF_TYPE_ASTRING:  		*(char **)pval = scf_simple_prop_next_astring(prop);  		break; +	default: +		break;  	}  ret:  	scf_simple_prop_free(prop); @@ -1710,3 +1961,109 @@ ipmgmt_update_dbver(scf_resources_t *res)  	(void) ipmgmt_set_scfprop(res, IPMGMTD_APP_PG,  	    IPMGMTD_PROP_DBVER, &version, SCF_TYPE_INTEGER);  } + +/* + * Return TRUE if `ifname' has persistent configuration for the `af' address + * family in the datastore. + * It is possible to call the function with af == AF_UNSPEC, so in this case + * the function returns TRUE if either AF_INET or AF_INET6 interface exists + */ +boolean_t +ipmgmt_persist_if_exists(const char *ifname, sa_family_t af) +{ +	boolean_t exists = B_FALSE; +	nvlist_t    *if_info_nvl; +	uint16_t    *families = NULL; +	sa_family_t af_db; +	uint_t	nelem = 0; + +	if (ipmgmt_get_ifinfo_nvl(ifname, &if_info_nvl) != 0) +		goto done; + +	if (nvlist_lookup_uint16_array(if_info_nvl, IPADM_NVP_FAMILIES, +	    &families, &nelem) != 0) +		goto done; + +	while (nelem-- > 0) { +		af_db = families[nelem]; +		if (af_db == af || (af == AF_UNSPEC && +		    (af_db == AF_INET || af_db == AF_INET6))) { +			exists = B_TRUE; +			break; +		} +	} + +done: +	if (if_info_nvl != NULL) +		nvlist_free(if_info_nvl); + +	return (exists); +} + +/* + * Retrieves the membership information for the requested mif_name + * if mif_name is a member of a IPMP group, then gif_name will contain + * the name of IPMP group interface, otherwise the variable will be empty + */ +void +ipmgmt_get_group_interface(const char *mif_name, char *gif_name, size_t size) +{ +	char	*gif_name_from_nvl; +	nvlist_t	*if_info_nvl; + +	gif_name[0] = '\0'; + +	if (ipmgmt_get_ifinfo_nvl(mif_name, &if_info_nvl) != 0) +		goto done; + +	if (nvlist_lookup_string(if_info_nvl, IPADM_NVP_GIFNAME, +	    &gif_name_from_nvl) != 0) +		goto done; + +	(void) strlcpy(gif_name, gif_name_from_nvl, size); + +done: +	if (if_info_nvl != NULL) +		nvlist_free(if_info_nvl); +} + +static int +ipmgmt_get_ifinfo_nvl(const char *ifname, nvlist_t **if_info_nvl) +{ +	ipmgmt_get_cbarg_t cbarg; +	nvpair_t    *nvp; +	nvlist_t    *nvl; +	int	err; + +	cbarg.cb_ifname = NULL; +	cbarg.cb_aobjname = NULL; +	cbarg.cb_ocnt = 0; + +	if ((err = nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0)) != 0) +		goto done; + +	err = ipmgmt_db_walk(ipmgmt_db_getif, &cbarg, IPADM_DB_READ); +	if (err == ENOENT && cbarg.cb_ocnt > 0) +		err = 0; + +	if (err != 0) +		goto done; + +	for (nvp = nvlist_next_nvpair(cbarg.cb_onvl, NULL); nvp != NULL; +	    nvp = nvlist_next_nvpair(cbarg.cb_onvl, nvp)) { + +		if (strcmp(nvpair_name(nvp), ifname) != 0) +			continue; + +		if ((err = nvpair_value_nvlist(nvp, &nvl)) != 0 || +		    (err = nvlist_dup(nvl, if_info_nvl, NV_UNIQUE_NAME)) != 0) +			*if_info_nvl = NULL; + +		break; +	} + +done: +	nvlist_free(cbarg.cb_onvl); + +	return (err); +} diff --git a/usr/src/cmd/cmd-inet/usr.lib/in.mpathd/Makefile b/usr/src/cmd/cmd-inet/usr.lib/in.mpathd/Makefile index 3668af100b..d63134dae8 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/in.mpathd/Makefile +++ b/usr/src/cmd/cmd-inet/usr.lib/in.mpathd/Makefile @@ -22,16 +22,21 @@  # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.  # Use is subject to license terms.  # +# Copyright 2021 Tintri by DDN, Inc. All rights reserved. +#  PROG		= in.mpathd  ROOTFS_PROG	= $(PROG)  OBJS		= mpd_tables.o mpd_main.o mpd_probe.o  SRCS		= $(OBJS:%.o=%.c)  DEFAULTFILES	= mpathd.dfl +SVCMETHOD	= net-ipmp +MANIFEST	= network-ipmp.xml  include ../../../Makefile.cmd  ROOTCMDDIR	= $(ROOT)/lib/inet +ROOTMANIFESTDIR	= $(ROOTSVCNETWORK)  POFILE		= $(PROG).po  POFILES		= $(SRCS:%.c=%.po) @@ -63,15 +68,9 @@ $(PROG):	$(OBJS)  		$(LINK.c) -o $@ $(OBJS) $(LDLIBS) $(CTFMERGE_HOOK)  		$(POST_PROCESS) -include ../Makefile.lib - -$(ROOTLIBINETPROG): -		$(RM) $@; $(SYMLINK) ../../../lib/inet/$(PROG) $@ - -$(ROOTSBINPROG): -		$(RM) $@; $(SYMLINK) ../lib/inet/$(PROG) $@ +check:		$(CHKMANIFEST) -install:	all $(ROOTLIBINETPROG) $(ROOTSBINPROG) $(ROOTCMD) \ +install:	all $(ROOTCMD) $(ROOTMANIFEST) $(ROOTSVCMETHOD) \  		$(ROOTETCDEFAULTFILES)  clean: @@ -79,7 +78,7 @@ clean:  lint:		lint_SRCS -$(POFILE): 	$(POFILES) +$(POFILE):	$(POFILES)  		$(RM) $@  		$(CAT) $(POFILES) > $@ diff --git a/usr/src/cmd/cmd-inet/usr.lib/in.mpathd/net-ipmp b/usr/src/cmd/cmd-inet/usr.lib/in.mpathd/net-ipmp new file mode 100644 index 0000000000..be4263a74b --- /dev/null +++ b/usr/src/cmd/cmd-inet/usr.lib/in.mpathd/net-ipmp @@ -0,0 +1,31 @@ +#!/sbin/sh +# +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source.  A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2021 Tintri by DDN, Inc. All rights reserved. +# + +. /lib/svc/share/smf_include.sh + +if [ -z "$SMF_FMRI" ]; then +        echo "this script can only be invoked by smf(5)" +        exit $SMF_EXIT_ERR_NOSMF +fi + +smf_configure_ip || exit $SMF_EXIT_ERR_FATAL + +if /lib/inet/in.mpathd; then +        exit $SMF_EXIT_OK +else +        exit $SMF_EXIT_ERR_FATAL +fi diff --git a/usr/src/cmd/cmd-inet/usr.lib/in.mpathd/network-ipmp.xml b/usr/src/cmd/cmd-inet/usr.lib/in.mpathd/network-ipmp.xml new file mode 100644 index 0000000000..282bf5b4df --- /dev/null +++ b/usr/src/cmd/cmd-inet/usr.lib/in.mpathd/network-ipmp.xml @@ -0,0 +1,78 @@ +<?xml version='1.0'?> +<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'> + +<!-- + Copyright 2021 Tintri by DDN, Inc. All rights reserved. + + This file and its contents are supplied under the terms of the + Common Development and Distribution License ("CDDL"), version 1.0. + You may only use this file in accordance with the terms of version + 1.0 of the CDDL. + + A full copy of the text of the CDDL should have accompanied this + source.  A copy of the CDDL is also available via the Internet at + http://www.illumos.org/license/CDDL. + +        NOTE:  This service manifest is not editable; its contents will +        be overwritten by package or patch operations, including +        operating system upgrade.  Make customizations in a different +        file. +--> + +<service_bundle type='manifest' name='SUNWcsr:ipmp'> + +<service +	name='network/ipmp' +	type='service' +	version='1'> + +	<create_default_instance enabled='true' /> + +	<dependency name='loopback' grouping='require_all' restart_on='none' +	    type='service'> +		<service_fmri value='svc:/network/loopback' /> +	</dependency> + +	<dependent name='network-physical' grouping='optional_all' +	    restart_on='none'> +		<service_fmri value='svc:/network/physical:default' /> +	</dependent> + +	<exec_method type='method' name='start' exec='/lib/svc/method/net-ipmp' +	    timeout_seconds='60'> +	</exec_method> + +	<exec_method type='method' name='stop' exec=':kill' +	    timeout_seconds='60'> +	</exec_method> + +	<exec_method type='method' name='refresh' exec=':kill -HUP' +	    timeout_seconds='60'> +	</exec_method> + +	<property_group name='config' type='application'> +		<propval name='action_authorization' type='astring' +		    value='solaris.smf.manage.ipmp' /> +	</property_group> + +	<property_group name='general' type='framework'> +		<propval name='action_authorization' type='astring' +		    value='solaris.smf.manage.ipmp' /> +		<propval name='value_authorization' type='astring' +		    value='solaris.smf.manage.ipmp' /> +	</property_group> + +	<stability value='Unstable' /> + +	<template> +		<common_name> +			<loctext xml:lang='C'> +				IP MultiPathing +			</loctext> +		</common_name> +		<documentation> +			<manpage title='in.mpathd' section='1M' /> +		</documentation> +	</template> +</service> +</service_bundle> diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ipadm/Makefile b/usr/src/cmd/cmd-inet/usr.sbin/ipadm/Makefile index 801fb40158..c9337fb75b 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/ipadm/Makefile +++ b/usr/src/cmd/cmd-inet/usr.sbin/ipadm/Makefile @@ -23,6 +23,9 @@  # Use is subject to license terms.  #  # Copyright 2020 Joyent, Inc. +# Copyright 2021 Tintri by DDN, Inc. All rights reserved. +# +#  PROG =		ipadm  ROOTFS_PROG =	$(PROG) @@ -39,7 +42,7 @@ COMMONSRCS=	$(CMDINETCOMMONDIR)/$(COMMONOBJS:%.o=%.c)  SRCS=		$(LOCALSRCS) $(COMMONSRCS)  CPPFLAGS +=	-I$(CMDINETCOMMONDIR) -LDLIBS +=       -lofmt -linetutil -lipadm -lnvpair +LDLIBS +=       -lofmt -linetutil -lipadm -lnvpair -lipmp -lcmdutils  LINTFLAGS +=	-m  ROOTUSRSBINLINKS = $(PROG:%=$(ROOTUSRSBIN)/%) diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c b/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c index e48b32733f..1a1aa5e5ac 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c +++ b/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c @@ -21,11 +21,10 @@  /*   * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2017 Nexenta Systems, Inc.   * Copyright (c) 2018, Joyent, Inc.   * Copyright 2017 Gary Mills   * Copyright (c) 2016, Chris Fraire <cfraire@me.com>. - * Copyright 2021, Tintri by DDN. All rights reserved. + * Copyright 2021 Tintri by DDN, Inc. All rights reserved.   * Copyright 2021 OmniOS Community Edition (OmniOSce) Association.   */ @@ -40,6 +39,8 @@  #include <libdllink.h>  #include <libinetutil.h>  #include <libipadm.h> +#include <ipmp.h> +#include <ipmp_admin.h>  #include <locale.h>  #include <netdb.h>  #include <netinet/in.h> @@ -53,21 +54,25 @@  #include <sys/stat.h>  #include <sys/types.h>  #include <zone.h> +#include <sys/list.h> +#include <stddef.h>  #define	STR_UNKNOWN_VAL	"?"  #define	LIFC_DEFAULT	(LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES |\  			LIFC_UNDER_IPMP) +static void do_create_ip_common(int, char **, const char *, uint32_t); +  typedef void cmdfunc_t(int, char **, const char *);  static cmdfunc_t do_help; -static cmdfunc_t do_create_if, do_delete_if, do_enable_if, do_disable_if; -static cmdfunc_t do_show_if; -static cmdfunc_t do_set_prop, do_show_prop, do_set_ifprop; -static cmdfunc_t do_show_ifprop, do_reset_ifprop, do_reset_prop; -static cmdfunc_t do_show_addrprop, do_set_addrprop, do_reset_addrprop; -static cmdfunc_t do_create_addr, do_delete_addr, do_show_addr; -static cmdfunc_t do_enable_addr, do_disable_addr; -static cmdfunc_t do_up_addr, do_down_addr, do_refresh_addr; +static cmdfunc_t do_create_ip, do_delete_ip; +static cmdfunc_t do_create_ipmp, do_add_ipmp, do_remove_ipmp; +static cmdfunc_t do_disable_if, do_enable_if, do_show_if; +static cmdfunc_t do_set_ifprop, do_reset_ifprop, do_show_ifprop; +static cmdfunc_t do_create_addr, do_delete_addr, do_show_addr, do_refresh_addr; +static cmdfunc_t do_disable_addr, do_enable_addr, do_down_addr, do_up_addr; +static cmdfunc_t do_set_addrprop, do_reset_addrprop, do_show_addrprop; +static cmdfunc_t do_set_prop, do_reset_prop, do_show_prop;  typedef struct	cmd {  	char		*c_name; @@ -78,12 +83,28 @@ typedef struct	cmd {  static cmd_t	cmds[] = {  	{ "help",	do_help,	NULL },  	/* interface management related sub-commands */ -	{ "create-if",	do_create_if,	"\tcreate-if\t[-t] <interface>"	}, -	{ "disable-if",	do_disable_if,	"\tdisable-if\t-t <interface>"	}, -	{ "enable-if",	do_enable_if,	"\tenable-if\t-t <interface>"	}, -	{ "delete-if",	do_delete_if,	"\tdelete-if\t<interface>"	}, -	{ "show-if",	do_show_if, +	{ "create-if", do_create_ip, "\tcreate-if\t[-t] <interface>"	}, +	{ "create-ip", do_create_ip, "\tcreate-ip\t[-t] <interface>"	}, +	{ "delete-if", do_delete_ip, "\tdelete-if\t<interface>\n"	}, +	{ "delete-ip", do_delete_ip, "\tdelete-ip\t<interface>\n"	}, + +	{ "create-ipmp", do_create_ipmp, +	    "\tcreate-ipmp\t[-t] [-i <interface>[,<interface>]...] " +	    "<ipmp-interface>"						}, +	{ "delete-ipmp", do_delete_ip, +	    "\tdelete-ipmp\t<ipmp-interface>"				}, +	{ "add-ipmp", do_add_ipmp, +	    "\tadd-ipmp\t[-t] -i <interface>[,<interface>]... " +	    "<ipmp-interface>"						}, +	{ "remove-ipmp", do_remove_ipmp, +	    "\tremove-ipmp\t[-t] -i <interface>[,<interface>]... " +	    "<ipmp-interface>\n"					}, + +	{ "disable-if", do_disable_if, "\tdisable-if\t-t <interface>"	}, +	{ "enable-if", do_enable_if, "\tenable-if\t-t <interface>"	}, +	{ "show-if", do_show_if,  	    "\tshow-if\t\t[[-p] -o <field>,...] [<interface>]\n"	}, +  	{ "set-ifprop",	do_set_ifprop,  	    "\tset-ifprop\t[-t] -p <prop>=<value[,...]> -m <protocol> "  	    "<interface>"						}, @@ -101,14 +122,15 @@ static cmd_t	cmds[] = {  	    "\t\t\t[-1] [-h <hostname>] <addrobj>\n"  	    "\tcreate-addr\t[-t] -T addrconf [-i interface-id]\n"  	    "\t\t\t[-p {stateful|stateless}={yes|no}] <addrobj>" }, -	{ "down-addr",	do_down_addr,	"\tdown-addr\t[-t] <addrobj>"	}, -	{ "up-addr",	do_up_addr,	"\tup-addr\t\t[-t] <addrobj>"	}, -	{ "disable-addr", do_disable_addr, "\tdisable-addr\t-t <addrobj>" }, -	{ "enable-addr", do_enable_addr, "\tenable-addr\t-t <addrobj>"	}, -	{ "refresh-addr", do_refresh_addr, "\trefresh-addr\t[-i] <addrobj>" },  	{ "delete-addr", do_delete_addr, "\tdelete-addr\t[-r] <addrobj>" }, -	{ "show-addr",	do_show_addr, -	    "\tshow-addr\t[[-p] -o <field>,...] [<addrobj>]\n"		}, +	{ "show-addr", do_show_addr, +	    "\tshow-addr\t[[-p] -o <field>,...] [<addrobj>]"		}, +	{ "refresh-addr", do_refresh_addr, "\trefresh-addr\t[-i] <addrobj>" }, +	{ "down-addr", do_down_addr, "\tdown-addr\t[-t] <addrobj>"	}, +	{ "up-addr", do_up_addr, "\tup-addr\t\t[-t] <addrobj>"	}, +	{ "disable-addr", do_disable_addr, "\tdisable-addr\t-t <addrobj>" }, +	{ "enable-addr", do_enable_addr, "\tenable-addr\t-t <addrobj>\n" }, +  	{ "set-addrprop", do_set_addrprop,  	    "\tset-addrprop\t[-t] -p <prop>=<value[,...]> <addrobj>"	},  	{ "reset-addrprop", do_reset_addrprop, @@ -118,11 +140,11 @@ static cmd_t	cmds[] = {  	    "<addrobj>\n"						},  	/* protocol properties related sub-commands */ -	{ "set-prop",	do_set_prop, +	{ "set-prop", do_set_prop,  	    "\tset-prop\t[-t] -p <prop>[+|-]=<value[,...]> <protocol>"	}, -	{ "reset-prop",	do_reset_prop, +	{ "reset-prop", do_reset_prop,  	    "\treset-prop\t[-t] -p <prop> <protocol>"			}, -	{ "show-prop",	do_show_prop, +	{ "show-prop", do_show_prop,  	    "\tshow-prop\t[[-c] -o <field>,...] [-p <prop>,...]"  	    " [protocol]"						}  }; @@ -282,7 +304,7 @@ typedef struct show_addr_args_s {  typedef struct show_if_args_s {  	show_if_state_t *si_state; -	ipadm_if_info_list_t *si_info; +	ipadm_if_info_t *si_info;  } show_if_args_t;  typedef enum { @@ -296,6 +318,7 @@ typedef enum {  typedef enum {  	SI_IFNAME, +	SI_IFCLASS,  	SI_STATE,  	SI_CURRENT,  	SI_PERSISTENT @@ -315,6 +338,7 @@ static ofmt_field_t show_addr_fields[] = {  static ofmt_field_t show_if_fields[] = {  /* name,	field width,	id,		callback */  { "IFNAME",	11,		SI_IFNAME,	print_si_cb}, +{ "CLASS",	10,		SI_IFCLASS,	print_si_cb},  { "STATE",	9,		SI_STATE,	print_si_cb},  { "CURRENT",	13,		SI_CURRENT,	print_si_cb},  { "PERSISTENT",	11,		SI_PERSISTENT,	print_si_cb}, @@ -328,6 +352,11 @@ typedef struct intf_mask {  	uint64_t	mask;  } fmask_t; +typedef enum { +    IPMP_ADD_MEMBER, +    IPMP_REMOVE_MEMBER +} ipmp_action_t; +  /*   * Handle to libipadm. Opened in main() before the sub-command specific   * function is called and is closed before the program exits. @@ -349,6 +378,9 @@ static void	warn_ipadmerr(ipadm_status_t, const char *, ...);  static void	ipadm_check_propstr(const char *, boolean_t, const char *);  static void	process_misc_addrargs(int, char **, const char *, int *,  		    uint32_t *); +static void	do_action_ipmp(char *, ipadm_ipmp_members_t *, ipmp_action_t, +    uint32_t); +  static void  usage(int ret) @@ -419,19 +451,17 @@ main(int argc, char *argv[])  }  /* - * Create an IP interface for which no saved configuration exists in the - * persistent store. + * Create regular IP interface or IPMP group interface   */  static void -do_create_if(int argc, char *argv[], const char *use) +do_create_ip_common(int argc, char *argv[], const char *use, uint32_t flags)  {  	ipadm_status_t	status;  	int		option; -	uint32_t	flags = IPADM_OPT_PERSIST|IPADM_OPT_ACTIVE;  	opterr = 0; -	while ((option = getopt_long(argc, argv, ":t", if_longopts, -	    NULL)) != -1) { +	while ((option = getopt_long(argc, argv, +	    ":t", if_longopts, NULL)) != -1) {  		switch (option) {  		case 't':  			/* @@ -444,8 +474,12 @@ do_create_if(int argc, char *argv[], const char *use)  			die_opterr(optopt, option, use);  		}  	} -	if (optind != (argc - 1)) -		die("Usage: %s", use); +	if (optind != (argc - 1)) { +		if (use != NULL) +			die("usage: %s", use); +		else +			die(NULL); +	}  	status = ipadm_create_if(iph, argv[optind], AF_UNSPEC, flags);  	if (status != IPADM_SUCCESS) {  		die("Could not create %s : %s", @@ -454,6 +488,185 @@ do_create_if(int argc, char *argv[], const char *use)  }  /* + * Helpers to parse options into ipadm_ipmp_members_t list, and to free it. + */ +static ipadm_ipmp_members_t * +get_ipmp_members(int argc, char *argv[], const char *use, uint32_t *flags) +{ +	ipadm_ipmp_members_t *members = NULL; +	ipadm_ipmp_member_t *member; +	char *ifname; +	int option; + + +	opterr = 0; +	while ((option = getopt_long(argc, argv, ":i:", if_longopts, NULL)) != +	    -1) { +		switch (option) { +		case 't': +			*flags &= ~IPADM_OPT_PERSIST; +			break; +		case 'i': +			if (members == NULL) { +				members = calloc(1, +				    sizeof (ipadm_ipmp_members_t)); +				if (members == NULL) +					die("insufficient memory"); +				list_create(members, +				    sizeof (ipadm_ipmp_member_t), +				    offsetof(ipadm_ipmp_member_t, node)); +			} + +			for (ifname = strtok(optarg, ","); +			    ifname != NULL; +			    ifname = strtok(NULL, ",")) { +				if ((member = calloc(1, +				    sizeof (ipadm_ipmp_member_t))) == NULL) +					die("insufficient memory"); + +				if (strlcpy(member->if_name, ifname, +				    sizeof (member->if_name)) >= LIFNAMSIZ) +					die("Incorrect length of interface " +					    "name: %s", ifname); + +				list_insert_tail(members, member); +			} +			break; +		default: +			die_opterr(optopt, option, use); +		} +	} + +	if (optind != (argc - 1)) +		die("Usage: %s", use); + +	if (members != NULL && list_is_empty(members)) { +		free(members); +		members = NULL; +	} + +	return (members); +} + +static void +free_ipmp_members(ipadm_ipmp_members_t *members) +{ +	ipadm_ipmp_member_t *member; + +	while ((member = list_remove_head(members)) != NULL) +		free(member); + +	list_destroy(members); + +	free(members); +} + +/* + * Create an IPMP group interface for which no saved configuration + * exists in the persistent store. + */ +static void +do_create_ipmp(int argc, char *argv[], const char *use) +{ +	uint32_t flags = IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE | IPADM_OPT_IPMP; +	ipadm_ipmp_members_t *members = NULL; +	ipmp_handle_t ipmp_handle; +	int retval; + +	retval = ipmp_open(&ipmp_handle); +	if (retval != IPMP_SUCCESS) { +		die("Could not create IPMP handle: %s", +		    ipadm_status2str(retval)); +	} + +	retval = ipmp_ping_daemon(ipmp_handle); +	ipmp_close(ipmp_handle); + +	if (retval != IPMP_SUCCESS) { +		die("Cannot ping in.mpathd: %s", ipmp_errmsg(retval)); +	} + +	members = get_ipmp_members(argc, argv, use, &flags); + +	do_create_ip_common(argc, argv, use, flags); + +	if (members != NULL) { +		do_action_ipmp(argv[optind], members, IPMP_ADD_MEMBER, flags); +		free_ipmp_members(members); +	} +} + +static void +do_add_ipmp(int argc, char *argv[], const char *use) +{ +	uint32_t flags = IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE; +	ipadm_ipmp_members_t *members; + +	members = get_ipmp_members(argc, argv, use, &flags); + +	if (members == NULL) +		die_opterr(optopt, ':', use); + +	do_action_ipmp(argv[optind], members, IPMP_ADD_MEMBER, flags); +	free_ipmp_members(members); +} + +static void +do_remove_ipmp(int argc, char *argv[], const char *use) +{ +	uint32_t flags = IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE; +	ipadm_ipmp_members_t *members; + +	members = get_ipmp_members(argc, argv, use, &flags); + +	if (members == NULL) +		die_opterr(optopt, ':', use); + +	do_action_ipmp(argv[optind], members, IPMP_REMOVE_MEMBER, flags); +	free_ipmp_members(members); +} + +static void +do_action_ipmp(char *ipmp, ipadm_ipmp_members_t *members, ipmp_action_t action, +    uint32_t flags) +{ +	ipadm_status_t (*func)(ipadm_handle_t, const char *, const char *, +	    uint32_t); +	ipadm_status_t  status; +	ipadm_ipmp_member_t *member; +	char *ifname; +	const char *msg; + +	if (action == IPMP_ADD_MEMBER) { +		func = ipadm_add_ipmp_member; +		msg = "Cannot add interface '%s' to IPMP interface '%s': %s"; +	} else { +		func = ipadm_remove_ipmp_member; +		msg = "Cannot remove interface '%s' from IPMP interface '%s': " +		    "%s"; +	} + +	while ((member = list_remove_head(members)) != NULL) { +		ifname = member->if_name; + +		status = func(iph, ipmp, ifname, flags); +		if (status != IPADM_SUCCESS) +			die(msg, ifname, ipmp, ipadm_status2str(status)); +	} +} + +/* + * Create an IP interface for which no saved configuration exists in the + * persistent store. + */ +static void +do_create_ip(int argc, char *argv[], const char *use) +{ +	do_create_ip_common(argc, argv, use, +	    IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE); +} + +/*   * Enable an IP interface based on the persistent configuration for   * that interface.   */ @@ -480,7 +693,7 @@ do_enable_if(int argc, char *argv[], const char *use)   * Remove an IP interface from both active and persistent configuration.   */  static void -do_delete_if(int argc, char *argv[], const char *use) +do_delete_ip(int argc, char *argv[], const char *use)  {  	ipadm_status_t	status;  	uint32_t	flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST; @@ -687,7 +900,7 @@ do_show_ifprop(int argc, char **argv, const char *use)  	uint_t		proto;  	boolean_t	m_arg = _B_FALSE;  	char		*protostr; -	ipadm_if_info_list_t *ifinfo, *ifl; +	ipadm_if_info_t	*ifinfo, *ifp;  	ipadm_status_t	status;  	show_prop_state_t state; @@ -751,9 +964,8 @@ do_show_ifprop(int argc, char **argv, const char *use)  	if (status != IPADM_SUCCESS)  		die("Error retrieving interface(s): %s",  		    ipadm_status2str(status)); -	for (ifl = ifinfo; ifl != NULL; ifl = ifl->ifil_next) { -		(void) strlcpy(state.sps_ifname, ifl->ifil_ifi.ifi_name, -		    LIFNAMSIZ); +	for (ifp = ifinfo; ifp != NULL; ifp = ifp->ifi_next) { +		(void) strlcpy(state.sps_ifname, ifp->ifi_name, LIFNAMSIZ);  		state.sps_proto = proto;  		show_properties(&state, IPADMPROP_CLASS_IF);  	} @@ -1057,14 +1269,16 @@ die(const char *format, ...)  {  	va_list alist; -	format = gettext(format); -	(void) fprintf(stderr, "%s: ", progname); +	if (format != NULL) { +		format = gettext(format); +		(void) fprintf(stderr, "%s: ", progname); -	va_start(alist, format); -	(void) vfprintf(stderr, format, alist); -	va_end(alist); +		va_start(alist, format); +		(void) vfprintf(stderr, format, alist); +		va_end(alist); -	(void) putchar('\n'); +		(void) putchar('\n'); +	}  	ipadm_destroy_addrobj(ipaddr);  	ipadm_close(iph); @@ -1624,7 +1838,7 @@ flags2str(uint64_t flags, fmask_t *tbl, boolean_t is_bits,  static boolean_t  is_from_gz(const char *lifname)  { -	ipadm_if_info_list_t	*if_info; +	ipadm_if_info_t		*if_info;  	char			phyname[LIFNAMSIZ], *cp;  	boolean_t		ret = _B_FALSE;  	ipadm_status_t		status; @@ -1647,7 +1861,7 @@ is_from_gz(const char *lifname)  	if (status != IPADM_SUCCESS)  		return (ret); -	if (if_info->ifil_ifi.ifi_cflags & IFIF_L3PROTECT) +	if (if_info->ifi_cflags & IFIF_L3PROTECT)  		ret = _B_TRUE;  	ipadm_free_if_info(if_info);  	return (ret); @@ -1902,8 +2116,8 @@ static boolean_t  print_si_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)  {  	show_if_args_t		*arg = ofarg->ofmt_cbarg; -	ipadm_if_info_list_t	*ifinfo = arg->si_info; -	char			*ifname = ifinfo->ifil_ifi.ifi_name; +	ipadm_if_info_t		*ifinfo = arg->si_info; +	char			*ifname = ifinfo->ifi_name;  	fmask_t intf_state[] = {  		{ "ok",		IFIS_OK,	IPADM_ALL_BITS},  		{ "down",	IFIS_DOWN,	IPADM_ALL_BITS}, @@ -1933,22 +2147,33 @@ print_si_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)  		{ "6",	IFIF_IPV6,		IFIF_IPV6	},  		{ NULL,	0,			0		}  	}; +	fmask_t intf_class[] = { +		{ "IP",		IPADM_IF_CLASS_REGULAR, IPADM_ALL_BITS}, +		{ "IPMP",	IPADM_IF_CLASS_IPMP,    IPADM_ALL_BITS}, +		{ "VIRTUAL",	IPADM_IF_CLASS_VIRTUAL, IPADM_ALL_BITS}, +		{ "UNKNOWN",	IPADM_IF_CLASS_UNKNOWN, IPADM_ALL_BITS}, +		{ NULL,	0,	0} +	};  	buf[0] = '\0';  	switch (ofarg->ofmt_id) {  	case SI_IFNAME:  		(void) snprintf(buf, bufsize, "%s", ifname);  		break; +	case SI_IFCLASS: +		flags2str(ifinfo->ifi_class, intf_class, _B_FALSE, +		    buf, bufsize); +		break;  	case SI_STATE: -		flags2str(ifinfo->ifil_ifi.ifi_state, intf_state, _B_FALSE, +		flags2str(ifinfo->ifi_state, intf_state, _B_FALSE,  		    buf, bufsize);  		break;  	case SI_CURRENT: -		flags2str(ifinfo->ifil_ifi.ifi_cflags, intf_cflags, _B_TRUE, +		flags2str(ifinfo->ifi_cflags, intf_cflags, _B_TRUE,  		    buf, bufsize);  		break;  	case SI_PERSISTENT: -		flags2str(ifinfo->ifil_ifi.ifi_pflags, intf_pflags, _B_TRUE, +		flags2str(ifinfo->ifi_pflags, intf_pflags, _B_TRUE,  		    buf, bufsize);  		break;  	default: @@ -1969,7 +2194,7 @@ do_show_if(int argc, char *argv[], const char *use)  	ipadm_status_t		status;  	show_if_state_t		state;  	char			*fields_str = NULL; -	ipadm_if_info_list_t	*if_info, *ptr; +	ipadm_if_info_t		*if_info, *ptr;  	show_if_args_t		sargs;  	int			option;  	ofmt_handle_t		ofmt; @@ -2014,7 +2239,7 @@ do_show_if(int argc, char *argv[], const char *use)  		    ipadm_status2str(status));  	} -	for (ptr = if_info; ptr != NULL; ptr = ptr->ifil_next) { +	for (ptr = if_info; ptr != NULL; ptr = ptr->ifi_next) {  		sargs.si_info = ptr;  		ofmt_print(state.si_ofmt, &sargs);  	} diff --git a/usr/src/cmd/rcm_daemon/common/ip_rcm.c b/usr/src/cmd/rcm_daemon/common/ip_rcm.c index 7d2eeec9b7..3c86f2b868 100644 --- a/usr/src/cmd/rcm_daemon/common/ip_rcm.c +++ b/usr/src/cmd/rcm_daemon/common/ip_rcm.c @@ -20,7 +20,7 @@   */  /*   * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2021, Tintri by DDN. All rights reserved. + * Copyright 2021 Tintri by DDN, Inc. All rights reserved.   */  /* @@ -2374,7 +2374,7 @@ if_configure_ipadm(datalink_id_t linkid)  {  	char ifinst[MAXLINKNAMELEN];  	boolean_t found; -	ipadm_if_info_list_t *ifinfo, *ptr; +	ipadm_if_info_t *ifinfo, *ptr;  	ipadm_status_t status;  	assert(linkid != DATALINK_INVALID_LINKID); @@ -2399,8 +2399,8 @@ if_configure_ipadm(datalink_id_t linkid)  	}  	if (ifinfo != NULL) {  		found = B_FALSE; -		for (ptr = ifinfo; ptr != NULL; ptr = ptr->ifil_next) { -			if (strncmp(ptr->ifil_ifi.ifi_name, ifinst, +		for (ptr = ifinfo; ptr != NULL; ptr = ptr->ifi_next) { +			if (strncmp(ptr->ifi_name, ifinst,  			    sizeof (ifinst)) == 0) {  				found = B_TRUE;  				break; diff --git a/usr/src/cmd/svc/milestone/net-init b/usr/src/cmd/svc/milestone/net-init index ad2ff3d963..ea59624007 100644 --- a/usr/src/cmd/svc/milestone/net-init +++ b/usr/src/cmd/svc/milestone/net-init @@ -23,6 +23,8 @@  # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.  # Use is subject to license terms.  # +# Copyright 2021 Tintri by DDN, Inc. All rights reserved. +#  # This is the second phase of TCP/IP configuration.  The first part is  # run by the svc:/network/physical service and includes configuring the  # interfaces and setting the machine's hostname.  The svc:/network/initial @@ -38,8 +40,8 @@  #  # In a shared-IP zone we need this service to be up, but all of the work -# it tries to do is irrelevant (and will actually lead to the service  -# failing if we try to do it), so just bail out.  +# it tries to do is irrelevant (and will actually lead to the service +# failing if we try to do it), so just bail out.  # In the global zone and exclusive-IP zones we proceed.  #  smf_configure_ip || exit $SMF_EXIT_OK @@ -50,16 +52,6 @@ if [ -f /etc/inet/ipaddrsel.conf ]; then  fi  # -# If explicit IPMP groups are being used, in.mpathd will already be started. -# However, if TRACK_INTERFACES_ONLY_WITH_GROUPS=no and no explicit IPMP -# groups have been configured, then it still needs to be started.  So, fire -# it up in "adopt" mode; if there are no interfaces it needs to manage, it -# will automatically exit. -# -/usr/bin/pgrep -x -u 0 -z `smf_zonename` in.mpathd >/dev/null 2>&1 || \ -    /usr/lib/inet/in.mpathd -a - -#  # Set the RFC 1948 entropy, regardless of if I'm using it or not.  If present,  # use the encrypted root password as a source of entropy.  Otherwise,  # just use the pre-set (and hopefully difficult to guess) entropy that diff --git a/usr/src/cmd/svc/milestone/net-physical b/usr/src/cmd/svc/milestone/net-physical index 89784dcbbc..2d7d76d9b0 100644 --- a/usr/src/cmd/svc/milestone/net-physical +++ b/usr/src/cmd/svc/milestone/net-physical @@ -19,12 +19,13 @@  #  # CDDL HEADER END  # -# -# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. -# Copyright 2012 Milan Jurik. All rights reserved. +  #  # Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T.  # All rights reserved. +# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012 Milan Jurik. All rights reserved. +# Copyright 2021 Tintri by DDN, Inc. All rights reserved.  #  . /lib/svc/share/smf_include.sh @@ -32,8 +33,8 @@  #  # In a shared-IP zone we need this service to be up, but all of the work -# it tries to do is irrelevant (and will actually lead to the service  -# failing if we try to do it), so just bail out.  +# it tries to do is irrelevant (and will actually lead to the service +# failing if we try to do it), so just bail out.  # In the global zone and exclusive-IP zones we proceed.  #  smf_configure_ip || exit $SMF_EXIT_OK @@ -50,14 +51,14 @@ if smf_is_globalzone; then  	# Update PVID on interfaces configured with VLAN 1  	update_pvid -	#  +	#  	# Upgrade handling. The upgrade file consists of a series of dladm(1M)  	# commands. Note that after we are done, we cannot rename the upgrade  	# script file as the file system is still read-only at this point.  	# Defer this to the manifest-import service.  	#  	upgrade_script=/var/svc/profile/upgrade_datalink -	if [ -f "${upgrade_script}" ]; then  +	if [ -f "${upgrade_script}" ]; then  		. "${upgrade_script}"  	fi @@ -230,11 +231,11 @@ fi  if [ -n "$ipmp_list" ]; then  	set -- $ipmp_list  	while [ $# -gt 0 ]; do -	    	if /sbin/ifconfig $1 ipmp; then +		if /sbin/ifconfig $1 ipmp; then  			ipmp_created="$ipmp_created $1"  		else  			ipmp_failed="$ipmp_failed $1" -		fi	 +		fi  		shift  	done  	[ -n "$ipmp_failed" ] && warn_failed_ifs "create IPv4 IPMP" \ @@ -296,11 +297,11 @@ fi  if [ -n "$ipmp6_list" ]; then  	set -- $ipmp6_list  	while [ $# -gt 0 ]; do -	    	if /sbin/ifconfig $1 inet6 ipmp; then +		if /sbin/ifconfig $1 inet6 ipmp; then  			ipmp6_created="$ipmp6_created $1"  		else  			ipmp6_failed="$ipmp6_failed $1" - 		fi +		fi  		shift  	done  	[ -n "$ipmp6_failed" ] && warn_failed_ifs "create IPv6 IPMP" \ @@ -308,6 +309,21 @@ if [ -n "$ipmp6_list" ]; then  fi  # +# Upgrade ipadm.conf. +# +if /usr/bin/grep -q _family /etc/ipadm/ipadm.conf; then +	oldifs=$(/usr/bin/sed -En \ +	    's/^_ifname=([a-z0-9]+);_family=[0-9]+;$/\1/p' \ +	    /etc/ipadm/ipadm.conf | /usr/bin/sort -u) +	/usr/bin/sed -i '/_family/d' /etc/ipadm/ipadm.conf +	for oldif in $oldifs; do +		/usr/bin/printf \ +		    "_ifname=%s;_ifclass=0;_families=2,26;\n" \ +		    $oldif >> /etc/ipadm/ipadm.conf +	done +fi + +#  # Finally configure interfaces set up with ipadm. Any /etc/hostname*.intf  # files take precedence over ipadm defined configurations except when  # we are in a non-global zone and Layer-3 protection of IP addresses is @@ -333,7 +349,7 @@ for showif_output in `/sbin/ipadm show-if -p -o ifname,state,current`; do  			    "ignoring ipadm configuration" > /dev/msglog  			continue;  		else -			echo "Ignoring /etc/hostname*.$intf" > /dev/msglog  +			echo "Ignoring /etc/hostname*.$intf" > /dev/msglog  			/sbin/ifconfig $intf unplumb > /dev/null 2>&1  			/sbin/ifconfig $intf inet6 unplumb > /dev/null 2>&1  		fi @@ -524,7 +540,7 @@ fi  # Any non-loopback IPv4 interfaces with usable addresses up?  if [ -n "`/sbin/ifconfig -a4u`" ]; then -    	/sbin/ifconfig -a4u | while read intf addr rest; do +	/sbin/ifconfig -a4u | while read intf addr rest; do  		[ $intf = inet ] && [ $addr != 127.0.0.1 ] &&  		[ $addr != 0.0.0.0 ] && exit $SMF_EXIT_OK  	done && exit $SMF_EXIT_OK | 
