xref: /onnv-gate/usr/src/lib/libipadm/common/ipadm_persist.c (revision 13125:34b1540309cc)
112016SGirish.Moodalbail@Sun.COM /*
212016SGirish.Moodalbail@Sun.COM  * CDDL HEADER START
312016SGirish.Moodalbail@Sun.COM  *
412016SGirish.Moodalbail@Sun.COM  * The contents of this file are subject to the terms of the
512016SGirish.Moodalbail@Sun.COM  * Common Development and Distribution License (the "License").
612016SGirish.Moodalbail@Sun.COM  * You may not use this file except in compliance with the License.
712016SGirish.Moodalbail@Sun.COM  *
812016SGirish.Moodalbail@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
912016SGirish.Moodalbail@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1012016SGirish.Moodalbail@Sun.COM  * See the License for the specific language governing permissions
1112016SGirish.Moodalbail@Sun.COM  * and limitations under the License.
1212016SGirish.Moodalbail@Sun.COM  *
1312016SGirish.Moodalbail@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1412016SGirish.Moodalbail@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1512016SGirish.Moodalbail@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1612016SGirish.Moodalbail@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1712016SGirish.Moodalbail@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1812016SGirish.Moodalbail@Sun.COM  *
1912016SGirish.Moodalbail@Sun.COM  * CDDL HEADER END
2012016SGirish.Moodalbail@Sun.COM  */
2112016SGirish.Moodalbail@Sun.COM /*
2212297SVasumathi.Sundaram@oracle.COM  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2312016SGirish.Moodalbail@Sun.COM  */
2412016SGirish.Moodalbail@Sun.COM 
2512016SGirish.Moodalbail@Sun.COM /*
2612016SGirish.Moodalbail@Sun.COM  * This file contains routines to read/write formatted entries from/to
2712016SGirish.Moodalbail@Sun.COM  * libipadm data store /etc/ipadm/ipadm.conf. Each entry in the DB is a
2812016SGirish.Moodalbail@Sun.COM  * series of IPADM_NVPAIR_SEP separated (name, value) pairs, as shown
2912016SGirish.Moodalbail@Sun.COM  * below:
3012016SGirish.Moodalbail@Sun.COM  *		name=value[;...]
3112016SGirish.Moodalbail@Sun.COM  *
3212016SGirish.Moodalbail@Sun.COM  * The 'name' determines how to interpret 'value'. The supported names are:
3312016SGirish.Moodalbail@Sun.COM  *
3412016SGirish.Moodalbail@Sun.COM  *  IPADM_NVP_IPV6ADDR - value holds local and remote IPv6 addresses and when
3512016SGirish.Moodalbail@Sun.COM  *	       converted to nvlist, will contain nvpairs for local and remote
3612016SGirish.Moodalbail@Sun.COM  *	       addresses. These nvpairs are of type DATA_TYPE_STRING
3712016SGirish.Moodalbail@Sun.COM  *
3812016SGirish.Moodalbail@Sun.COM  *  IPADM_NVP_IPV4ADDR - value holds local and remote IPv4 addresses and when
3912016SGirish.Moodalbail@Sun.COM  *	       converted to nvlist, will contain nvpairs for local and remote
4012016SGirish.Moodalbail@Sun.COM  *	       addresses. These nvpairs are of type DATA_TYPE_STRING
4112016SGirish.Moodalbail@Sun.COM  *
4212016SGirish.Moodalbail@Sun.COM  *  IPADM_NVP_INTFID - value holds token, prefixlen, stateless and stateful
4312016SGirish.Moodalbail@Sun.COM  *	       info and when converted to nvlist, will contain following nvpairs
4412016SGirish.Moodalbail@Sun.COM  *			interface_id: DATA_TYPE_UINT8_ARRAY
4512016SGirish.Moodalbail@Sun.COM  *			prefixlen: DATA_TYPE_UINT32
4612016SGirish.Moodalbail@Sun.COM  *			stateless: DATA_TYPE_STRING
4712016SGirish.Moodalbail@Sun.COM  *			stateful: DATA_TYPE_STRING
4812016SGirish.Moodalbail@Sun.COM  *
4912016SGirish.Moodalbail@Sun.COM  *  IPADM_NVP_DHCP - value holds wait time and primary info and when converted
5012016SGirish.Moodalbail@Sun.COM  *	       to nvlist, will contain following nvpairs
5112016SGirish.Moodalbail@Sun.COM  *			wait:	DATA_TYPE_INT32
5212016SGirish.Moodalbail@Sun.COM  *			primary: DATA_TYPE_BOOLEAN
5312016SGirish.Moodalbail@Sun.COM  *
5412016SGirish.Moodalbail@Sun.COM  *  default  - value is a single entity and when converted to nvlist, will
5512016SGirish.Moodalbail@Sun.COM  *	       contain nvpair of type DATA_TYPE_STRING. nvpairs private to
5612016SGirish.Moodalbail@Sun.COM  *	       ipadm are of this type. Further the property name and property
5712016SGirish.Moodalbail@Sun.COM  *	       values are stored as nvpairs of this type.
5812016SGirish.Moodalbail@Sun.COM  *
5912016SGirish.Moodalbail@Sun.COM  * The syntax for each line is described above the respective functions below.
6012016SGirish.Moodalbail@Sun.COM  */
6112016SGirish.Moodalbail@Sun.COM 
6212016SGirish.Moodalbail@Sun.COM #include <stdlib.h>
6312016SGirish.Moodalbail@Sun.COM #include <strings.h>
6412016SGirish.Moodalbail@Sun.COM #include <errno.h>
6512016SGirish.Moodalbail@Sun.COM #include <ctype.h>
6612016SGirish.Moodalbail@Sun.COM #include <sys/types.h>
6712016SGirish.Moodalbail@Sun.COM #include <sys/stat.h>
6812016SGirish.Moodalbail@Sun.COM #include <sys/dld.h>
6912016SGirish.Moodalbail@Sun.COM #include <fcntl.h>
7012016SGirish.Moodalbail@Sun.COM #include <dirent.h>
7112016SGirish.Moodalbail@Sun.COM #include <unistd.h>
7212016SGirish.Moodalbail@Sun.COM #include <assert.h>
7312016SGirish.Moodalbail@Sun.COM #include <sys/socket.h>
7412016SGirish.Moodalbail@Sun.COM #include <netinet/in.h>
7512016SGirish.Moodalbail@Sun.COM #include <arpa/inet.h>
7612016SGirish.Moodalbail@Sun.COM #include <sys/sockio.h>
7712016SGirish.Moodalbail@Sun.COM #include "libipadm_impl.h"
7812016SGirish.Moodalbail@Sun.COM 
7912016SGirish.Moodalbail@Sun.COM #define	MAXLINELEN		1024
8012016SGirish.Moodalbail@Sun.COM #define	IPADM_NVPAIR_SEP	";"
8112016SGirish.Moodalbail@Sun.COM #define	IPADM_NAME_SEP		","
8212016SGirish.Moodalbail@Sun.COM 
8312016SGirish.Moodalbail@Sun.COM static char ipadm_rootdir[MAXPATHLEN] = "/";
8412016SGirish.Moodalbail@Sun.COM 
8512016SGirish.Moodalbail@Sun.COM static int ipadm_process_db_line(db_wfunc_t *, void *, FILE *fp, FILE *nfp,
8612016SGirish.Moodalbail@Sun.COM     ipadm_db_op_t);
8712016SGirish.Moodalbail@Sun.COM 
8812016SGirish.Moodalbail@Sun.COM /*
8912016SGirish.Moodalbail@Sun.COM  * convert nvpair to a "name=value" string for writing to the DB.
9012016SGirish.Moodalbail@Sun.COM  */
9112016SGirish.Moodalbail@Sun.COM typedef size_t  ipadm_wfunc_t(nvpair_t *, char *, size_t);
9212016SGirish.Moodalbail@Sun.COM 
9312016SGirish.Moodalbail@Sun.COM /*
9412016SGirish.Moodalbail@Sun.COM  * ipadm_rfunc_t takes (`name', `value') and adds the appropriately typed
9512016SGirish.Moodalbail@Sun.COM  * nvpair to the nvlist.
9612016SGirish.Moodalbail@Sun.COM  */
9712016SGirish.Moodalbail@Sun.COM typedef void  ipadm_rfunc_t(nvlist_t *, char *name, char *value);
9812016SGirish.Moodalbail@Sun.COM 
9912016SGirish.Moodalbail@Sun.COM static ipadm_rfunc_t	i_ipadm_str_dbline2nvl, i_ipadm_ip4_dbline2nvl,
10012016SGirish.Moodalbail@Sun.COM 			i_ipadm_ip6_dbline2nvl, i_ipadm_intfid_dbline2nvl,
10112016SGirish.Moodalbail@Sun.COM 			i_ipadm_dhcp_dbline2nvl;
10212016SGirish.Moodalbail@Sun.COM 
10312016SGirish.Moodalbail@Sun.COM static ipadm_wfunc_t	i_ipadm_str_nvp2dbline, i_ipadm_ip4_nvp2dbline,
10412016SGirish.Moodalbail@Sun.COM 			i_ipadm_ip6_nvp2dbline, i_ipadm_intfid_nvp2dbline,
10512016SGirish.Moodalbail@Sun.COM 			i_ipadm_dhcp_nvp2dbline;
10612016SGirish.Moodalbail@Sun.COM 
10712016SGirish.Moodalbail@Sun.COM /*
10812016SGirish.Moodalbail@Sun.COM  * table of function pointers to read/write formatted entries from/to
10912016SGirish.Moodalbail@Sun.COM  * ipadm.conf.
11012016SGirish.Moodalbail@Sun.COM  */
11112016SGirish.Moodalbail@Sun.COM typedef struct ipadm_conf_ent_s {
11212016SGirish.Moodalbail@Sun.COM 	const char		*ipent_type_name;
11312016SGirish.Moodalbail@Sun.COM 	ipadm_wfunc_t		*ipent_wfunc;
11412016SGirish.Moodalbail@Sun.COM 	ipadm_rfunc_t		*ipent_rfunc;
11512016SGirish.Moodalbail@Sun.COM } ipadm_conf_ent_t;
11612016SGirish.Moodalbail@Sun.COM 
11712016SGirish.Moodalbail@Sun.COM static ipadm_conf_ent_t ipadm_conf_ent[] = {
11812016SGirish.Moodalbail@Sun.COM 	{ IPADM_NVP_IPV6ADDR, i_ipadm_ip6_nvp2dbline, i_ipadm_ip6_dbline2nvl },
11912016SGirish.Moodalbail@Sun.COM 	{ IPADM_NVP_IPV4ADDR, i_ipadm_ip4_nvp2dbline, i_ipadm_ip4_dbline2nvl },
12012016SGirish.Moodalbail@Sun.COM 	{ IPADM_NVP_INTFID, i_ipadm_intfid_nvp2dbline,
12112016SGirish.Moodalbail@Sun.COM 	    i_ipadm_intfid_dbline2nvl },
12212016SGirish.Moodalbail@Sun.COM 	{ IPADM_NVP_DHCP, i_ipadm_dhcp_nvp2dbline, i_ipadm_dhcp_dbline2nvl },
12312016SGirish.Moodalbail@Sun.COM 	{ NULL,	i_ipadm_str_nvp2dbline,	i_ipadm_str_dbline2nvl }
12412016SGirish.Moodalbail@Sun.COM };
12512016SGirish.Moodalbail@Sun.COM 
12612016SGirish.Moodalbail@Sun.COM static ipadm_conf_ent_t *
i_ipadm_find_conf_type(const char * type)12712016SGirish.Moodalbail@Sun.COM i_ipadm_find_conf_type(const char *type)
12812016SGirish.Moodalbail@Sun.COM {
12912016SGirish.Moodalbail@Sun.COM 	int	i;
13012016SGirish.Moodalbail@Sun.COM 
13112016SGirish.Moodalbail@Sun.COM 	for (i = 0; ipadm_conf_ent[i].ipent_type_name != NULL; i++)
13212016SGirish.Moodalbail@Sun.COM 		if (strcmp(type, ipadm_conf_ent[i].ipent_type_name) == 0)
13312016SGirish.Moodalbail@Sun.COM 			break;
13412016SGirish.Moodalbail@Sun.COM 	return (&ipadm_conf_ent[i]);
13512016SGirish.Moodalbail@Sun.COM }
13612016SGirish.Moodalbail@Sun.COM 
13712016SGirish.Moodalbail@Sun.COM /*
13812016SGirish.Moodalbail@Sun.COM  * Extracts the hostnames IPADM_NVP_IPADDRHNAME and IPADM_NVP_IPDADDRHNAME from
13912016SGirish.Moodalbail@Sun.COM  * the given nvlist `nvl' and adds the strings to `buf'.
14012016SGirish.Moodalbail@Sun.COM  */
14112016SGirish.Moodalbail@Sun.COM size_t
i_ipadm_ip_addhostname2dbline(nvlist_t * nvl,char * buf,size_t buflen)14212016SGirish.Moodalbail@Sun.COM i_ipadm_ip_addhostname2dbline(nvlist_t *nvl, char *buf, size_t buflen)
14312016SGirish.Moodalbail@Sun.COM {
14412016SGirish.Moodalbail@Sun.COM 	char	*cp;
14512016SGirish.Moodalbail@Sun.COM 	char	tmpbuf[IPADM_STRSIZE];
14612016SGirish.Moodalbail@Sun.COM 
14712016SGirish.Moodalbail@Sun.COM 	/* Add the local hostname */
14812016SGirish.Moodalbail@Sun.COM 	if (nvlist_lookup_string(nvl, IPADM_NVP_IPADDRHNAME, &cp) != 0)
14912016SGirish.Moodalbail@Sun.COM 		return (0);
15012016SGirish.Moodalbail@Sun.COM 	(void) strlcat(buf, cp, buflen); /* local hostname */
15112016SGirish.Moodalbail@Sun.COM 
15212016SGirish.Moodalbail@Sun.COM 	/* Add the dst hostname */
15312016SGirish.Moodalbail@Sun.COM 	if (nvlist_lookup_string(nvl, IPADM_NVP_IPDADDRHNAME, &cp) != 0) {
15412016SGirish.Moodalbail@Sun.COM 		/* no dst addr. just add a NULL character */
15512016SGirish.Moodalbail@Sun.COM 		(void) snprintf(tmpbuf, sizeof (tmpbuf), ",");
15612016SGirish.Moodalbail@Sun.COM 	} else {
15712016SGirish.Moodalbail@Sun.COM 		(void) snprintf(tmpbuf, sizeof (tmpbuf), ",%s", cp);
15812016SGirish.Moodalbail@Sun.COM 	}
15912016SGirish.Moodalbail@Sun.COM 	return (strlcat(buf, tmpbuf, buflen));
16012016SGirish.Moodalbail@Sun.COM }
16112016SGirish.Moodalbail@Sun.COM 
16212016SGirish.Moodalbail@Sun.COM /*
16312016SGirish.Moodalbail@Sun.COM  * Converts IPADM_NVP_IPV4ADDR nvpair to a string representation for writing to
16412016SGirish.Moodalbail@Sun.COM  * the DB. The converted string format:
16512016SGirish.Moodalbail@Sun.COM  *	ipv4addr=<local numeric IP string or hostname,remote numeric IP
16612016SGirish.Moodalbail@Sun.COM  *          string or hostname>
16712016SGirish.Moodalbail@Sun.COM  */
16812016SGirish.Moodalbail@Sun.COM static size_t
i_ipadm_ip4_nvp2dbline(nvpair_t * nvp,char * buf,size_t buflen)16912016SGirish.Moodalbail@Sun.COM i_ipadm_ip4_nvp2dbline(nvpair_t *nvp, char *buf, size_t buflen)
17012016SGirish.Moodalbail@Sun.COM {
17112016SGirish.Moodalbail@Sun.COM 	nvlist_t	*v;
17212016SGirish.Moodalbail@Sun.COM 	int		nbytes;
17312016SGirish.Moodalbail@Sun.COM 
17412016SGirish.Moodalbail@Sun.COM 	assert(nvpair_type(nvp) == DATA_TYPE_NVLIST &&
17512016SGirish.Moodalbail@Sun.COM 	    strcmp(nvpair_name(nvp), IPADM_NVP_IPV4ADDR) == 0);
17612016SGirish.Moodalbail@Sun.COM 
17712016SGirish.Moodalbail@Sun.COM 	(void) snprintf(buf, buflen, "%s=", IPADM_NVP_IPV4ADDR);
17812016SGirish.Moodalbail@Sun.COM 	if (nvpair_value_nvlist(nvp, &v) != 0)
17912016SGirish.Moodalbail@Sun.COM 		goto fail;
18012016SGirish.Moodalbail@Sun.COM 	nbytes = i_ipadm_ip_addhostname2dbline(v, buf, buflen);
18112016SGirish.Moodalbail@Sun.COM 	if (nbytes != 0)
18212016SGirish.Moodalbail@Sun.COM 		return (nbytes);
18312016SGirish.Moodalbail@Sun.COM fail:
18412016SGirish.Moodalbail@Sun.COM 	buf[0] = '\0';
18512016SGirish.Moodalbail@Sun.COM 	return (0);
18612016SGirish.Moodalbail@Sun.COM }
18712016SGirish.Moodalbail@Sun.COM 
18812016SGirish.Moodalbail@Sun.COM /*
18912016SGirish.Moodalbail@Sun.COM  * Converts IPADM_NVP_IPV6ADDR nvpair to a string representation for writing to
19012016SGirish.Moodalbail@Sun.COM  * the DB. The converted string format:
19112016SGirish.Moodalbail@Sun.COM  *	ipv6addr=<local numeric IP string or hostname,remote numeric IP
19212016SGirish.Moodalbail@Sun.COM  *          string or hostname>
19312016SGirish.Moodalbail@Sun.COM  */
19412016SGirish.Moodalbail@Sun.COM static size_t
i_ipadm_ip6_nvp2dbline(nvpair_t * nvp,char * buf,size_t buflen)19512016SGirish.Moodalbail@Sun.COM i_ipadm_ip6_nvp2dbline(nvpair_t *nvp, char *buf, size_t buflen)
19612016SGirish.Moodalbail@Sun.COM {
19712016SGirish.Moodalbail@Sun.COM 	nvlist_t	*v;
19812016SGirish.Moodalbail@Sun.COM 	int		nbytes;
19912016SGirish.Moodalbail@Sun.COM 
20012016SGirish.Moodalbail@Sun.COM 	assert(nvpair_type(nvp) == DATA_TYPE_NVLIST &&
20112016SGirish.Moodalbail@Sun.COM 	    strcmp(nvpair_name(nvp), IPADM_NVP_IPV6ADDR) == 0);
20212016SGirish.Moodalbail@Sun.COM 
20312016SGirish.Moodalbail@Sun.COM 	(void) snprintf(buf, buflen, "%s=", IPADM_NVP_IPV6ADDR);
20412016SGirish.Moodalbail@Sun.COM 	if (nvpair_value_nvlist(nvp, &v) != 0)
20512016SGirish.Moodalbail@Sun.COM 		goto fail;
20612016SGirish.Moodalbail@Sun.COM 	nbytes = i_ipadm_ip_addhostname2dbline(v, buf, buflen);
20712016SGirish.Moodalbail@Sun.COM 	if (nbytes != 0)
20812016SGirish.Moodalbail@Sun.COM 		return (nbytes);
20912016SGirish.Moodalbail@Sun.COM fail:
21012016SGirish.Moodalbail@Sun.COM 	buf[0] = '\0';
21112016SGirish.Moodalbail@Sun.COM 	return (0);
21212016SGirish.Moodalbail@Sun.COM }
21312016SGirish.Moodalbail@Sun.COM 
21412016SGirish.Moodalbail@Sun.COM /*
21512016SGirish.Moodalbail@Sun.COM  * Converts IPADM_NVP_INTFID nvpair to a string representation for writing to
21612016SGirish.Moodalbail@Sun.COM  * the DB. The converted string format:
21712016SGirish.Moodalbail@Sun.COM  *	IPADM_NVP_INTFID=<intfid/prefixlen>,{yes|no},{yes|no}
21812016SGirish.Moodalbail@Sun.COM  */
21912016SGirish.Moodalbail@Sun.COM static size_t
i_ipadm_intfid_nvp2dbline(nvpair_t * nvp,char * buf,size_t buflen)22012016SGirish.Moodalbail@Sun.COM i_ipadm_intfid_nvp2dbline(nvpair_t *nvp, char *buf, size_t buflen)
22112016SGirish.Moodalbail@Sun.COM {
22212016SGirish.Moodalbail@Sun.COM 	char		addrbuf[IPADM_STRSIZE];
22312016SGirish.Moodalbail@Sun.COM 	nvlist_t	*v;
22412016SGirish.Moodalbail@Sun.COM 	uint32_t	prefixlen;
22512016SGirish.Moodalbail@Sun.COM 	struct in6_addr	in6addr;
22612016SGirish.Moodalbail@Sun.COM 	char		*stateless;
22712016SGirish.Moodalbail@Sun.COM 	char		*stateful;
22812016SGirish.Moodalbail@Sun.COM 
22912016SGirish.Moodalbail@Sun.COM 	assert(nvpair_type(nvp) == DATA_TYPE_NVLIST &&
23012016SGirish.Moodalbail@Sun.COM 	    strcmp(nvpair_name(nvp), IPADM_NVP_INTFID) == 0);
23112016SGirish.Moodalbail@Sun.COM 
23212016SGirish.Moodalbail@Sun.COM 	(void) snprintf(buf, buflen, "%s=", IPADM_NVP_INTFID);
23312016SGirish.Moodalbail@Sun.COM 	if (nvpair_value_nvlist(nvp, &v) != 0)
23412016SGirish.Moodalbail@Sun.COM 		goto fail;
23512016SGirish.Moodalbail@Sun.COM 	if (i_ipadm_nvl2in6_addr(v, IPADM_NVP_IPNUMADDR, &in6addr) !=
23612016SGirish.Moodalbail@Sun.COM 	    IPADM_SUCCESS)
23712016SGirish.Moodalbail@Sun.COM 		goto fail;
23812016SGirish.Moodalbail@Sun.COM 	(void) inet_ntop(AF_INET6, &in6addr, addrbuf,
23912016SGirish.Moodalbail@Sun.COM 	    sizeof (addrbuf));
24012016SGirish.Moodalbail@Sun.COM 	(void) strlcat(buf, addrbuf, buflen);
24112016SGirish.Moodalbail@Sun.COM 	if (nvlist_lookup_uint32(v, IPADM_NVP_PREFIXLEN, &prefixlen) != 0 ||
24212016SGirish.Moodalbail@Sun.COM 	    nvlist_lookup_string(v, IPADM_NVP_STATELESS, &stateless) != 0 ||
24312016SGirish.Moodalbail@Sun.COM 	    nvlist_lookup_string(v, IPADM_NVP_STATEFUL, &stateful) != 0)
24412016SGirish.Moodalbail@Sun.COM 		goto fail;
24512016SGirish.Moodalbail@Sun.COM 	(void) snprintf(addrbuf, sizeof (addrbuf), "/%d,%s,%s",
24612016SGirish.Moodalbail@Sun.COM 	    prefixlen, stateless, stateful);
24712016SGirish.Moodalbail@Sun.COM 	return (strlcat(buf, addrbuf, buflen));
24812016SGirish.Moodalbail@Sun.COM fail:
24912016SGirish.Moodalbail@Sun.COM 	buf[0] = '\0';
25012016SGirish.Moodalbail@Sun.COM 	return (0);
25112016SGirish.Moodalbail@Sun.COM }
25212016SGirish.Moodalbail@Sun.COM 
25312016SGirish.Moodalbail@Sun.COM /*
25412016SGirish.Moodalbail@Sun.COM  * Converts IPADM_NVP_DHCP nvpair to a string representation for writing to the
25512016SGirish.Moodalbail@Sun.COM  * DB. The converted string format:
25612016SGirish.Moodalbail@Sun.COM  *	IPADM_NVP_DHCP=<wait_time>,{yes|no}
25712016SGirish.Moodalbail@Sun.COM  */
25812016SGirish.Moodalbail@Sun.COM static size_t
i_ipadm_dhcp_nvp2dbline(nvpair_t * nvp,char * buf,size_t buflen)25912016SGirish.Moodalbail@Sun.COM i_ipadm_dhcp_nvp2dbline(nvpair_t *nvp, char *buf, size_t buflen)
26012016SGirish.Moodalbail@Sun.COM {
26112016SGirish.Moodalbail@Sun.COM 	char		addrbuf[IPADM_STRSIZE];
26212016SGirish.Moodalbail@Sun.COM 	int32_t 	wait;
26312016SGirish.Moodalbail@Sun.COM 	boolean_t	primary;
26412016SGirish.Moodalbail@Sun.COM 	nvlist_t	*v;
26512016SGirish.Moodalbail@Sun.COM 
26612016SGirish.Moodalbail@Sun.COM 	assert(nvpair_type(nvp) == DATA_TYPE_NVLIST &&
26712016SGirish.Moodalbail@Sun.COM 	    strcmp(nvpair_name(nvp), IPADM_NVP_DHCP) == 0);
26812016SGirish.Moodalbail@Sun.COM 
26912016SGirish.Moodalbail@Sun.COM 	if (nvpair_value_nvlist(nvp, &v) != 0 ||
27012016SGirish.Moodalbail@Sun.COM 	    nvlist_lookup_int32(v, IPADM_NVP_WAIT, &wait) != 0 ||
27112016SGirish.Moodalbail@Sun.COM 	    nvlist_lookup_boolean_value(v, IPADM_NVP_PRIMARY, &primary) != 0) {
27212016SGirish.Moodalbail@Sun.COM 		return (0);
27312016SGirish.Moodalbail@Sun.COM 	}
27412016SGirish.Moodalbail@Sun.COM 	(void) snprintf(buf, buflen, "%s=", IPADM_NVP_DHCP);
27512016SGirish.Moodalbail@Sun.COM 	(void) snprintf(addrbuf, sizeof (addrbuf), "%d,%s", wait,
27612016SGirish.Moodalbail@Sun.COM 	    (primary ? "yes" : "no"));
27712016SGirish.Moodalbail@Sun.COM 	return (strlcat(buf, addrbuf, buflen));
27812016SGirish.Moodalbail@Sun.COM }
27912016SGirish.Moodalbail@Sun.COM 
28012016SGirish.Moodalbail@Sun.COM /*
28112016SGirish.Moodalbail@Sun.COM  * Constructs a "<name>=<value>" string from the nvpair, whose type must
28212016SGirish.Moodalbail@Sun.COM  * be STRING.
28312016SGirish.Moodalbail@Sun.COM  */
28412016SGirish.Moodalbail@Sun.COM static size_t
i_ipadm_str_nvp2dbline(nvpair_t * nvp,char * buf,size_t buflen)28512016SGirish.Moodalbail@Sun.COM i_ipadm_str_nvp2dbline(nvpair_t *nvp, char *buf, size_t buflen)
28612016SGirish.Moodalbail@Sun.COM {
28712016SGirish.Moodalbail@Sun.COM 	char	*str = NULL;
28812016SGirish.Moodalbail@Sun.COM 
28912016SGirish.Moodalbail@Sun.COM 	assert(nvpair_type(nvp) == DATA_TYPE_STRING);
29012016SGirish.Moodalbail@Sun.COM 	if (nvpair_value_string(nvp, &str) != 0)
29112016SGirish.Moodalbail@Sun.COM 		return (0);
29212016SGirish.Moodalbail@Sun.COM 	return (snprintf(buf, buflen, "%s=%s", nvpair_name(nvp), str));
29312016SGirish.Moodalbail@Sun.COM }
29412016SGirish.Moodalbail@Sun.COM 
29512016SGirish.Moodalbail@Sun.COM /*
29612016SGirish.Moodalbail@Sun.COM  * Converts a nvlist to string of the form:
29712016SGirish.Moodalbail@Sun.COM  *  <prop0>=<val0>,...,<valn>;...;<propn>=<val0>,...,<valn>;
29812016SGirish.Moodalbail@Sun.COM  */
29912016SGirish.Moodalbail@Sun.COM size_t
ipadm_nvlist2str(nvlist_t * nvl,char * buf,size_t buflen)30012016SGirish.Moodalbail@Sun.COM ipadm_nvlist2str(nvlist_t *nvl, char *buf, size_t buflen)
30112016SGirish.Moodalbail@Sun.COM {
30212016SGirish.Moodalbail@Sun.COM 	nvpair_t	*nvp = NULL;
30312016SGirish.Moodalbail@Sun.COM 	uint_t		nbytes = 0, tbytes = 0;
30412016SGirish.Moodalbail@Sun.COM 	ipadm_conf_ent_t *ipent;
30512016SGirish.Moodalbail@Sun.COM 	size_t		bufsize = buflen;
30612016SGirish.Moodalbail@Sun.COM 
30712016SGirish.Moodalbail@Sun.COM 	for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
30812016SGirish.Moodalbail@Sun.COM 	    nvp = nvlist_next_nvpair(nvl, nvp)) {
30912016SGirish.Moodalbail@Sun.COM 		ipent = i_ipadm_find_conf_type(nvpair_name(nvp));
31012016SGirish.Moodalbail@Sun.COM 		nbytes = (*ipent->ipent_wfunc)(nvp, buf, buflen);
31112016SGirish.Moodalbail@Sun.COM 		/* add nvpair separator */
31212016SGirish.Moodalbail@Sun.COM 		nbytes += snprintf(buf + nbytes, buflen - nbytes, "%s",
31312016SGirish.Moodalbail@Sun.COM 		    IPADM_NVPAIR_SEP);
31412016SGirish.Moodalbail@Sun.COM 		buflen -= nbytes;
31512016SGirish.Moodalbail@Sun.COM 		buf += nbytes;
31612016SGirish.Moodalbail@Sun.COM 		tbytes += nbytes;
31712016SGirish.Moodalbail@Sun.COM 		if (tbytes >= bufsize)	/* buffer overflow */
31812016SGirish.Moodalbail@Sun.COM 			return (0);
31912016SGirish.Moodalbail@Sun.COM 	}
32012016SGirish.Moodalbail@Sun.COM 	nbytes = snprintf(buf, buflen, "%c%c", '\n', '\0');
32112016SGirish.Moodalbail@Sun.COM 	tbytes += nbytes;
32212016SGirish.Moodalbail@Sun.COM 	if (tbytes >= bufsize)
32312016SGirish.Moodalbail@Sun.COM 		return (0);
32412016SGirish.Moodalbail@Sun.COM 	return (tbytes);
32512016SGirish.Moodalbail@Sun.COM }
32612016SGirish.Moodalbail@Sun.COM 
32712016SGirish.Moodalbail@Sun.COM /*
32812016SGirish.Moodalbail@Sun.COM  * Adds a nvpair, using the `name' and `value', to the nvlist in `nvl'.
32912016SGirish.Moodalbail@Sun.COM  * The value will be interpreted as explained at the top of this file.
33012016SGirish.Moodalbail@Sun.COM  */
33112016SGirish.Moodalbail@Sun.COM static void
i_ipadm_add_nvpair(nvlist_t * nvl,char * name,char * value)33212016SGirish.Moodalbail@Sun.COM i_ipadm_add_nvpair(nvlist_t *nvl, char *name, char *value)
33312016SGirish.Moodalbail@Sun.COM {
33412016SGirish.Moodalbail@Sun.COM 	ipadm_conf_ent_t	*ipent;
33512016SGirish.Moodalbail@Sun.COM 
33612016SGirish.Moodalbail@Sun.COM 	ipent = i_ipadm_find_conf_type(name);
33712016SGirish.Moodalbail@Sun.COM 	(*ipent->ipent_rfunc)(nvl, name, value);
33812016SGirish.Moodalbail@Sun.COM }
33912016SGirish.Moodalbail@Sun.COM 
34012016SGirish.Moodalbail@Sun.COM /*
34112016SGirish.Moodalbail@Sun.COM  * Adds an nvpair for IPv4 addr to the nvlist. The "name" is the string in
34212016SGirish.Moodalbail@Sun.COM  * IPADM_NVP_IPV4ADDR. The "value" for IPADM_NVP_IPV4ADDR is another nvlist.
34312016SGirish.Moodalbail@Sun.COM  * Allocate the value nvlist for IPADM_NVP_IPV4ADDR if necessary, and add
34412016SGirish.Moodalbail@Sun.COM  * the address and hostnames from the address object `ipaddr' to it.
34512016SGirish.Moodalbail@Sun.COM  * Then add the allocated nvlist to `nvl'.
34612016SGirish.Moodalbail@Sun.COM  */
34712016SGirish.Moodalbail@Sun.COM ipadm_status_t
i_ipadm_add_ipaddr2nvl(nvlist_t * nvl,ipadm_addrobj_t ipaddr)34812016SGirish.Moodalbail@Sun.COM i_ipadm_add_ipaddr2nvl(nvlist_t *nvl, ipadm_addrobj_t ipaddr)
34912016SGirish.Moodalbail@Sun.COM {
35012016SGirish.Moodalbail@Sun.COM 	nvlist_t		*nvl_addr = NULL;
35112016SGirish.Moodalbail@Sun.COM 	int			err;
35212016SGirish.Moodalbail@Sun.COM 	char			*name;
35312016SGirish.Moodalbail@Sun.COM 	sa_family_t		af = ipaddr->ipadm_af;
35412016SGirish.Moodalbail@Sun.COM 
35512016SGirish.Moodalbail@Sun.COM 	if (af == AF_INET) {
35612016SGirish.Moodalbail@Sun.COM 		name = IPADM_NVP_IPV4ADDR;
35712016SGirish.Moodalbail@Sun.COM 	} else {
35812016SGirish.Moodalbail@Sun.COM 		assert(af == AF_INET6);
35912016SGirish.Moodalbail@Sun.COM 		name = IPADM_NVP_IPV6ADDR;
36012016SGirish.Moodalbail@Sun.COM 	}
36112016SGirish.Moodalbail@Sun.COM 
36212016SGirish.Moodalbail@Sun.COM 	if (!nvlist_exists(nvl, name)) {
36312016SGirish.Moodalbail@Sun.COM 		if ((err = nvlist_alloc(&nvl_addr, NV_UNIQUE_NAME, 0)) != 0)
36412016SGirish.Moodalbail@Sun.COM 			return (ipadm_errno2status(err));
36512016SGirish.Moodalbail@Sun.COM 		if ((err = nvlist_add_nvlist(nvl, name, nvl_addr)) != 0) {
36612016SGirish.Moodalbail@Sun.COM 			nvlist_free(nvl_addr);
36712016SGirish.Moodalbail@Sun.COM 			return (ipadm_errno2status(err));
36812016SGirish.Moodalbail@Sun.COM 		}
36912016SGirish.Moodalbail@Sun.COM 		nvlist_free(nvl_addr);
37012016SGirish.Moodalbail@Sun.COM 	}
37112016SGirish.Moodalbail@Sun.COM 	if ((err = nvlist_lookup_nvlist(nvl, name, &nvl_addr)) != 0 ||
37212016SGirish.Moodalbail@Sun.COM 	    (err = nvlist_add_string(nvl_addr, IPADM_NVP_IPADDRHNAME,
37312016SGirish.Moodalbail@Sun.COM 	    ipaddr->ipadm_static_aname)) != 0)
37412016SGirish.Moodalbail@Sun.COM 		return (ipadm_errno2status(err));
37512297SVasumathi.Sundaram@oracle.COM 	if (ipaddr->ipadm_static_dname[0] != '\0') {
37612016SGirish.Moodalbail@Sun.COM 		if ((err = nvlist_add_string(nvl_addr, IPADM_NVP_IPDADDRHNAME,
37712016SGirish.Moodalbail@Sun.COM 		    ipaddr->ipadm_static_dname)) != 0)
37812016SGirish.Moodalbail@Sun.COM 			return (ipadm_errno2status(err));
37912016SGirish.Moodalbail@Sun.COM 	}
38012016SGirish.Moodalbail@Sun.COM 
38112016SGirish.Moodalbail@Sun.COM 	return (IPADM_SUCCESS);
38212016SGirish.Moodalbail@Sun.COM }
38312016SGirish.Moodalbail@Sun.COM 
38412016SGirish.Moodalbail@Sun.COM /*
38512016SGirish.Moodalbail@Sun.COM  * Adds an nvpair for IPv6 interface id to the nvlist. The "name" is
38612016SGirish.Moodalbail@Sun.COM  * the string in IPADM_NVP_INTFID. The "value" for IPADM_NVP_INTFID is another
38712016SGirish.Moodalbail@Sun.COM  * nvlist. Allocate the value nvlist for IPADM_NVP_INTFID if necessary, and add
38812016SGirish.Moodalbail@Sun.COM  * the interface id and its prefixlen from the address object `ipaddr' to it.
38912016SGirish.Moodalbail@Sun.COM  * Then add the allocated nvlist to `nvl'.
39012016SGirish.Moodalbail@Sun.COM  */
39112016SGirish.Moodalbail@Sun.COM ipadm_status_t
i_ipadm_add_intfid2nvl(nvlist_t * nvl,ipadm_addrobj_t addr)39212016SGirish.Moodalbail@Sun.COM i_ipadm_add_intfid2nvl(nvlist_t *nvl, ipadm_addrobj_t addr)
39312016SGirish.Moodalbail@Sun.COM {
39412016SGirish.Moodalbail@Sun.COM 	nvlist_t	*nvl_addr = NULL;
39512016SGirish.Moodalbail@Sun.COM 	struct in6_addr	addr6;
39612016SGirish.Moodalbail@Sun.COM 	int		err;
39712016SGirish.Moodalbail@Sun.COM 
39812016SGirish.Moodalbail@Sun.COM 	if (!nvlist_exists(nvl, IPADM_NVP_INTFID)) {
39912016SGirish.Moodalbail@Sun.COM 		if ((err = nvlist_alloc(&nvl_addr, NV_UNIQUE_NAME, 0)) != 0)
40012016SGirish.Moodalbail@Sun.COM 			return (ipadm_errno2status(err));
40112016SGirish.Moodalbail@Sun.COM 		if ((err = nvlist_add_nvlist(nvl, IPADM_NVP_INTFID,
40212016SGirish.Moodalbail@Sun.COM 		    nvl_addr)) != 0) {
40312016SGirish.Moodalbail@Sun.COM 			nvlist_free(nvl_addr);
40412016SGirish.Moodalbail@Sun.COM 			return (ipadm_errno2status(err));
40512016SGirish.Moodalbail@Sun.COM 		}
40612016SGirish.Moodalbail@Sun.COM 		nvlist_free(nvl_addr);
40712016SGirish.Moodalbail@Sun.COM 	}
40812016SGirish.Moodalbail@Sun.COM 	if ((err = nvlist_lookup_nvlist(nvl, IPADM_NVP_INTFID,
40912016SGirish.Moodalbail@Sun.COM 	    &nvl_addr)) != 0 || (err = nvlist_add_uint32(nvl_addr,
41012016SGirish.Moodalbail@Sun.COM 	    IPADM_NVP_PREFIXLEN, addr->ipadm_intfidlen)) != 0) {
41112016SGirish.Moodalbail@Sun.COM 		return (ipadm_errno2status(err));
41212016SGirish.Moodalbail@Sun.COM 	}
41312016SGirish.Moodalbail@Sun.COM 	addr6 = addr->ipadm_intfid.sin6_addr;
41412016SGirish.Moodalbail@Sun.COM 	if ((err = nvlist_add_uint8_array(nvl_addr, IPADM_NVP_IPNUMADDR,
41512016SGirish.Moodalbail@Sun.COM 	    addr6.s6_addr, 16)) != 0) {
41612016SGirish.Moodalbail@Sun.COM 		return (ipadm_errno2status(err));
41712016SGirish.Moodalbail@Sun.COM 	}
41812016SGirish.Moodalbail@Sun.COM 	if (addr->ipadm_stateless)
41912016SGirish.Moodalbail@Sun.COM 		err = nvlist_add_string(nvl_addr, IPADM_NVP_STATELESS, "yes");
42012016SGirish.Moodalbail@Sun.COM 	else
42112016SGirish.Moodalbail@Sun.COM 		err = nvlist_add_string(nvl_addr, IPADM_NVP_STATELESS, "no");
42212016SGirish.Moodalbail@Sun.COM 	if (err != 0)
42312016SGirish.Moodalbail@Sun.COM 		return (ipadm_errno2status(err));
42412016SGirish.Moodalbail@Sun.COM 	if (addr->ipadm_stateful)
42512016SGirish.Moodalbail@Sun.COM 		err = nvlist_add_string(nvl_addr, IPADM_NVP_STATEFUL, "yes");
42612016SGirish.Moodalbail@Sun.COM 	else
42712016SGirish.Moodalbail@Sun.COM 		err = nvlist_add_string(nvl_addr, IPADM_NVP_STATEFUL, "no");
42812016SGirish.Moodalbail@Sun.COM 	if (err != 0)
42912016SGirish.Moodalbail@Sun.COM 		return (ipadm_errno2status(err));
43012016SGirish.Moodalbail@Sun.COM 
43112016SGirish.Moodalbail@Sun.COM 	return (IPADM_SUCCESS);
43212016SGirish.Moodalbail@Sun.COM }
43312016SGirish.Moodalbail@Sun.COM 
43412016SGirish.Moodalbail@Sun.COM /*
43512016SGirish.Moodalbail@Sun.COM  * Adds an nvpair for a dhcp address object to the nvlist. The "name" is
43612016SGirish.Moodalbail@Sun.COM  * the string in IPADM_NVP_DHCP. The "value" for IPADM_NVP_DHCP is another
43712016SGirish.Moodalbail@Sun.COM  * nvlist. Allocate the value nvlist for IPADM_NVP_DHCP if necessary, and add
43812016SGirish.Moodalbail@Sun.COM  * the parameters from the arguments `primary' and `wait'.
43912016SGirish.Moodalbail@Sun.COM  * Then add the allocated nvlist to `nvl'.
44012016SGirish.Moodalbail@Sun.COM  */
44112016SGirish.Moodalbail@Sun.COM ipadm_status_t
i_ipadm_add_dhcp2nvl(nvlist_t * nvl,boolean_t primary,int32_t wait)44212016SGirish.Moodalbail@Sun.COM i_ipadm_add_dhcp2nvl(nvlist_t *nvl, boolean_t primary, int32_t wait)
44312016SGirish.Moodalbail@Sun.COM {
44412016SGirish.Moodalbail@Sun.COM 	nvlist_t	*nvl_dhcp = NULL;
44512016SGirish.Moodalbail@Sun.COM 	int		err;
44612016SGirish.Moodalbail@Sun.COM 
44712016SGirish.Moodalbail@Sun.COM 	if (!nvlist_exists(nvl, IPADM_NVP_DHCP)) {
44812016SGirish.Moodalbail@Sun.COM 		if ((err = nvlist_alloc(&nvl_dhcp, NV_UNIQUE_NAME, 0)) != 0)
44912016SGirish.Moodalbail@Sun.COM 			return (ipadm_errno2status(err));
45012016SGirish.Moodalbail@Sun.COM 		if ((err = nvlist_add_nvlist(nvl, IPADM_NVP_DHCP,
45112016SGirish.Moodalbail@Sun.COM 		    nvl_dhcp)) != 0) {
45212016SGirish.Moodalbail@Sun.COM 			nvlist_free(nvl_dhcp);
45312016SGirish.Moodalbail@Sun.COM 			return (ipadm_errno2status(err));
45412016SGirish.Moodalbail@Sun.COM 		}
45512016SGirish.Moodalbail@Sun.COM 		nvlist_free(nvl_dhcp);
45612016SGirish.Moodalbail@Sun.COM 	}
45712016SGirish.Moodalbail@Sun.COM 	if ((err = nvlist_lookup_nvlist(nvl, IPADM_NVP_DHCP, &nvl_dhcp)) != 0 ||
45812016SGirish.Moodalbail@Sun.COM 	    (err = nvlist_add_int32(nvl_dhcp, IPADM_NVP_WAIT, wait)) != 0 ||
45912016SGirish.Moodalbail@Sun.COM 	    (err = nvlist_add_boolean_value(nvl_dhcp, IPADM_NVP_PRIMARY,
46012016SGirish.Moodalbail@Sun.COM 	    primary)) != 0) {
46112016SGirish.Moodalbail@Sun.COM 		return (ipadm_errno2status(err));
46212016SGirish.Moodalbail@Sun.COM 	}
46312016SGirish.Moodalbail@Sun.COM 
46412016SGirish.Moodalbail@Sun.COM 	return (IPADM_SUCCESS);
46512016SGirish.Moodalbail@Sun.COM }
46612016SGirish.Moodalbail@Sun.COM 
46712016SGirish.Moodalbail@Sun.COM /*
46812016SGirish.Moodalbail@Sun.COM  * Add (name, value) as an nvpair of type DATA_TYPE_STRING to nvlist.
46912016SGirish.Moodalbail@Sun.COM  */
47012016SGirish.Moodalbail@Sun.COM static void
i_ipadm_str_dbline2nvl(nvlist_t * nvl,char * name,char * value)47112016SGirish.Moodalbail@Sun.COM i_ipadm_str_dbline2nvl(nvlist_t *nvl, char *name, char *value)
47212016SGirish.Moodalbail@Sun.COM {
47312016SGirish.Moodalbail@Sun.COM 	/* if value is NULL create an empty node */
47412016SGirish.Moodalbail@Sun.COM 	if (value == NULL)
47512016SGirish.Moodalbail@Sun.COM 		(void) nvlist_add_string(nvl, name, "");
47612016SGirish.Moodalbail@Sun.COM 	else
47712016SGirish.Moodalbail@Sun.COM 		(void) nvlist_add_string(nvl, name, value);
47812016SGirish.Moodalbail@Sun.COM }
47912016SGirish.Moodalbail@Sun.COM 
48012016SGirish.Moodalbail@Sun.COM /*
48112016SGirish.Moodalbail@Sun.COM  * `name' = IPADM_NVP_IPV4ADDR and
48212016SGirish.Moodalbail@Sun.COM  * `value' = <local numeric IP string or hostname,remote numeric IP string or
48312016SGirish.Moodalbail@Sun.COM  *     hostname>
48412016SGirish.Moodalbail@Sun.COM  * This function will add an nvlist with the hostname information in
48512016SGirish.Moodalbail@Sun.COM  * nvpairs to the nvlist in `nvl'.
48612016SGirish.Moodalbail@Sun.COM  */
48712016SGirish.Moodalbail@Sun.COM static void
i_ipadm_ip4_dbline2nvl(nvlist_t * nvl,char * name,char * value)48812016SGirish.Moodalbail@Sun.COM i_ipadm_ip4_dbline2nvl(nvlist_t *nvl, char *name, char *value)
48912016SGirish.Moodalbail@Sun.COM {
49012016SGirish.Moodalbail@Sun.COM 	char			*cp, *hname;
49112016SGirish.Moodalbail@Sun.COM 	struct ipadm_addrobj_s	ipaddr;
49212016SGirish.Moodalbail@Sun.COM 
49312016SGirish.Moodalbail@Sun.COM 	assert(strcmp(name, IPADM_NVP_IPV4ADDR) == 0 && value != NULL);
49412016SGirish.Moodalbail@Sun.COM 
49512016SGirish.Moodalbail@Sun.COM 	bzero(&ipaddr, sizeof (ipaddr));
49612016SGirish.Moodalbail@Sun.COM 	ipaddr.ipadm_af = AF_INET;
49712016SGirish.Moodalbail@Sun.COM 
49812016SGirish.Moodalbail@Sun.COM 	hname = value; /* local hostname */
49912016SGirish.Moodalbail@Sun.COM 	cp = strchr(hname, ',');
50012016SGirish.Moodalbail@Sun.COM 	assert(cp != NULL);
50112016SGirish.Moodalbail@Sun.COM 	*cp++ = '\0';
50212016SGirish.Moodalbail@Sun.COM 	(void) strlcpy(ipaddr.ipadm_static_aname, hname,
50312016SGirish.Moodalbail@Sun.COM 	    sizeof (ipaddr.ipadm_static_aname));
50412016SGirish.Moodalbail@Sun.COM 
50512016SGirish.Moodalbail@Sun.COM 	if (*cp != '\0') {
50612016SGirish.Moodalbail@Sun.COM 		/* we have a dst hostname */
50712016SGirish.Moodalbail@Sun.COM 		(void) strlcpy(ipaddr.ipadm_static_dname, cp,
50812016SGirish.Moodalbail@Sun.COM 		    sizeof (ipaddr.ipadm_static_dname));
50912016SGirish.Moodalbail@Sun.COM 	}
51012016SGirish.Moodalbail@Sun.COM 	(void) i_ipadm_add_ipaddr2nvl(nvl, &ipaddr);
51112016SGirish.Moodalbail@Sun.COM }
51212016SGirish.Moodalbail@Sun.COM 
51312016SGirish.Moodalbail@Sun.COM /*
51412016SGirish.Moodalbail@Sun.COM  * `name' = IPADM_NVP_IPV6ADDR and
51512016SGirish.Moodalbail@Sun.COM  * `value' = <local numeric IP string or hostname,remote numeric IP string or
51612016SGirish.Moodalbail@Sun.COM  *     hostname>
51712016SGirish.Moodalbail@Sun.COM  * This function will add an nvlist with the hostname information in
51812016SGirish.Moodalbail@Sun.COM  * nvpairs to the nvlist in `nvl'.
51912016SGirish.Moodalbail@Sun.COM  */
52012016SGirish.Moodalbail@Sun.COM static void
i_ipadm_ip6_dbline2nvl(nvlist_t * nvl,char * name,char * value)52112016SGirish.Moodalbail@Sun.COM i_ipadm_ip6_dbline2nvl(nvlist_t *nvl, char *name, char *value)
52212016SGirish.Moodalbail@Sun.COM {
52312016SGirish.Moodalbail@Sun.COM 	char			*cp, *hname;
52412016SGirish.Moodalbail@Sun.COM 	struct ipadm_addrobj_s	ipaddr;
52512016SGirish.Moodalbail@Sun.COM 
52612016SGirish.Moodalbail@Sun.COM 	assert(strcmp(name, IPADM_NVP_IPV6ADDR) == 0 && value != NULL);
52712016SGirish.Moodalbail@Sun.COM 
52812016SGirish.Moodalbail@Sun.COM 	bzero(&ipaddr, sizeof (ipaddr));
52912016SGirish.Moodalbail@Sun.COM 	ipaddr.ipadm_af = AF_INET6;
53012016SGirish.Moodalbail@Sun.COM 
53112016SGirish.Moodalbail@Sun.COM 	hname = value; /* local hostname */
53212016SGirish.Moodalbail@Sun.COM 	cp = strchr(hname, ',');
53312016SGirish.Moodalbail@Sun.COM 	assert(cp != NULL);
53412016SGirish.Moodalbail@Sun.COM 	*cp++ = '\0';
53512016SGirish.Moodalbail@Sun.COM 	(void) strlcpy(ipaddr.ipadm_static_aname, hname,
53612016SGirish.Moodalbail@Sun.COM 	    sizeof (ipaddr.ipadm_static_aname));
53712016SGirish.Moodalbail@Sun.COM 
53812016SGirish.Moodalbail@Sun.COM 	if (*cp != '\0') {
53912016SGirish.Moodalbail@Sun.COM 		/* we have a dst hostname */
54012016SGirish.Moodalbail@Sun.COM 		(void) strlcpy(ipaddr.ipadm_static_dname, cp,
54112016SGirish.Moodalbail@Sun.COM 		    sizeof (ipaddr.ipadm_static_dname));
54212016SGirish.Moodalbail@Sun.COM 	}
54312016SGirish.Moodalbail@Sun.COM 	(void) i_ipadm_add_ipaddr2nvl(nvl, &ipaddr);
54412016SGirish.Moodalbail@Sun.COM }
54512016SGirish.Moodalbail@Sun.COM 
54612016SGirish.Moodalbail@Sun.COM /*
54712016SGirish.Moodalbail@Sun.COM  * `name' = IPADM_NVP_INTFID and `value' = <intfid/prefixlen>,{yes,no},{yes|no}
54812016SGirish.Moodalbail@Sun.COM  * This function will add an nvlist with the address object information in
54912016SGirish.Moodalbail@Sun.COM  * nvpairs to the nvlist in `nvl'.
55012016SGirish.Moodalbail@Sun.COM  */
55112016SGirish.Moodalbail@Sun.COM static void
i_ipadm_intfid_dbline2nvl(nvlist_t * nvl,char * name,char * value)55212016SGirish.Moodalbail@Sun.COM i_ipadm_intfid_dbline2nvl(nvlist_t *nvl, char *name, char *value)
55312016SGirish.Moodalbail@Sun.COM {
55412016SGirish.Moodalbail@Sun.COM 	char			*cp;
55512016SGirish.Moodalbail@Sun.COM 	struct ipadm_addrobj_s	ipaddr;
55612016SGirish.Moodalbail@Sun.COM 	char			*endp;
55712016SGirish.Moodalbail@Sun.COM 	char			*prefixlen;
55812016SGirish.Moodalbail@Sun.COM 	char			*stateless;
55912016SGirish.Moodalbail@Sun.COM 	char			*stateful;
56012016SGirish.Moodalbail@Sun.COM 
56112016SGirish.Moodalbail@Sun.COM 	assert(strcmp(name, IPADM_NVP_INTFID) == 0 && value != NULL);
56212016SGirish.Moodalbail@Sun.COM 
56312016SGirish.Moodalbail@Sun.COM 	bzero(&ipaddr, sizeof (ipaddr));
56412016SGirish.Moodalbail@Sun.COM 
56512016SGirish.Moodalbail@Sun.COM 	cp = strchr(value, '/');
56612016SGirish.Moodalbail@Sun.COM 	assert(cp != NULL);
56712016SGirish.Moodalbail@Sun.COM 
56812016SGirish.Moodalbail@Sun.COM 	*cp++ = '\0';
56912016SGirish.Moodalbail@Sun.COM 	ipaddr.ipadm_intfid.sin6_family = AF_INET6;
57012016SGirish.Moodalbail@Sun.COM 	(void) inet_pton(AF_INET6, value, &ipaddr.ipadm_intfid.sin6_addr);
57112016SGirish.Moodalbail@Sun.COM 
57212016SGirish.Moodalbail@Sun.COM 	prefixlen = cp;
57312016SGirish.Moodalbail@Sun.COM 	cp = strchr(cp, ',');
57412016SGirish.Moodalbail@Sun.COM 	assert(cp != NULL);
57512016SGirish.Moodalbail@Sun.COM 	*cp++ = '\0';
57612016SGirish.Moodalbail@Sun.COM 
57712016SGirish.Moodalbail@Sun.COM 	errno = 0;
57812016SGirish.Moodalbail@Sun.COM 	ipaddr.ipadm_intfidlen = (uint32_t)strtoul(prefixlen, &endp, 10);
57912016SGirish.Moodalbail@Sun.COM 	if (*endp != '\0' || errno != 0)
58012016SGirish.Moodalbail@Sun.COM 		return;
58112016SGirish.Moodalbail@Sun.COM 
58212016SGirish.Moodalbail@Sun.COM 	stateless = cp;
58312016SGirish.Moodalbail@Sun.COM 	stateful = strchr(stateless, ',');
58412016SGirish.Moodalbail@Sun.COM 	assert(stateful != NULL);
58512016SGirish.Moodalbail@Sun.COM 	*stateful++ = '\0';
58612016SGirish.Moodalbail@Sun.COM 	ipaddr.ipadm_stateless = (strcmp(stateless, "yes") == 0);
58712016SGirish.Moodalbail@Sun.COM 	ipaddr.ipadm_stateful = (strcmp(stateful, "yes") == 0);
58812016SGirish.Moodalbail@Sun.COM 
58912016SGirish.Moodalbail@Sun.COM 	/* Add all of it to the given nvlist */
59012016SGirish.Moodalbail@Sun.COM 	(void) i_ipadm_add_intfid2nvl(nvl, &ipaddr);
59112016SGirish.Moodalbail@Sun.COM }
59212016SGirish.Moodalbail@Sun.COM 
59312016SGirish.Moodalbail@Sun.COM /*
59412016SGirish.Moodalbail@Sun.COM  * `name' = IPADM_NVP_DHCP and `value' = <wait_time>,{yes|no}
59512016SGirish.Moodalbail@Sun.COM  * This function will add an nvlist with the dhcp address object information in
59612016SGirish.Moodalbail@Sun.COM  * nvpairs to the nvlist in `nvl'.
59712016SGirish.Moodalbail@Sun.COM  */
59812016SGirish.Moodalbail@Sun.COM static void
i_ipadm_dhcp_dbline2nvl(nvlist_t * nvl,char * name,char * value)59912016SGirish.Moodalbail@Sun.COM i_ipadm_dhcp_dbline2nvl(nvlist_t *nvl, char *name, char *value)
60012016SGirish.Moodalbail@Sun.COM {
60112016SGirish.Moodalbail@Sun.COM 	char		*cp;
60212016SGirish.Moodalbail@Sun.COM 	char		*endp;
60312016SGirish.Moodalbail@Sun.COM 	long		wait_time;
60412016SGirish.Moodalbail@Sun.COM 	boolean_t	primary;
60512016SGirish.Moodalbail@Sun.COM 
60612016SGirish.Moodalbail@Sun.COM 	assert(strcmp(name, IPADM_NVP_DHCP) == 0 && value != NULL);
60712016SGirish.Moodalbail@Sun.COM 	cp = strchr(value, ',');
60812016SGirish.Moodalbail@Sun.COM 	assert(cp != NULL);
60912016SGirish.Moodalbail@Sun.COM 	*cp++ = '\0';
61012016SGirish.Moodalbail@Sun.COM 	errno = 0;
61112016SGirish.Moodalbail@Sun.COM 	wait_time = strtol(value, &endp, 10);
61212016SGirish.Moodalbail@Sun.COM 	if (*endp != '\0' || errno != 0)
61312016SGirish.Moodalbail@Sun.COM 		return;
61412016SGirish.Moodalbail@Sun.COM 	primary = (strcmp(cp, "yes") == 0);
61512016SGirish.Moodalbail@Sun.COM 	(void) i_ipadm_add_dhcp2nvl(nvl, primary, (int32_t)wait_time);
61612016SGirish.Moodalbail@Sun.COM }
61712016SGirish.Moodalbail@Sun.COM 
61812016SGirish.Moodalbail@Sun.COM /*
61912016SGirish.Moodalbail@Sun.COM  * Parses the buffer, for name-value pairs and creates nvlist. The value
62012016SGirish.Moodalbail@Sun.COM  * is always considered to be a string.
62112016SGirish.Moodalbail@Sun.COM  */
62212016SGirish.Moodalbail@Sun.COM int
ipadm_str2nvlist(const char * inbuf,nvlist_t ** ipnvl,uint_t flags)62312016SGirish.Moodalbail@Sun.COM ipadm_str2nvlist(const char *inbuf, nvlist_t **ipnvl, uint_t flags)
62412016SGirish.Moodalbail@Sun.COM {
62512016SGirish.Moodalbail@Sun.COM 	char	*nv, *name, *val, *buf, *cp, *sep;
62612016SGirish.Moodalbail@Sun.COM 	int	err;
62712016SGirish.Moodalbail@Sun.COM 
62812016SGirish.Moodalbail@Sun.COM 	if (inbuf == NULL || inbuf[0] == '\0' || ipnvl == NULL)
62912016SGirish.Moodalbail@Sun.COM 		return (EINVAL);
63012016SGirish.Moodalbail@Sun.COM 	*ipnvl = NULL;
63112016SGirish.Moodalbail@Sun.COM 
63212016SGirish.Moodalbail@Sun.COM 	/*
63312016SGirish.Moodalbail@Sun.COM 	 * If IPADM_NORVAL is set, then `inbuf' should be comma delimited values
63412016SGirish.Moodalbail@Sun.COM 	 */
63512016SGirish.Moodalbail@Sun.COM 	if ((flags & IPADM_NORVAL) && strchr(inbuf, '=') != NULL)
63612016SGirish.Moodalbail@Sun.COM 		return (EINVAL);
63712016SGirish.Moodalbail@Sun.COM 
63812016SGirish.Moodalbail@Sun.COM 	if ((cp = buf = strdup(inbuf)) == NULL)
63912016SGirish.Moodalbail@Sun.COM 		return (errno);
64012016SGirish.Moodalbail@Sun.COM 
64112016SGirish.Moodalbail@Sun.COM 	while (isspace(*buf))
64212016SGirish.Moodalbail@Sun.COM 		buf++;
64312016SGirish.Moodalbail@Sun.COM 
64412016SGirish.Moodalbail@Sun.COM 	if (*buf == '\0') {
64512016SGirish.Moodalbail@Sun.COM 		err = EINVAL;
64612016SGirish.Moodalbail@Sun.COM 		goto fail;
64712016SGirish.Moodalbail@Sun.COM 	}
64812016SGirish.Moodalbail@Sun.COM 
64912016SGirish.Moodalbail@Sun.COM 	nv = buf;
65012016SGirish.Moodalbail@Sun.COM 	/*
65112016SGirish.Moodalbail@Sun.COM 	 * work on one nvpair at a time and extract the name and value
65212016SGirish.Moodalbail@Sun.COM 	 */
65312016SGirish.Moodalbail@Sun.COM 	sep = ((flags & IPADM_NORVAL) ? IPADM_NAME_SEP : IPADM_NVPAIR_SEP);
65412016SGirish.Moodalbail@Sun.COM 	while ((nv = strsep(&buf, sep)) != NULL) {
65512016SGirish.Moodalbail@Sun.COM 		if (*nv == '\n')
65612016SGirish.Moodalbail@Sun.COM 			continue;
65712016SGirish.Moodalbail@Sun.COM 		name = nv;
65812016SGirish.Moodalbail@Sun.COM 		if ((val = strchr(nv, '=')) != NULL)
65912016SGirish.Moodalbail@Sun.COM 			*val++ = '\0';
66012016SGirish.Moodalbail@Sun.COM 		if (*ipnvl == NULL &&
66112016SGirish.Moodalbail@Sun.COM 		    (err = nvlist_alloc(ipnvl, NV_UNIQUE_NAME, 0)) != 0)
66212016SGirish.Moodalbail@Sun.COM 			goto fail;
66312016SGirish.Moodalbail@Sun.COM 		if (nvlist_exists(*ipnvl, name)) {
66412016SGirish.Moodalbail@Sun.COM 			err = EEXIST;
66512016SGirish.Moodalbail@Sun.COM 			goto fail;
66612016SGirish.Moodalbail@Sun.COM 		}
66712016SGirish.Moodalbail@Sun.COM 		/* Add the extracted nvpair to the nvlist `ipnvl'. */
66812016SGirish.Moodalbail@Sun.COM 		(void) i_ipadm_add_nvpair(*ipnvl, name, val);
66912016SGirish.Moodalbail@Sun.COM 	}
67012016SGirish.Moodalbail@Sun.COM 	free(cp);
67112016SGirish.Moodalbail@Sun.COM 	return (0);
67212016SGirish.Moodalbail@Sun.COM fail:
67312016SGirish.Moodalbail@Sun.COM 	free(cp);
67412016SGirish.Moodalbail@Sun.COM 	nvlist_free(*ipnvl);
67512016SGirish.Moodalbail@Sun.COM 	*ipnvl = NULL;
67612016SGirish.Moodalbail@Sun.COM 	return (err);
67712016SGirish.Moodalbail@Sun.COM }
67812016SGirish.Moodalbail@Sun.COM 
67912016SGirish.Moodalbail@Sun.COM /*
68012016SGirish.Moodalbail@Sun.COM  * Opens the data store for read/write operation. For write operation we open
68112016SGirish.Moodalbail@Sun.COM  * another file and scribble the changes to it and copy the new file back to
68212016SGirish.Moodalbail@Sun.COM  * old file.
68312016SGirish.Moodalbail@Sun.COM  */
68412016SGirish.Moodalbail@Sun.COM int
ipadm_rw_db(db_wfunc_t * db_walk_func,void * arg,const char * db_file,mode_t db_perms,ipadm_db_op_t db_op)68512016SGirish.Moodalbail@Sun.COM ipadm_rw_db(db_wfunc_t *db_walk_func, void *arg, const char *db_file,
68612016SGirish.Moodalbail@Sun.COM     mode_t db_perms, ipadm_db_op_t db_op)
68712016SGirish.Moodalbail@Sun.COM {
68812016SGirish.Moodalbail@Sun.COM 	FILE		*fp, *nfp = NULL;
68912016SGirish.Moodalbail@Sun.COM 	char		file[MAXPATHLEN];
69012016SGirish.Moodalbail@Sun.COM 	char		newfile[MAXPATHLEN];
69112016SGirish.Moodalbail@Sun.COM 	int		nfd;
69212016SGirish.Moodalbail@Sun.COM 	boolean_t	writeop;
69312016SGirish.Moodalbail@Sun.COM 	int		err = 0;
69412016SGirish.Moodalbail@Sun.COM 
69512016SGirish.Moodalbail@Sun.COM 	writeop = (db_op != IPADM_DB_READ);
69612016SGirish.Moodalbail@Sun.COM 
69712016SGirish.Moodalbail@Sun.COM 	(void) snprintf(file, MAXPATHLEN, "%s/%s", ipadm_rootdir, db_file);
69812016SGirish.Moodalbail@Sun.COM 
69912016SGirish.Moodalbail@Sun.COM 	/* open the data store */
70012016SGirish.Moodalbail@Sun.COM 	if ((fp = fopen(file, (writeop ? "r+" : "r"))) == NULL)
70112016SGirish.Moodalbail@Sun.COM 		return (errno);
70212016SGirish.Moodalbail@Sun.COM 
70312016SGirish.Moodalbail@Sun.COM 	if (writeop) {
70412016SGirish.Moodalbail@Sun.COM 		(void) snprintf(newfile, MAXPATHLEN, "%s/%s.new",
70512016SGirish.Moodalbail@Sun.COM 		    ipadm_rootdir, db_file);
70612016SGirish.Moodalbail@Sun.COM 		if ((nfd = open(newfile, O_WRONLY | O_CREAT | O_TRUNC,
70712016SGirish.Moodalbail@Sun.COM 		    db_perms)) < 0) {
70812016SGirish.Moodalbail@Sun.COM 			err = errno;
70912016SGirish.Moodalbail@Sun.COM 			(void) fclose(fp);
71012016SGirish.Moodalbail@Sun.COM 			return (err);
71112016SGirish.Moodalbail@Sun.COM 		}
71212016SGirish.Moodalbail@Sun.COM 
71312016SGirish.Moodalbail@Sun.COM 		if ((nfp = fdopen(nfd, "w")) == NULL) {
71412016SGirish.Moodalbail@Sun.COM 			err = errno;
71512016SGirish.Moodalbail@Sun.COM 			(void) close(nfd);
71612016SGirish.Moodalbail@Sun.COM 			(void) fclose(fp);
71712016SGirish.Moodalbail@Sun.COM 			(void) unlink(newfile);
71812016SGirish.Moodalbail@Sun.COM 			return (err);
71912016SGirish.Moodalbail@Sun.COM 		}
72012016SGirish.Moodalbail@Sun.COM 	}
72112016SGirish.Moodalbail@Sun.COM 	err = ipadm_process_db_line(db_walk_func, arg, fp, nfp, db_op);
72212016SGirish.Moodalbail@Sun.COM 	if (!writeop)
72312016SGirish.Moodalbail@Sun.COM 		goto done;
72412016SGirish.Moodalbail@Sun.COM 	if (err != 0 && err != ENOENT)
72512016SGirish.Moodalbail@Sun.COM 		goto done;
72612016SGirish.Moodalbail@Sun.COM 
72712016SGirish.Moodalbail@Sun.COM 	if (fflush(nfp) == EOF) {
72812016SGirish.Moodalbail@Sun.COM 		err = errno;
72912016SGirish.Moodalbail@Sun.COM 		goto done;
73012016SGirish.Moodalbail@Sun.COM 	}
73112016SGirish.Moodalbail@Sun.COM 	(void) fclose(fp);
73212016SGirish.Moodalbail@Sun.COM 	(void) fclose(nfp);
73312016SGirish.Moodalbail@Sun.COM 
73412016SGirish.Moodalbail@Sun.COM 	if (rename(newfile, file) < 0) {
73512016SGirish.Moodalbail@Sun.COM 		err = errno;
73612016SGirish.Moodalbail@Sun.COM 		(void) unlink(newfile);
73712016SGirish.Moodalbail@Sun.COM 	}
73812016SGirish.Moodalbail@Sun.COM 	return (err);
73912016SGirish.Moodalbail@Sun.COM done:
74012016SGirish.Moodalbail@Sun.COM 	if (nfp != NULL) {
74112016SGirish.Moodalbail@Sun.COM 		(void) fclose(nfp);
74212016SGirish.Moodalbail@Sun.COM 		if (err != 0)
74312016SGirish.Moodalbail@Sun.COM 			(void) unlink(newfile);
74412016SGirish.Moodalbail@Sun.COM 	}
74512016SGirish.Moodalbail@Sun.COM 	(void) fclose(fp);
74612016SGirish.Moodalbail@Sun.COM 	return (err);
74712016SGirish.Moodalbail@Sun.COM }
74812016SGirish.Moodalbail@Sun.COM 
74912016SGirish.Moodalbail@Sun.COM /*
75012016SGirish.Moodalbail@Sun.COM  * Processes each line of the configuration file, skipping lines with
75112016SGirish.Moodalbail@Sun.COM  * leading spaces, blank lines and comments. The line form the DB
75212016SGirish.Moodalbail@Sun.COM  * is converted to nvlist and the callback function is called to process
75312016SGirish.Moodalbail@Sun.COM  * the list. The buf could be modified by the callback function and
75412016SGirish.Moodalbail@Sun.COM  * if this is a write operation and buf is not truncated, buf will
75512016SGirish.Moodalbail@Sun.COM  * be written to disk.
75612016SGirish.Moodalbail@Sun.COM  *
75712016SGirish.Moodalbail@Sun.COM  * Further if cont is set to B_FALSE,  the remainder of the file will
75812016SGirish.Moodalbail@Sun.COM  * continue to be read (however callback function will not be called) and,
75912016SGirish.Moodalbail@Sun.COM  * if necessary, written to disk as well.
76012016SGirish.Moodalbail@Sun.COM  */
76112016SGirish.Moodalbail@Sun.COM static int
ipadm_process_db_line(db_wfunc_t * db_walk_func,void * arg,FILE * fp,FILE * nfp,ipadm_db_op_t db_op)76212016SGirish.Moodalbail@Sun.COM ipadm_process_db_line(db_wfunc_t *db_walk_func, void *arg, FILE *fp, FILE *nfp,
76312016SGirish.Moodalbail@Sun.COM     ipadm_db_op_t db_op)
76412016SGirish.Moodalbail@Sun.COM {
76512016SGirish.Moodalbail@Sun.COM 	int		err = 0;
76612016SGirish.Moodalbail@Sun.COM 	char		buf[MAXLINELEN];
76712016SGirish.Moodalbail@Sun.COM 	boolean_t	cont = B_TRUE;
76812016SGirish.Moodalbail@Sun.COM 	int		i, len;
76912016SGirish.Moodalbail@Sun.COM 	nvlist_t	*db_nvl = NULL;
77012016SGirish.Moodalbail@Sun.COM 	boolean_t	line_deleted = B_FALSE;
77112016SGirish.Moodalbail@Sun.COM 
77212016SGirish.Moodalbail@Sun.COM 	while (fgets(buf, MAXLINELEN, fp) != NULL) {
77312016SGirish.Moodalbail@Sun.COM 		/*
77412016SGirish.Moodalbail@Sun.COM 		 * Skip leading spaces, blank lines, and comments.
77512016SGirish.Moodalbail@Sun.COM 		 */
77612016SGirish.Moodalbail@Sun.COM 		len = strnlen(buf, MAXLINELEN);
77712016SGirish.Moodalbail@Sun.COM 		for (i = 0; i < len; i++) {
77812016SGirish.Moodalbail@Sun.COM 			if (!isspace(buf[i]))
77912016SGirish.Moodalbail@Sun.COM 				break;
78012016SGirish.Moodalbail@Sun.COM 		}
78112016SGirish.Moodalbail@Sun.COM 
78212016SGirish.Moodalbail@Sun.COM 		if (i != len && buf[i] != '#' && cont) {
78312016SGirish.Moodalbail@Sun.COM 			if (ipadm_str2nvlist(buf, &db_nvl, 0) == 0) {
78412016SGirish.Moodalbail@Sun.COM 				cont = db_walk_func(arg, db_nvl, buf,
78512016SGirish.Moodalbail@Sun.COM 				    MAXLINELEN, &err);
78612016SGirish.Moodalbail@Sun.COM 			} else {
78712016SGirish.Moodalbail@Sun.COM 				/* Delete corrupted line. */
78812016SGirish.Moodalbail@Sun.COM 				buf[0] = '\0';
78912016SGirish.Moodalbail@Sun.COM 			}
79012016SGirish.Moodalbail@Sun.COM 			nvlist_free(db_nvl);
79112016SGirish.Moodalbail@Sun.COM 			db_nvl = NULL;
79212016SGirish.Moodalbail@Sun.COM 		}
79312016SGirish.Moodalbail@Sun.COM 		if (err != 0)
79412016SGirish.Moodalbail@Sun.COM 			break;
79512016SGirish.Moodalbail@Sun.COM 		if (nfp != NULL && buf[0] == '\0')
79612016SGirish.Moodalbail@Sun.COM 			line_deleted = B_TRUE;
79712016SGirish.Moodalbail@Sun.COM 		if (nfp != NULL	&& buf[0] != '\0' && fputs(buf, nfp) == EOF) {
79812016SGirish.Moodalbail@Sun.COM 			err = errno;
79912016SGirish.Moodalbail@Sun.COM 			break;
80012016SGirish.Moodalbail@Sun.COM 		}
80112016SGirish.Moodalbail@Sun.COM 	}
80212016SGirish.Moodalbail@Sun.COM 
80312016SGirish.Moodalbail@Sun.COM 	if (err != 0 || !cont)
80412016SGirish.Moodalbail@Sun.COM 		return (err);
80512016SGirish.Moodalbail@Sun.COM 
80612016SGirish.Moodalbail@Sun.COM 	if (db_op == IPADM_DB_WRITE) {
807*13125SGirish.Moodalbail@oracle.COM 		nvlist_t	*nvl;
80812016SGirish.Moodalbail@Sun.COM 
80912016SGirish.Moodalbail@Sun.COM 		/*
810*13125SGirish.Moodalbail@oracle.COM 		 * `arg' will be NULL when we are doing in-line update of
811*13125SGirish.Moodalbail@oracle.COM 		 * entries.
81212016SGirish.Moodalbail@Sun.COM 		 */
813*13125SGirish.Moodalbail@oracle.COM 		if (arg != NULL) {
814*13125SGirish.Moodalbail@oracle.COM 			nvl = ((ipadm_dbwrite_cbarg_t *)arg)->dbw_nvl;
815*13125SGirish.Moodalbail@oracle.COM 			/*
816*13125SGirish.Moodalbail@oracle.COM 			 * If the specified entry is not found above, we add
817*13125SGirish.Moodalbail@oracle.COM 			 * the entry to the configuration file, here.
818*13125SGirish.Moodalbail@oracle.COM 			 */
819*13125SGirish.Moodalbail@oracle.COM 			(void) memset(buf, 0, MAXLINELEN);
820*13125SGirish.Moodalbail@oracle.COM 			if (ipadm_nvlist2str(nvl, buf, MAXLINELEN) == 0)
821*13125SGirish.Moodalbail@oracle.COM 				err = ENOBUFS;
822*13125SGirish.Moodalbail@oracle.COM 			else if (fputs(buf, nfp) == EOF)
823*13125SGirish.Moodalbail@oracle.COM 				err = errno;
824*13125SGirish.Moodalbail@oracle.COM 		}
82512016SGirish.Moodalbail@Sun.COM 		return (err);
82612016SGirish.Moodalbail@Sun.COM 	}
82712016SGirish.Moodalbail@Sun.COM 
82812016SGirish.Moodalbail@Sun.COM 	if (db_op == IPADM_DB_DELETE && line_deleted)
82912016SGirish.Moodalbail@Sun.COM 		return (0);
83012016SGirish.Moodalbail@Sun.COM 
83112016SGirish.Moodalbail@Sun.COM 	/* if we have come this far, then we didn't find any match */
83212016SGirish.Moodalbail@Sun.COM 	return (ENOENT);
83312016SGirish.Moodalbail@Sun.COM }
834