Print this page
7388 Support DHCP Client FQDN. Allow IAID/DUID for all v4.


   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 {