summaryrefslogtreecommitdiff
path: root/usr/src/lib/libipadm/common/ipadm_persist.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libipadm/common/ipadm_persist.c')
-rw-r--r--usr/src/lib/libipadm/common/ipadm_persist.c236
1 files changed, 206 insertions, 30 deletions
diff --git a/usr/src/lib/libipadm/common/ipadm_persist.c b/usr/src/lib/libipadm/common/ipadm_persist.c
index 3043d5e51e..557e29fb3e 100644
--- a/usr/src/lib/libipadm/common/ipadm_persist.c
+++ b/usr/src/lib/libipadm/common/ipadm_persist.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2021 Tintri by DDN, Inc. All rights reserved.
*/
/*
@@ -51,6 +52,12 @@
* wait: DATA_TYPE_INT32
* primary: DATA_TYPE_BOOLEAN
*
+ * IPADM_NVP_FAMILIES - value holds interface families and when converted
+ * to nvlist, will be a DATA_TYPE_UINT16_ARRAY
+ *
+ * IPADM_NVP_MIFNAMES - value holds IPMP group members and when converted
+ * to nvlist, will be a DATA_TYPE_STRING_ARRAY
+ *
* default - value is a single entity and when converted to nvlist, will
* contain nvpair of type DATA_TYPE_STRING. nvpairs private to
* ipadm are of this type. Further the property name and property
@@ -88,21 +95,23 @@ static int ipadm_process_db_line(db_wfunc_t *, void *, FILE *fp, FILE *nfp,
/*
* convert nvpair to a "name=value" string for writing to the DB.
*/
-typedef size_t ipadm_wfunc_t(nvpair_t *, char *, size_t);
+typedef size_t ipadm_wfunc_t(nvpair_t *, char *, size_t);
/*
* ipadm_rfunc_t takes (`name', `value') and adds the appropriately typed
* nvpair to the nvlist.
*/
-typedef void ipadm_rfunc_t(nvlist_t *, char *name, char *value);
+typedef ipadm_status_t ipadm_rfunc_t(nvlist_t *, char *, char *);
static ipadm_rfunc_t i_ipadm_str_dbline2nvl, i_ipadm_ip4_dbline2nvl,
i_ipadm_ip6_dbline2nvl, i_ipadm_intfid_dbline2nvl,
- i_ipadm_dhcp_dbline2nvl;
+ i_ipadm_dhcp_dbline2nvl, i_ipadm_families_dbline2nvl,
+ i_ipadm_groupmembers_dbline2nvl;
static ipadm_wfunc_t i_ipadm_str_nvp2dbline, i_ipadm_ip4_nvp2dbline,
i_ipadm_ip6_nvp2dbline, i_ipadm_intfid_nvp2dbline,
- i_ipadm_dhcp_nvp2dbline;
+ i_ipadm_dhcp_nvp2dbline, i_ipadm_families_nvp2dbline,
+ i_ipadm_groupmembers_nvp2dbline;
/*
* table of function pointers to read/write formatted entries from/to
@@ -120,6 +129,10 @@ static ipadm_conf_ent_t ipadm_conf_ent[] = {
{ IPADM_NVP_INTFID, i_ipadm_intfid_nvp2dbline,
i_ipadm_intfid_dbline2nvl },
{ IPADM_NVP_DHCP, i_ipadm_dhcp_nvp2dbline, i_ipadm_dhcp_dbline2nvl },
+ { IPADM_NVP_FAMILIES, i_ipadm_families_nvp2dbline,
+ i_ipadm_families_dbline2nvl },
+ { IPADM_NVP_MIFNAMES, i_ipadm_groupmembers_nvp2dbline,
+ i_ipadm_groupmembers_dbline2nvl},
{ NULL, i_ipadm_str_nvp2dbline, i_ipadm_str_dbline2nvl }
};
@@ -259,7 +272,7 @@ static size_t
i_ipadm_dhcp_nvp2dbline(nvpair_t *nvp, char *buf, size_t buflen)
{
char addrbuf[IPADM_STRSIZE];
- int32_t wait;
+ int32_t wait;
boolean_t primary;
nvlist_t *v;
@@ -328,13 +341,13 @@ ipadm_nvlist2str(nvlist_t *nvl, char *buf, size_t buflen)
* Adds a nvpair, using the `name' and `value', to the nvlist in `nvl'.
* The value will be interpreted as explained at the top of this file.
*/
-static void
+static ipadm_status_t
i_ipadm_add_nvpair(nvlist_t *nvl, char *name, char *value)
{
ipadm_conf_ent_t *ipent;
ipent = i_ipadm_find_conf_type(name);
- (*ipent->ipent_rfunc)(nvl, name, value);
+ return ((*ipent->ipent_rfunc)(nvl, name, value));
}
/*
@@ -467,14 +480,18 @@ i_ipadm_add_dhcp2nvl(nvlist_t *nvl, boolean_t primary, int32_t wait)
/*
* Add (name, value) as an nvpair of type DATA_TYPE_STRING to nvlist.
*/
-static void
+static ipadm_status_t
i_ipadm_str_dbline2nvl(nvlist_t *nvl, char *name, char *value)
{
+ int err;
+
/* if value is NULL create an empty node */
if (value == NULL)
- (void) nvlist_add_string(nvl, name, "");
+ err = nvlist_add_string(nvl, name, "");
else
- (void) nvlist_add_string(nvl, name, value);
+ err = nvlist_add_string(nvl, name, value);
+
+ return (ipadm_errno2status(err));
}
/*
@@ -484,7 +501,7 @@ i_ipadm_str_dbline2nvl(nvlist_t *nvl, char *name, char *value)
* This function will add an nvlist with the hostname information in
* nvpairs to the nvlist in `nvl'.
*/
-static void
+static ipadm_status_t
i_ipadm_ip4_dbline2nvl(nvlist_t *nvl, char *name, char *value)
{
char *cp, *hname;
@@ -507,7 +524,7 @@ i_ipadm_ip4_dbline2nvl(nvlist_t *nvl, char *name, char *value)
(void) strlcpy(ipaddr.ipadm_static_dname, cp,
sizeof (ipaddr.ipadm_static_dname));
}
- (void) i_ipadm_add_ipaddr2nvl(nvl, &ipaddr);
+ return (i_ipadm_add_ipaddr2nvl(nvl, &ipaddr));
}
/*
@@ -517,7 +534,7 @@ i_ipadm_ip4_dbline2nvl(nvlist_t *nvl, char *name, char *value)
* This function will add an nvlist with the hostname information in
* nvpairs to the nvlist in `nvl'.
*/
-static void
+static ipadm_status_t
i_ipadm_ip6_dbline2nvl(nvlist_t *nvl, char *name, char *value)
{
char *cp, *hname;
@@ -540,7 +557,7 @@ i_ipadm_ip6_dbline2nvl(nvlist_t *nvl, char *name, char *value)
(void) strlcpy(ipaddr.ipadm_static_dname, cp,
sizeof (ipaddr.ipadm_static_dname));
}
- (void) i_ipadm_add_ipaddr2nvl(nvl, &ipaddr);
+ return (i_ipadm_add_ipaddr2nvl(nvl, &ipaddr));
}
/*
@@ -548,7 +565,7 @@ i_ipadm_ip6_dbline2nvl(nvlist_t *nvl, char *name, char *value)
* This function will add an nvlist with the address object information in
* nvpairs to the nvlist in `nvl'.
*/
-static void
+static ipadm_status_t
i_ipadm_intfid_dbline2nvl(nvlist_t *nvl, char *name, char *value)
{
char *cp;
@@ -577,7 +594,7 @@ i_ipadm_intfid_dbline2nvl(nvlist_t *nvl, char *name, char *value)
errno = 0;
ipaddr.ipadm_intfidlen = (uint32_t)strtoul(prefixlen, &endp, 10);
if (*endp != '\0' || errno != 0)
- return;
+ return (ipadm_errno2status(errno));
stateless = cp;
stateful = strchr(stateless, ',');
@@ -587,7 +604,7 @@ i_ipadm_intfid_dbline2nvl(nvlist_t *nvl, char *name, char *value)
ipaddr.ipadm_stateful = (strcmp(stateful, "yes") == 0);
/* Add all of it to the given nvlist */
- (void) i_ipadm_add_intfid2nvl(nvl, &ipaddr);
+ return (i_ipadm_add_intfid2nvl(nvl, &ipaddr));
}
/*
@@ -595,7 +612,7 @@ i_ipadm_intfid_dbline2nvl(nvlist_t *nvl, char *name, char *value)
* This function will add an nvlist with the dhcp address object information in
* nvpairs to the nvlist in `nvl'.
*/
-static void
+static ipadm_status_t
i_ipadm_dhcp_dbline2nvl(nvlist_t *nvl, char *name, char *value)
{
char *cp;
@@ -610,39 +627,194 @@ i_ipadm_dhcp_dbline2nvl(nvlist_t *nvl, char *name, char *value)
errno = 0;
wait_time = strtol(value, &endp, 10);
if (*endp != '\0' || errno != 0)
- return;
+ return (ipadm_errno2status(errno));
primary = (strcmp(cp, "yes") == 0);
- (void) i_ipadm_add_dhcp2nvl(nvl, primary, (int32_t)wait_time);
+ return (i_ipadm_add_dhcp2nvl(nvl, primary, (int32_t)wait_time));
+}
+
+/*
+ * Input 'nvp': name = IPADM_NVP_FAMILIES and value = array of 'uint16_t'
+ *
+ *
+ */
+static size_t
+i_ipadm_families_nvp2dbline(nvpair_t *nvp, char *buf, size_t buflen)
+{
+ uint_t nelem = 0;
+ uint16_t *elem;
+
+ assert(nvpair_type(nvp) == DATA_TYPE_UINT16_ARRAY);
+
+ if (nvpair_value_uint16_array(nvp,
+ &elem, &nelem) != 0) {
+ buf[0] = '\0';
+ return (0);
+ }
+
+ assert(nelem != 0 || nelem > 2);
+
+ if (nelem == 1) {
+ return (snprintf(buf, buflen, "%s=%d",
+ nvpair_name(nvp), elem[0]));
+ } else {
+ return (snprintf(buf, buflen, "%s=%d,%d",
+ nvpair_name(nvp), elem[0], elem[1]));
+ }
+}
+
+/*
+ * name = IPADM_NVP_FAMILIES and value = <FAMILY>[,FAMILY]
+ *
+ * output nvp: name = IPADM_NVP_FAMILIES and value = array of 'uint16_t'
+ *
+ */
+static ipadm_status_t
+i_ipadm_families_dbline2nvl(nvlist_t *nvl, char *name, char *value)
+{
+ uint16_t families[2];
+ uint_t nelem = 0;
+ char *val, *lasts;
+
+ if ((val = strtok_r(value,
+ ",", &lasts)) != NULL) {
+ families[0] = atoi(val);
+ nelem++;
+ if ((val = strtok_r(NULL,
+ ",", &lasts)) != NULL) {
+ families[1] = atoi(val);
+ nelem++;
+ }
+ return (ipadm_errno2status(nvlist_add_uint16_array(nvl,
+ IPADM_NVP_FAMILIES, families, nelem)));
+ }
+
+ return (IPADM_INVALID_ARG);
+}
+
+/*
+ * input nvp: name = IPADM_NVP_MIFNAMES and value = array of 'char *'
+ *
+ *
+ */
+static size_t
+i_ipadm_groupmembers_nvp2dbline(nvpair_t *nvp, char *buf, size_t buflen)
+{
+ uint_t nelem = 0;
+ char **elem;
+ size_t n;
+
+ assert(nvpair_type(nvp) == DATA_TYPE_STRING_ARRAY);
+
+ if (nvpair_value_string_array(nvp,
+ &elem, &nelem) != 0) {
+ buf[0] = '\0';
+ return (0);
+ }
+
+ assert(nelem != 0);
+
+ n = snprintf(buf, buflen, "%s=", IPADM_NVP_MIFNAMES);
+ if (n >= buflen)
+ return (n);
+
+ while (nelem-- > 0) {
+ n = strlcat(buf, elem[nelem], buflen);
+ if (nelem > 0)
+ n = strlcat(buf, ",", buflen);
+
+ if (n > buflen)
+ return (n);
+ }
+
+ return (n);
+}
+
+/*
+ * name = IPADM_NVP_MIFNAMES and value = <if_name>[,if_name]
+ *
+ * output nvp: name = IPADM_NVP_MIFNAMES and value = array of 'char *'
+ */
+static ipadm_status_t
+i_ipadm_groupmembers_dbline2nvl(nvlist_t *nvl, char *name, char *value)
+{
+ char **members = NULL;
+ char *member = NULL;
+ char *val, *lasts;
+ uint_t m_cnt = 0;
+ ipadm_status_t ret = IPADM_SUCCESS;
+
+ assert(strcmp(name, IPADM_NVP_MIFNAMES) == 0 && value != NULL);
+
+ for (val = strtok_r(value, ",", &lasts);
+ val != NULL;
+ val = strtok_r(NULL, ",", &lasts)) {
+ if ((m_cnt % 4) == 0) {
+ char **tmp = recallocarray(members, m_cnt, m_cnt + 4,
+ sizeof (char *));
+
+ if (tmp == NULL) {
+ ret = IPADM_NO_MEMORY;
+ goto fail;
+ }
+
+ members = tmp;
+ }
+
+ member = calloc(1, LIFNAMSIZ);
+
+ if (member == NULL) {
+ ret = IPADM_NO_MEMORY;
+ goto fail;
+ }
+
+ (void) strlcpy(member, val, LIFNAMSIZ);
+ members[m_cnt++] = member;
+
+ }
+
+ if ((ret = ipadm_errno2status(nvlist_add_string_array(nvl,
+ IPADM_NVP_MIFNAMES, members, m_cnt))) != IPADM_SUCCESS)
+ goto fail;
+
+fail:
+ while (m_cnt-- > 0) {
+ free(members[m_cnt]);
+ }
+
+ free(members);
+
+ return (ret);
}
/*
* Parses the buffer, for name-value pairs and creates nvlist. The value
* is always considered to be a string.
*/
-int
+ipadm_status_t
ipadm_str2nvlist(const char *inbuf, nvlist_t **ipnvl, uint_t flags)
{
+ ipadm_status_t status;
char *nv, *name, *val, *buf, *cp, *sep;
int err;
if (inbuf == NULL || inbuf[0] == '\0' || ipnvl == NULL)
- return (EINVAL);
+ return (IPADM_INVALID_ARG);
*ipnvl = NULL;
/*
* If IPADM_NORVAL is set, then `inbuf' should be comma delimited values
*/
if ((flags & IPADM_NORVAL) && strchr(inbuf, '=') != NULL)
- return (EINVAL);
+ return (IPADM_INVALID_ARG);
if ((cp = buf = strdup(inbuf)) == NULL)
- return (errno);
+ return (ipadm_errno2status(errno));
while (isspace(*buf))
buf++;
if (*buf == '\0') {
- err = EINVAL;
+ status = IPADM_INVALID_ARG;
goto fail;
}
@@ -658,22 +830,26 @@ ipadm_str2nvlist(const char *inbuf, nvlist_t **ipnvl, uint_t flags)
if ((val = strchr(nv, '=')) != NULL)
*val++ = '\0';
if (*ipnvl == NULL &&
- (err = nvlist_alloc(ipnvl, NV_UNIQUE_NAME, 0)) != 0)
+ (err = nvlist_alloc(ipnvl, NV_UNIQUE_NAME, 0)) != 0) {
+ status = ipadm_errno2status(err);
goto fail;
+ }
if (nvlist_exists(*ipnvl, name)) {
- err = EEXIST;
+ status = IPADM_EXISTS;
goto fail;
}
/* Add the extracted nvpair to the nvlist `ipnvl'. */
- (void) i_ipadm_add_nvpair(*ipnvl, name, val);
+ status = i_ipadm_add_nvpair(*ipnvl, name, val);
+ if (status != IPADM_SUCCESS)
+ goto fail;
}
free(cp);
- return (0);
+ return (IPADM_SUCCESS);
fail:
free(cp);
nvlist_free(*ipnvl);
*ipnvl = NULL;
- return (err);
+ return (status);
}
/*