4  * The contents of this file are subject to the terms of the
   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(),
 
 
 367                         cbarg->cb_ocnt++;
 368         }
 369         return (B_TRUE);
 370 }
 371 
 372 /*
 373  * This function only gets called if a volatile filesystem version
 374  * of the configuration file has been created. This only happens in the
 375  * extremely rare case that a request has been made to update the configuration
 376  * file at boottime while the root filesystem was read-only. This is
 377  * really a rare occurrence now that we don't support UFS root filesystems
 378  * any longer. This function will periodically attempt to write the
 379  * configuration back to its location on the root filesystem. Success
 380  * will indicate that the filesystem is no longer read-only.
 381  */
 382 /* ARGSUSED */
 383 static void *
 384 ipmgmt_db_restore_thread(void *arg)
 385 {
 386         int err;
 387 
 388         for (;;) {
 389                 (void) sleep(5);
 390                 (void) pthread_rwlock_wrlock(&ipmgmt_dbconf_lock);
 391                 if (!ipmgmt_rdonly_root)
 392                         break;
 393                 err = ipmgmt_cpfile(IPADM_VOL_DB_FILE, IPADM_DB_FILE, B_FALSE);
 394                 if (err == 0) {
 395                         ipmgmt_rdonly_root = B_FALSE;
 396                         break;
 397                 }
 398                 (void) pthread_rwlock_unlock(&ipmgmt_dbconf_lock);
 399         }
 400         (void) pthread_rwlock_unlock(&ipmgmt_dbconf_lock);
 401         return (NULL);
 402 }
 403 
 404 /*
 405  * This function takes the appropriate lock, read or write, based on the
 406  * `db_op' and then calls DB walker ipadm_rw_db(). The code is complicated
 407  * by the fact that we are not always guaranteed to have a writable root
 408  * filesystem since it is possible that we are reading or writing during
 409  * bootime while the root filesystem is still read-only. This is, by far,
 410  * the exception case. Normally, this function will be called when the
 411  * root filesystem is writable. In the unusual case where this is not
 412  * true, the configuration file is copied to the volatile file system
 413  * and is updated there until the root filesystem becomes writable. At
 414  * that time the file will be moved back to its proper location by
 415  * ipmgmt_db_restore_thread().
 416  */
 417 extern int
 418 ipmgmt_db_walk(db_wfunc_t *db_walk_func, void *db_warg, ipadm_db_op_t db_op)
 419 {
 420         int             err;
 421         boolean_t       writeop;
 422         mode_t          mode;
 423         pthread_t       tid;
 424         pthread_attr_t  attr;
 425 
 426         writeop = (db_op != IPADM_DB_READ);
 427         if (writeop) {
 428                 (void) pthread_rwlock_wrlock(&ipmgmt_dbconf_lock);
 429                 mode = IPADM_FILE_MODE;
 430         } else {
 431                 (void) pthread_rwlock_rdlock(&ipmgmt_dbconf_lock);
 432                 mode = 0;
 433         }
 434 
 435         /*
 436          * Did a previous write attempt fail? If so, don't even try to
 437          * read/write to IPADM_DB_FILE.
 438          */
 439         if (!ipmgmt_rdonly_root) {
 440                 err = ipadm_rw_db(db_walk_func, db_warg, IPADM_DB_FILE,
 441                     mode, db_op);
 442                 if (err != EROFS)
 443                         goto done;
 444         }
 445 
 446         /*
 447          * If we haven't already copied the file to the volatile
 448          * file system, do so. This should only happen on a failed
 449          * writeop(i.e., we have acquired the write lock above).
 450          */
 451         if (access(IPADM_VOL_DB_FILE, F_OK) != 0) {
 452                 assert(writeop);
 453                 err = ipmgmt_cpfile(IPADM_DB_FILE, IPADM_VOL_DB_FILE, B_TRUE);
 454                 if (err != 0)
 455                         goto done;
 456                 (void) pthread_attr_init(&attr);
 457                 (void) pthread_attr_setdetachstate(&attr,
 458                     PTHREAD_CREATE_DETACHED);
 459                 err = pthread_create(&tid, &attr, ipmgmt_db_restore_thread,
 460                     NULL);
 461                 (void) pthread_attr_destroy(&attr);
 462                 if (err != 0) {
 463                         (void) unlink(IPADM_VOL_DB_FILE);
 464                         goto done;
 465                 }
 466                 ipmgmt_rdonly_root = B_TRUE;
 467         }
 468 
 469         /*
 470          * Read/write from the volatile copy.
 471          */
 472         err = ipadm_rw_db(db_walk_func, db_warg, IPADM_VOL_DB_FILE,
 473             mode, db_op);
 474 done:
 475         (void) pthread_rwlock_unlock(&ipmgmt_dbconf_lock);
 476         return (err);
 477 }
 478 
 479 /*
 480  * Used to add an entry towards the end of DB. It just returns B_TRUE for
 481  * every line of the DB. When we reach the end, ipadm_rw_db() adds the
 482  * line at the end.
 483  */
 484 /* ARGSUSED */
 485 boolean_t
 486 ipmgmt_db_add(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen, int *errp)
 487 {
 488         return (B_TRUE);
 489 }
 490 
 491 /*
 492  * This function is used to update or create an entry in DB. The nvlist_t,
 
1220                     &db_lifnumstr) != 0 || atoi(db_lifnumstr) != nodep->am_lnum)
1221                         return (B_TRUE);
1222         }
1223 
1224         /* we found the match, delete the line from the db */
1225         buf[0] = '\0';
1226 
1227         /* stop the walker */
1228         return (B_FALSE);
1229 }
1230 
1231 /*
1232  * Adds or deletes aobjmap node information into a temporary cache file.
1233  */
1234 extern int
1235 ipmgmt_persist_aobjmap(ipmgmt_aobjmap_t *nodep, ipadm_db_op_t op)
1236 {
1237         int                     err;
1238         ipadm_dbwrite_cbarg_t   cb;
1239         nvlist_t                *nvl = NULL;
1240 
1241         if (op == IPADM_DB_WRITE) {
1242                 if ((err = i_ipmgmt_node2nvl(&nvl, nodep)) != 0)
1243                         return (err);
1244                 cb.dbw_nvl = nvl;
1245                 if (nodep->am_atype == IPADM_ADDR_IPV6_ADDRCONF)
1246                         cb.dbw_flags = IPMGMT_ATYPE_V6ACONF;
1247                 else
1248                         cb.dbw_flags = 0;
1249 
1250                 err = ipadm_rw_db(ipmgmt_update_aobjmap, &cb,
1251                     ADDROBJ_MAPPING_DB_FILE, IPADM_FILE_MODE, IPADM_DB_WRITE);
1252                 nvlist_free(nvl);
1253         } else {
1254                 assert(op == IPADM_DB_DELETE);
1255 
1256                 err = ipadm_rw_db(ipmgmt_delete_aobjmap, nodep,
1257                     ADDROBJ_MAPPING_DB_FILE, IPADM_FILE_MODE, IPADM_DB_DELETE);
1258         }
1259         return (err);
1260 }
1261 
1262 /*
1263  * upgrades the ipadm data-store. It renames all the old private protocol
1264  * property names which start with leading protocol names to begin with
1265  * IPADM_PRIV_PROP_PREFIX.
1266  */
1267 /* ARGSUSED */
1268 boolean_t
1269 ipmgmt_db_upgrade(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,
1270     int *errp)
1271 {
1272         nvpair_t        *nvp;
1273         char            *name, *pname = NULL, *protostr = NULL, *pval = NULL;
1274         uint_t          proto, nproto;
1275         char            nname[IPMGMT_STRSIZE], tmpstr[IPMGMT_STRSIZE];
1276 
1277         *errp = 0;
 
 | 
 
 
   4  * The contents of this file are subject to the terms of the
   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 2015 Joyent, Inc.
  25  * Copyright 2016 Argo Technologie SA.
  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(),
 
 
 368                         cbarg->cb_ocnt++;
 369         }
 370         return (B_TRUE);
 371 }
 372 
 373 /*
 374  * This function only gets called if a volatile filesystem version
 375  * of the configuration file has been created. This only happens in the
 376  * extremely rare case that a request has been made to update the configuration
 377  * file at boottime while the root filesystem was read-only. This is
 378  * really a rare occurrence now that we don't support UFS root filesystems
 379  * any longer. This function will periodically attempt to write the
 380  * configuration back to its location on the root filesystem. Success
 381  * will indicate that the filesystem is no longer read-only.
 382  */
 383 /* ARGSUSED */
 384 static void *
 385 ipmgmt_db_restore_thread(void *arg)
 386 {
 387         int err;
 388         char confpath[MAXPATHLEN];
 389         char tmpconfpath[MAXPATHLEN];
 390 
 391         ipmgmt_path(IPADM_PATH_DB, confpath, sizeof (confpath));
 392         ipmgmt_path(IPADM_PATH_VOL_DB, tmpconfpath, sizeof (tmpconfpath));
 393 
 394         for (;;) {
 395                 (void) sleep(5);
 396                 (void) pthread_rwlock_wrlock(&ipmgmt_dbconf_lock);
 397                 if (!ipmgmt_rdonly_root)
 398                         break;
 399                 err = ipmgmt_cpfile(tmpconfpath, confpath, B_FALSE);
 400                 if (err == 0) {
 401                         ipmgmt_rdonly_root = B_FALSE;
 402                         break;
 403                 }
 404                 (void) pthread_rwlock_unlock(&ipmgmt_dbconf_lock);
 405         }
 406         (void) pthread_rwlock_unlock(&ipmgmt_dbconf_lock);
 407         return (NULL);
 408 }
 409 
 410 /*
 411  * This function takes the appropriate lock, read or write, based on the
 412  * `db_op' and then calls DB walker ipadm_rw_db(). The code is complicated
 413  * by the fact that we are not always guaranteed to have a writable root
 414  * filesystem since it is possible that we are reading or writing during
 415  * bootime while the root filesystem is still read-only. This is, by far,
 416  * the exception case. Normally, this function will be called when the
 417  * root filesystem is writable. In the unusual case where this is not
 418  * true, the configuration file is copied to the volatile file system
 419  * and is updated there until the root filesystem becomes writable. At
 420  * that time the file will be moved back to its proper location by
 421  * ipmgmt_db_restore_thread().
 422  */
 423 extern int
 424 ipmgmt_db_walk(db_wfunc_t *db_walk_func, void *db_warg, ipadm_db_op_t db_op)
 425 {
 426         int             err;
 427         boolean_t       writeop;
 428         mode_t          mode;
 429         pthread_t       tid;
 430         pthread_attr_t  attr;
 431         char            confpath[MAXPATHLEN];
 432         char            tmpconfpath[MAXPATHLEN];
 433 
 434         ipmgmt_path(IPADM_PATH_DB, confpath, sizeof (confpath));
 435         ipmgmt_path(IPADM_PATH_VOL_DB, tmpconfpath, sizeof (tmpconfpath));
 436 
 437         writeop = (db_op != IPADM_DB_READ);
 438         if (writeop) {
 439                 (void) pthread_rwlock_wrlock(&ipmgmt_dbconf_lock);
 440                 mode = IPADM_FILE_MODE;
 441         } else {
 442                 (void) pthread_rwlock_rdlock(&ipmgmt_dbconf_lock);
 443                 mode = 0;
 444         }
 445 
 446         /*
 447          * Did a previous write attempt fail? If so, don't even try to
 448          * read/write to the permanent configuration file.
 449          */
 450         if (!ipmgmt_rdonly_root) {
 451                 err = ipadm_rw_db(db_walk_func, db_warg, confpath, mode, db_op);
 452                 if (err != EROFS)
 453                         goto done;
 454         }
 455 
 456         /*
 457          * If we haven't already copied the file to the volatile
 458          * file system, do so. This should only happen on a failed
 459          * writeop (i.e., we have acquired the write lock above).
 460          */
 461         if (access(tmpconfpath, F_OK) != 0) {
 462                 assert(writeop);
 463                 err = ipmgmt_cpfile(confpath, tmpconfpath, B_TRUE);
 464                 if (err != 0)
 465                         goto done;
 466                 (void) pthread_attr_init(&attr);
 467                 (void) pthread_attr_setdetachstate(&attr,
 468                     PTHREAD_CREATE_DETACHED);
 469                 err = pthread_create(&tid, &attr, ipmgmt_db_restore_thread,
 470                     NULL);
 471                 (void) pthread_attr_destroy(&attr);
 472                 if (err != 0) {
 473                         (void) unlink(tmpconfpath);
 474                         goto done;
 475                 }
 476                 ipmgmt_rdonly_root = B_TRUE;
 477         }
 478 
 479         /*
 480          * Read/write from the volatile copy.
 481          */
 482         err = ipadm_rw_db(db_walk_func, db_warg, tmpconfpath,
 483             mode, db_op);
 484 done:
 485         (void) pthread_rwlock_unlock(&ipmgmt_dbconf_lock);
 486         return (err);
 487 }
 488 
 489 /*
 490  * Used to add an entry towards the end of DB. It just returns B_TRUE for
 491  * every line of the DB. When we reach the end, ipadm_rw_db() adds the
 492  * line at the end.
 493  */
 494 /* ARGSUSED */
 495 boolean_t
 496 ipmgmt_db_add(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen, int *errp)
 497 {
 498         return (B_TRUE);
 499 }
 500 
 501 /*
 502  * This function is used to update or create an entry in DB. The nvlist_t,
 
1230                     &db_lifnumstr) != 0 || atoi(db_lifnumstr) != nodep->am_lnum)
1231                         return (B_TRUE);
1232         }
1233 
1234         /* we found the match, delete the line from the db */
1235         buf[0] = '\0';
1236 
1237         /* stop the walker */
1238         return (B_FALSE);
1239 }
1240 
1241 /*
1242  * Adds or deletes aobjmap node information into a temporary cache file.
1243  */
1244 extern int
1245 ipmgmt_persist_aobjmap(ipmgmt_aobjmap_t *nodep, ipadm_db_op_t op)
1246 {
1247         int                     err;
1248         ipadm_dbwrite_cbarg_t   cb;
1249         nvlist_t                *nvl = NULL;
1250         char                    aobjpath[MAXPATHLEN];
1251 
1252         ipmgmt_path(IPADM_PATH_ADDROBJ_MAP_DB, aobjpath, sizeof (aobjpath));
1253 
1254         if (op == IPADM_DB_WRITE) {
1255                 if ((err = i_ipmgmt_node2nvl(&nvl, nodep)) != 0)
1256                         return (err);
1257                 cb.dbw_nvl = nvl;
1258                 if (nodep->am_atype == IPADM_ADDR_IPV6_ADDRCONF)
1259                         cb.dbw_flags = IPMGMT_ATYPE_V6ACONF;
1260                 else
1261                         cb.dbw_flags = 0;
1262 
1263                 err = ipadm_rw_db(ipmgmt_update_aobjmap, &cb, aobjpath,
1264                     IPADM_FILE_MODE, IPADM_DB_WRITE);
1265                 nvlist_free(nvl);
1266         } else {
1267                 assert(op == IPADM_DB_DELETE);
1268 
1269                 err = ipadm_rw_db(ipmgmt_delete_aobjmap, nodep, aobjpath,
1270                     IPADM_FILE_MODE, IPADM_DB_DELETE);
1271         }
1272         return (err);
1273 }
1274 
1275 /*
1276  * upgrades the ipadm data-store. It renames all the old private protocol
1277  * property names which start with leading protocol names to begin with
1278  * IPADM_PRIV_PROP_PREFIX.
1279  */
1280 /* ARGSUSED */
1281 boolean_t
1282 ipmgmt_db_upgrade(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,
1283     int *errp)
1284 {
1285         nvpair_t        *nvp;
1286         char            *name, *pname = NULL, *protostr = NULL, *pval = NULL;
1287         uint_t          proto, nproto;
1288         char            nname[IPMGMT_STRSIZE], tmpstr[IPMGMT_STRSIZE];
1289 
1290         *errp = 0;
 
 |