5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2016 Argo Technologie SA.
25 */
26
27 /*
28 * Contains DB walker functions, which are of type `db_wfunc_t';
29 *
30 * typedef boolean_t db_wfunc_t(void *cbarg, nvlist_t *db_nvl, char *buf,
31 * size_t bufsize, int *errp);
32 *
33 * ipadm_rw_db() walks through the data store, one line at a time and calls
34 * these call back functions with:
35 * `cbarg' - callback argument
36 * `db_nvl' - representing a line from DB in nvlist_t form
37 * `buf' - character buffer to hold modified line
38 * `bufsize'- size of the buffer
39 * `errp' - captures any error inside the walker function.
40 *
41 * All the 'write' callback functions modify `db_nvl' based on `cbarg' and
42 * copy string representation of `db_nvl' (using ipadm_nvlist2str()) into `buf'.
43 * To delete a line from the DB, buf[0] is set to `\0'. Inside ipadm_rw_db(),
44 * the modified `buf' is written back into DB.
891 int err = 0;
892 ipadm_db_op_t db_op;
893
894 (void) pthread_rwlock_wrlock(&aobjmap.aobjmap_rwlock);
895
896 head = aobjmap.aobjmap_head;
897 switch (op) {
898 case ADDROBJ_ADD:
899 /*
900 * check for stub nodes (added by ADDROBJ_LOOKUPADD) and
901 * update, else add the new node.
902 */
903 for (; head != NULL; head = head->am_next) {
904 /*
905 * For IPv6, we need to distinguish between the
906 * linklocal and non-linklocal nodes
907 */
908 if (strcmp(head->am_aobjname,
909 nodep->am_aobjname) == 0 &&
910 (head->am_atype != IPADM_ADDR_IPV6_ADDRCONF ||
911 head->am_linklocal == nodep->am_linklocal))
912 break;
913 }
914
915 if (head != NULL) {
916 /* update the node */
917 (void) strlcpy(head->am_ifname, nodep->am_ifname,
918 sizeof (head->am_ifname));
919 head->am_lnum = nodep->am_lnum;
920 head->am_family = nodep->am_family;
921 head->am_flags = nodep->am_flags;
922 head->am_atype = nodep->am_atype;
923 if (head->am_atype == IPADM_ADDR_IPV6_ADDRCONF) {
924 head->am_ifid = nodep->am_ifid;
925 head->am_linklocal = nodep->am_linklocal;
926 }
927 } else {
928 for (head = aobjmap.aobjmap_head; head != NULL;
929 head = head->am_next) {
930 if (strcmp(head->am_ifname,
931 nodep->am_ifname) == 0)
932 break;
933 }
934 nodep->am_nextnum = (head == NULL ? 0 :
935 head->am_nextnum);
936 err = i_ipmgmt_add_amnode(nodep);
937 }
938 db_op = IPADM_DB_WRITE;
939 break;
940 case ADDROBJ_DELETE:
941 prev = head;
942 while (head != NULL) {
943 if (strcmp(head->am_aobjname,
944 nodep->am_aobjname) == 0) {
945 nodep->am_atype = head->am_atype;
946 /*
1051 if ((err = nvlist_add_string(*nvl, IPADM_NVP_IFNAME,
1052 np->am_ifname)) != 0)
1053 goto fail;
1054
1055 (void) snprintf(strval, IPMGMT_STRSIZE, "%d", np->am_lnum);
1056 if ((err = nvlist_add_string(*nvl, IPADM_NVP_LIFNUM, strval)) != 0)
1057 goto fail;
1058
1059 (void) snprintf(strval, IPMGMT_STRSIZE, "%d", np->am_family);
1060 if ((err = nvlist_add_string(*nvl, IPADM_NVP_FAMILY, strval)) != 0)
1061 goto fail;
1062
1063 (void) snprintf(strval, IPMGMT_STRSIZE, "%d", np->am_flags);
1064 if ((err = nvlist_add_string(*nvl, FLAGS, strval)) != 0)
1065 goto fail;
1066
1067 (void) snprintf(strval, IPMGMT_STRSIZE, "%d", np->am_atype);
1068 if ((err = nvlist_add_string(*nvl, ATYPE, strval)) != 0)
1069 goto fail;
1070
1071 if (np->am_atype == IPADM_ADDR_IPV6_ADDRCONF) {
1072 struct sockaddr_in6 *in6;
1073
1074 in6 = (struct sockaddr_in6 *)&np->am_ifid;
1075 if (np->am_linklocal &&
1076 IN6_IS_ADDR_UNSPECIFIED(&in6->sin6_addr)) {
1077 if ((err = nvlist_add_string(*nvl, IPADM_NVP_IPNUMADDR,
1078 "default")) != 0)
1079 goto fail;
1080 } else {
1081 if (inet_ntop(AF_INET6, &in6->sin6_addr, strval,
1082 IPMGMT_STRSIZE) == NULL) {
1083 err = errno;
1084 goto fail;
1085 }
1086 if ((err = nvlist_add_string(*nvl, IPADM_NVP_IPNUMADDR,
1087 strval)) != 0)
1088 goto fail;
1089 }
1090 } else {
1091 if ((err = nvlist_add_string(*nvl, IPADM_NVP_IPNUMADDR,
1092 "")) != 0)
1093 goto fail;
1094 }
1095 return (err);
1096 fail:
1097 nvlist_free(*nvl);
1098 return (err);
1099 }
1100
1101 /*
1102 * Read the aobjmap data store and build the in-memory representation
1103 * of the aobjmap. We don't need to hold any locks while building this as
1104 * we do this in very early stage of daemon coming up, even before the door
1105 * is opened.
1106 */
1107 /* ARGSUSED */
1108 extern boolean_t
1109 ipmgmt_aobjmap_init(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,
1110 int *errp)
1111 {
1112 nvpair_t *nvp = NULL;
1113 char *name, *strval = NULL;
1121 name = nvpair_name(nvp);
1122
1123 if ((*errp = nvpair_value_string(nvp, &strval)) != 0)
1124 return (B_TRUE);
1125 if (strcmp(IPADM_NVP_AOBJNAME, name) == 0) {
1126 (void) strlcpy(node.am_aobjname, strval,
1127 sizeof (node.am_aobjname));
1128 } else if (strcmp(IPADM_NVP_IFNAME, name) == 0) {
1129 (void) strlcpy(node.am_ifname, strval,
1130 sizeof (node.am_ifname));
1131 } else if (strcmp(IPADM_NVP_LIFNUM, name) == 0) {
1132 node.am_lnum = atoi(strval);
1133 } else if (strcmp(IPADM_NVP_FAMILY, name) == 0) {
1134 node.am_family = (sa_family_t)atoi(strval);
1135 } else if (strcmp(FLAGS, name) == 0) {
1136 node.am_flags = atoi(strval);
1137 } else if (strcmp(ATYPE, name) == 0) {
1138 node.am_atype = (ipadm_addr_type_t)atoi(strval);
1139 } else if (strcmp(IPADM_NVP_IPNUMADDR, name) == 0) {
1140 if (node.am_atype == IPADM_ADDR_IPV6_ADDRCONF) {
1141 in6 = (struct sockaddr_in6 *)&node.am_ifid;
1142 if (strcmp(strval, "default") == 0) {
1143 bzero(in6, sizeof (node.am_ifid));
1144 node.am_linklocal = B_TRUE;
1145 } else {
1146 (void) inet_pton(AF_INET6, strval,
1147 &in6->sin6_addr);
1148 if (IN6_IS_ADDR_UNSPECIFIED(
1149 &in6->sin6_addr))
1150 node.am_linklocal = B_TRUE;
1151 }
1152 }
1153 }
1154 }
1155
1156 /* we have all the information we need, add the node */
1157 *errp = i_ipmgmt_add_amnode(&node);
1158
1159 return (B_TRUE);
1160 }
1161
1162 /*
1163 * Updates an entry from the temporary cache file, which matches the given
1164 * address object name.
1165 */
1166 /* ARGSUSED */
1167 static boolean_t
1168 ipmgmt_update_aobjmap(void *arg, nvlist_t *db_nvl, char *buf,
1169 size_t buflen, int *errp)
1170 {
|
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2016 Argo Technologie SA.
25 * Copyright (c) 2016, Chris Fraire <cfraire@me.com>.
26 */
27
28 /*
29 * Contains DB walker functions, which are of type `db_wfunc_t';
30 *
31 * typedef boolean_t db_wfunc_t(void *cbarg, nvlist_t *db_nvl, char *buf,
32 * size_t bufsize, int *errp);
33 *
34 * ipadm_rw_db() walks through the data store, one line at a time and calls
35 * these call back functions with:
36 * `cbarg' - callback argument
37 * `db_nvl' - representing a line from DB in nvlist_t form
38 * `buf' - character buffer to hold modified line
39 * `bufsize'- size of the buffer
40 * `errp' - captures any error inside the walker function.
41 *
42 * All the 'write' callback functions modify `db_nvl' based on `cbarg' and
43 * copy string representation of `db_nvl' (using ipadm_nvlist2str()) into `buf'.
44 * To delete a line from the DB, buf[0] is set to `\0'. Inside ipadm_rw_db(),
45 * the modified `buf' is written back into DB.
892 int err = 0;
893 ipadm_db_op_t db_op;
894
895 (void) pthread_rwlock_wrlock(&aobjmap.aobjmap_rwlock);
896
897 head = aobjmap.aobjmap_head;
898 switch (op) {
899 case ADDROBJ_ADD:
900 /*
901 * check for stub nodes (added by ADDROBJ_LOOKUPADD) and
902 * update, else add the new node.
903 */
904 for (; head != NULL; head = head->am_next) {
905 /*
906 * For IPv6, we need to distinguish between the
907 * linklocal and non-linklocal nodes
908 */
909 if (strcmp(head->am_aobjname,
910 nodep->am_aobjname) == 0 &&
911 (head->am_atype != IPADM_ADDR_IPV6_ADDRCONF ||
912 head->ipmgmt_am_linklocal ==
913 nodep->ipmgmt_am_linklocal))
914 break;
915 }
916
917 if (head != NULL) {
918 /* update the node */
919 (void) strlcpy(head->am_ifname, nodep->am_ifname,
920 sizeof (head->am_ifname));
921 head->am_lnum = nodep->am_lnum;
922 head->am_family = nodep->am_family;
923 head->am_flags = nodep->am_flags;
924 head->am_atype = nodep->am_atype;
925 (void) memcpy(&head->am_atype_cache, &nodep->am_atype_cache,
926 sizeof (head->am_atype_cache));
927 } else {
928 for (head = aobjmap.aobjmap_head; head != NULL;
929 head = head->am_next) {
930 if (strcmp(head->am_ifname,
931 nodep->am_ifname) == 0)
932 break;
933 }
934 nodep->am_nextnum = (head == NULL ? 0 :
935 head->am_nextnum);
936 err = i_ipmgmt_add_amnode(nodep);
937 }
938 db_op = IPADM_DB_WRITE;
939 break;
940 case ADDROBJ_DELETE:
941 prev = head;
942 while (head != NULL) {
943 if (strcmp(head->am_aobjname,
944 nodep->am_aobjname) == 0) {
945 nodep->am_atype = head->am_atype;
946 /*
1051 if ((err = nvlist_add_string(*nvl, IPADM_NVP_IFNAME,
1052 np->am_ifname)) != 0)
1053 goto fail;
1054
1055 (void) snprintf(strval, IPMGMT_STRSIZE, "%d", np->am_lnum);
1056 if ((err = nvlist_add_string(*nvl, IPADM_NVP_LIFNUM, strval)) != 0)
1057 goto fail;
1058
1059 (void) snprintf(strval, IPMGMT_STRSIZE, "%d", np->am_family);
1060 if ((err = nvlist_add_string(*nvl, IPADM_NVP_FAMILY, strval)) != 0)
1061 goto fail;
1062
1063 (void) snprintf(strval, IPMGMT_STRSIZE, "%d", np->am_flags);
1064 if ((err = nvlist_add_string(*nvl, FLAGS, strval)) != 0)
1065 goto fail;
1066
1067 (void) snprintf(strval, IPMGMT_STRSIZE, "%d", np->am_atype);
1068 if ((err = nvlist_add_string(*nvl, ATYPE, strval)) != 0)
1069 goto fail;
1070
1071 switch (np->am_atype) {
1072 case IPADM_ADDR_IPV6_ADDRCONF: {
1073 struct sockaddr_in6 *in6;
1074
1075 in6 = &np->ipmgmt_am_ifid;
1076 if (np->ipmgmt_am_linklocal &&
1077 IN6_IS_ADDR_UNSPECIFIED(&in6->sin6_addr)) {
1078 if ((err = nvlist_add_string(*nvl, IPADM_NVP_IPNUMADDR,
1079 "default")) != 0)
1080 goto fail;
1081 } else {
1082 if (inet_ntop(AF_INET6, &in6->sin6_addr, strval,
1083 IPMGMT_STRSIZE) == NULL) {
1084 err = errno;
1085 goto fail;
1086 }
1087 if ((err = nvlist_add_string(*nvl, IPADM_NVP_IPNUMADDR,
1088 strval)) != 0)
1089 goto fail;
1090 }
1091 }
1092 break;
1093 case IPADM_ADDR_DHCP: {
1094 if (np->ipmgmt_am_reqhost &&
1095 *np->ipmgmt_am_reqhost != '\0' &&
1096 (err = nvlist_add_string(*nvl, IPADM_NVP_REQHOST,
1097 np->ipmgmt_am_reqhost)) != 0)
1098 goto fail;
1099 }
1100 /* FALLTHRU */
1101 default:
1102 if ((err = nvlist_add_string(*nvl, IPADM_NVP_IPNUMADDR,
1103 "")) != 0)
1104 goto fail;
1105 break;
1106 }
1107 return (err);
1108 fail:
1109 nvlist_free(*nvl);
1110 return (err);
1111 }
1112
1113 /*
1114 * Read the aobjmap data store and build the in-memory representation
1115 * of the aobjmap. We don't need to hold any locks while building this as
1116 * we do this in very early stage of daemon coming up, even before the door
1117 * is opened.
1118 */
1119 /* ARGSUSED */
1120 extern boolean_t
1121 ipmgmt_aobjmap_init(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,
1122 int *errp)
1123 {
1124 nvpair_t *nvp = NULL;
1125 char *name, *strval = NULL;
1133 name = nvpair_name(nvp);
1134
1135 if ((*errp = nvpair_value_string(nvp, &strval)) != 0)
1136 return (B_TRUE);
1137 if (strcmp(IPADM_NVP_AOBJNAME, name) == 0) {
1138 (void) strlcpy(node.am_aobjname, strval,
1139 sizeof (node.am_aobjname));
1140 } else if (strcmp(IPADM_NVP_IFNAME, name) == 0) {
1141 (void) strlcpy(node.am_ifname, strval,
1142 sizeof (node.am_ifname));
1143 } else if (strcmp(IPADM_NVP_LIFNUM, name) == 0) {
1144 node.am_lnum = atoi(strval);
1145 } else if (strcmp(IPADM_NVP_FAMILY, name) == 0) {
1146 node.am_family = (sa_family_t)atoi(strval);
1147 } else if (strcmp(FLAGS, name) == 0) {
1148 node.am_flags = atoi(strval);
1149 } else if (strcmp(ATYPE, name) == 0) {
1150 node.am_atype = (ipadm_addr_type_t)atoi(strval);
1151 } else if (strcmp(IPADM_NVP_IPNUMADDR, name) == 0) {
1152 if (node.am_atype == IPADM_ADDR_IPV6_ADDRCONF) {
1153 in6 = &node.ipmgmt_am_ifid;
1154 if (strcmp(strval, "default") == 0) {
1155 bzero(in6, sizeof (node.ipmgmt_am_ifid));
1156 node.ipmgmt_am_linklocal = B_TRUE;
1157 } else {
1158 (void) inet_pton(AF_INET6, strval,
1159 &in6->sin6_addr);
1160 if (IN6_IS_ADDR_UNSPECIFIED(
1161 &in6->sin6_addr))
1162 node.ipmgmt_am_linklocal = B_TRUE;
1163 }
1164 }
1165 }
1166 }
1167
1168 /* we have all the information we need, add the node */
1169 *errp = i_ipmgmt_add_amnode(&node);
1170
1171 return (B_TRUE);
1172 }
1173
1174 /*
1175 * Updates an entry from the temporary cache file, which matches the given
1176 * address object name.
1177 */
1178 /* ARGSUSED */
1179 static boolean_t
1180 ipmgmt_update_aobjmap(void *arg, nvlist_t *db_nvl, char *buf,
1181 size_t buflen, int *errp)
1182 {
|