17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5ba2e4443Sseb * Common Development and Distribution License (the "License"). 6ba2e4443Sseb * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*d62bc4baSyz147064 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <unistd.h> 297c478bd9Sstevel@tonic-gate #include <stropts.h> 307c478bd9Sstevel@tonic-gate #include <errno.h> 31*d62bc4baSyz147064 #include <ctype.h> 320ba2cbe9Sxc151355 #include <fcntl.h> 330ba2cbe9Sxc151355 #include <strings.h> 340ba2cbe9Sxc151355 #include <dirent.h> 350ba2cbe9Sxc151355 #include <sys/stat.h> 360ba2cbe9Sxc151355 #include <libdladm_impl.h> 3733343a97Smeem #include <libintl.h> 38*d62bc4baSyz147064 #include <libdlpi.h> 39aae21359Skrgopi 400ba2cbe9Sxc151355 static char dladm_rootdir[MAXPATHLEN] = "/"; 410ba2cbe9Sxc151355 427c478bd9Sstevel@tonic-gate /* 437c478bd9Sstevel@tonic-gate * Issue an ioctl to the specified file descriptor attached to the 447c478bd9Sstevel@tonic-gate * DLD control driver interface. 457c478bd9Sstevel@tonic-gate */ 460ba2cbe9Sxc151355 int 47210db224Sericheng i_dladm_ioctl(int fd, int ic_cmd, void *ic_dp, int ic_len) 487c478bd9Sstevel@tonic-gate { 497c478bd9Sstevel@tonic-gate struct strioctl iocb; 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate iocb.ic_cmd = ic_cmd; 527c478bd9Sstevel@tonic-gate iocb.ic_timout = 0; 537c478bd9Sstevel@tonic-gate iocb.ic_len = ic_len; 54210db224Sericheng iocb.ic_dp = (char *)ic_dp; 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate return (ioctl(fd, I_STR, &iocb)); 577c478bd9Sstevel@tonic-gate } 587c478bd9Sstevel@tonic-gate 590ba2cbe9Sxc151355 const char * 600ba2cbe9Sxc151355 dladm_status2str(dladm_status_t status, char *buf) 610ba2cbe9Sxc151355 { 620ba2cbe9Sxc151355 const char *s; 630ba2cbe9Sxc151355 640ba2cbe9Sxc151355 switch (status) { 650ba2cbe9Sxc151355 case DLADM_STATUS_OK: 660ba2cbe9Sxc151355 s = "ok"; 670ba2cbe9Sxc151355 break; 680ba2cbe9Sxc151355 case DLADM_STATUS_BADARG: 690ba2cbe9Sxc151355 s = "invalid argument"; 700ba2cbe9Sxc151355 break; 710ba2cbe9Sxc151355 case DLADM_STATUS_FAILED: 720ba2cbe9Sxc151355 s = "operation failed"; 730ba2cbe9Sxc151355 break; 740ba2cbe9Sxc151355 case DLADM_STATUS_TOOSMALL: 750ba2cbe9Sxc151355 s = "buffer size too small"; 760ba2cbe9Sxc151355 break; 770ba2cbe9Sxc151355 case DLADM_STATUS_NOTSUP: 780ba2cbe9Sxc151355 s = "operation not supported"; 790ba2cbe9Sxc151355 break; 800ba2cbe9Sxc151355 case DLADM_STATUS_NOTFOUND: 810ba2cbe9Sxc151355 s = "object not found"; 820ba2cbe9Sxc151355 break; 830ba2cbe9Sxc151355 case DLADM_STATUS_BADVAL: 840ba2cbe9Sxc151355 s = "invalid value"; 850ba2cbe9Sxc151355 break; 860ba2cbe9Sxc151355 case DLADM_STATUS_NOMEM: 870ba2cbe9Sxc151355 s = "insufficient memory"; 880ba2cbe9Sxc151355 break; 890ba2cbe9Sxc151355 case DLADM_STATUS_EXIST: 900ba2cbe9Sxc151355 s = "object already exists"; 910ba2cbe9Sxc151355 break; 920ba2cbe9Sxc151355 case DLADM_STATUS_LINKINVAL: 930ba2cbe9Sxc151355 s = "invalid link"; 940ba2cbe9Sxc151355 break; 950ba2cbe9Sxc151355 case DLADM_STATUS_PROPRDONLY: 960ba2cbe9Sxc151355 s = "read-only property"; 970ba2cbe9Sxc151355 break; 980ba2cbe9Sxc151355 case DLADM_STATUS_BADVALCNT: 990ba2cbe9Sxc151355 s = "invalid number of values"; 1000ba2cbe9Sxc151355 break; 1010ba2cbe9Sxc151355 case DLADM_STATUS_DBNOTFOUND: 1020ba2cbe9Sxc151355 s = "database not found"; 1030ba2cbe9Sxc151355 break; 1040ba2cbe9Sxc151355 case DLADM_STATUS_DENIED: 1050ba2cbe9Sxc151355 s = "permission denied"; 1060ba2cbe9Sxc151355 break; 1070ba2cbe9Sxc151355 case DLADM_STATUS_IOERR: 1080ba2cbe9Sxc151355 s = "I/O error"; 1090ba2cbe9Sxc151355 break; 110f4b3ec61Sdh155122 case DLADM_STATUS_TEMPONLY: 111f4b3ec61Sdh155122 s = "change cannot be persistent, specify -t please"; 112f4b3ec61Sdh155122 break; 113f595a68aSyz147064 case DLADM_STATUS_TIMEDOUT: 114f595a68aSyz147064 s = "operation timed out"; 115f595a68aSyz147064 break; 116f595a68aSyz147064 case DLADM_STATUS_ISCONN: 117f595a68aSyz147064 s = "already connected"; 118f595a68aSyz147064 break; 119f595a68aSyz147064 case DLADM_STATUS_NOTCONN: 120f595a68aSyz147064 s = "not connected"; 121f595a68aSyz147064 break; 122f595a68aSyz147064 case DLADM_STATUS_REPOSITORYINVAL: 123f595a68aSyz147064 s = "invalid configuration repository"; 124f595a68aSyz147064 break; 125f595a68aSyz147064 case DLADM_STATUS_MACADDRINVAL: 126f595a68aSyz147064 s = "invalid MAC address"; 127f595a68aSyz147064 break; 128f595a68aSyz147064 case DLADM_STATUS_KEYINVAL: 129f595a68aSyz147064 s = "invalid key"; 130f595a68aSyz147064 break; 131843e1988Sjohnlev case DLADM_STATUS_INVALIDMACADDRLEN: 132843e1988Sjohnlev s = "invalid MAC address length"; 133843e1988Sjohnlev break; 134843e1988Sjohnlev case DLADM_STATUS_INVALIDMACADDRTYPE: 135843e1988Sjohnlev s = "invalid MAC address type"; 136843e1988Sjohnlev break; 137*d62bc4baSyz147064 case DLADM_STATUS_LINKBUSY: 138*d62bc4baSyz147064 s = "link busy"; 139843e1988Sjohnlev break; 140*d62bc4baSyz147064 case DLADM_STATUS_VIDINVAL: 141*d62bc4baSyz147064 s = "invalid VLAN identifier"; 142843e1988Sjohnlev break; 143*d62bc4baSyz147064 case DLADM_STATUS_TRYAGAIN: 144*d62bc4baSyz147064 s = "try again later"; 145*d62bc4baSyz147064 break; 146*d62bc4baSyz147064 case DLADM_STATUS_NONOTIF: 147*d62bc4baSyz147064 s = "link notification is not supported"; 148843e1988Sjohnlev break; 1490ba2cbe9Sxc151355 default: 15033343a97Smeem s = "<unknown error>"; 15133343a97Smeem break; 1520ba2cbe9Sxc151355 } 15333343a97Smeem (void) snprintf(buf, DLADM_STRSIZE, "%s", dgettext(TEXT_DOMAIN, s)); 1540ba2cbe9Sxc151355 return (buf); 1550ba2cbe9Sxc151355 } 1560ba2cbe9Sxc151355 1570ba2cbe9Sxc151355 /* 1580ba2cbe9Sxc151355 * Convert a unix errno to a dladm_status_t. 1590ba2cbe9Sxc151355 * We only convert errnos that are likely to be encountered. All others 1600ba2cbe9Sxc151355 * are mapped to DLADM_STATUS_FAILED. 1610ba2cbe9Sxc151355 */ 1620ba2cbe9Sxc151355 dladm_status_t 1630ba2cbe9Sxc151355 dladm_errno2status(int err) 1640ba2cbe9Sxc151355 { 1650ba2cbe9Sxc151355 switch (err) { 1660ba2cbe9Sxc151355 case EINVAL: 1670ba2cbe9Sxc151355 return (DLADM_STATUS_BADARG); 1680ba2cbe9Sxc151355 case EEXIST: 1690ba2cbe9Sxc151355 return (DLADM_STATUS_EXIST); 1700ba2cbe9Sxc151355 case ENOENT: 1710ba2cbe9Sxc151355 return (DLADM_STATUS_NOTFOUND); 1720ba2cbe9Sxc151355 case ENOSPC: 1730ba2cbe9Sxc151355 return (DLADM_STATUS_TOOSMALL); 1740ba2cbe9Sxc151355 case ENOMEM: 1750ba2cbe9Sxc151355 return (DLADM_STATUS_NOMEM); 1760ba2cbe9Sxc151355 case ENOTSUP: 1770ba2cbe9Sxc151355 return (DLADM_STATUS_NOTSUP); 178*d62bc4baSyz147064 case ENETDOWN: 179*d62bc4baSyz147064 return (DLADM_STATUS_NONOTIF); 1800ba2cbe9Sxc151355 case EACCES: 1810ba2cbe9Sxc151355 return (DLADM_STATUS_DENIED); 1820ba2cbe9Sxc151355 case EIO: 1830ba2cbe9Sxc151355 return (DLADM_STATUS_IOERR); 184843e1988Sjohnlev case EBUSY: 185*d62bc4baSyz147064 return (DLADM_STATUS_LINKBUSY); 186*d62bc4baSyz147064 case EAGAIN: 187*d62bc4baSyz147064 return (DLADM_STATUS_TRYAGAIN); 1880ba2cbe9Sxc151355 default: 1890ba2cbe9Sxc151355 return (DLADM_STATUS_FAILED); 1900ba2cbe9Sxc151355 } 1910ba2cbe9Sxc151355 } 1920ba2cbe9Sxc151355 1930ba2cbe9Sxc151355 /* 1940ba2cbe9Sxc151355 * These are the uid and gid of the user 'dladm'. 1950ba2cbe9Sxc151355 * The directory /etc/dladm and all files under it are owned by this user. 1960ba2cbe9Sxc151355 */ 1970ba2cbe9Sxc151355 #define DLADM_DB_OWNER 15 1980ba2cbe9Sxc151355 #define DLADM_DB_GROUP 3 1990ba2cbe9Sxc151355 #define LOCK_DB_PERMS S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH 2000ba2cbe9Sxc151355 2010ba2cbe9Sxc151355 static int 2020ba2cbe9Sxc151355 i_dladm_lock_db(const char *lock_file, short type) 2030ba2cbe9Sxc151355 { 2040ba2cbe9Sxc151355 int lock_fd; 2050ba2cbe9Sxc151355 struct flock lock; 2060ba2cbe9Sxc151355 2070ba2cbe9Sxc151355 if ((lock_fd = open(lock_file, O_RDWR | O_CREAT | O_TRUNC, 2080ba2cbe9Sxc151355 LOCK_DB_PERMS)) < 0) 2090ba2cbe9Sxc151355 return (-1); 2100ba2cbe9Sxc151355 2110ba2cbe9Sxc151355 lock.l_type = type; 2120ba2cbe9Sxc151355 lock.l_whence = SEEK_SET; 2130ba2cbe9Sxc151355 lock.l_start = 0; 2140ba2cbe9Sxc151355 lock.l_len = 0; 2150ba2cbe9Sxc151355 2160ba2cbe9Sxc151355 if (fcntl(lock_fd, F_SETLKW, &lock) < 0) { 2170ba2cbe9Sxc151355 int err = errno; 2180ba2cbe9Sxc151355 2190ba2cbe9Sxc151355 (void) close(lock_fd); 2200ba2cbe9Sxc151355 (void) unlink(lock_file); 2210ba2cbe9Sxc151355 errno = err; 2220ba2cbe9Sxc151355 return (-1); 2230ba2cbe9Sxc151355 } 2240ba2cbe9Sxc151355 return (lock_fd); 2250ba2cbe9Sxc151355 } 2260ba2cbe9Sxc151355 2270ba2cbe9Sxc151355 static void 2280ba2cbe9Sxc151355 i_dladm_unlock_db(const char *lock_file, int fd) 2290ba2cbe9Sxc151355 { 2300ba2cbe9Sxc151355 struct flock lock; 2310ba2cbe9Sxc151355 2320ba2cbe9Sxc151355 if (fd < 0) 2330ba2cbe9Sxc151355 return; 2340ba2cbe9Sxc151355 2350ba2cbe9Sxc151355 lock.l_type = F_UNLCK; 2360ba2cbe9Sxc151355 lock.l_whence = SEEK_SET; 2370ba2cbe9Sxc151355 lock.l_start = 0; 2380ba2cbe9Sxc151355 lock.l_len = 0; 2390ba2cbe9Sxc151355 2400ba2cbe9Sxc151355 (void) fcntl(fd, F_SETLKW, &lock); 2410ba2cbe9Sxc151355 (void) close(fd); 2420ba2cbe9Sxc151355 (void) unlink(lock_file); 2430ba2cbe9Sxc151355 } 2440ba2cbe9Sxc151355 245*d62bc4baSyz147064 /* 246*d62bc4baSyz147064 * Given a link class, returns its class string. 247*d62bc4baSyz147064 */ 248*d62bc4baSyz147064 const char * 249*d62bc4baSyz147064 dladm_class2str(datalink_class_t class, char *buf) 250*d62bc4baSyz147064 { 251*d62bc4baSyz147064 const char *s; 252*d62bc4baSyz147064 253*d62bc4baSyz147064 switch (class) { 254*d62bc4baSyz147064 case DATALINK_CLASS_PHYS: 255*d62bc4baSyz147064 s = "phys"; 256*d62bc4baSyz147064 break; 257*d62bc4baSyz147064 case DATALINK_CLASS_VLAN: 258*d62bc4baSyz147064 s = "vlan"; 259*d62bc4baSyz147064 break; 260*d62bc4baSyz147064 case DATALINK_CLASS_AGGR: 261*d62bc4baSyz147064 s = "aggr"; 262*d62bc4baSyz147064 break; 263*d62bc4baSyz147064 case DATALINK_CLASS_VNIC: 264*d62bc4baSyz147064 s = "vnic"; 265*d62bc4baSyz147064 break; 266*d62bc4baSyz147064 default: 267*d62bc4baSyz147064 s = "unknown"; 268*d62bc4baSyz147064 break; 269*d62bc4baSyz147064 } 270*d62bc4baSyz147064 271*d62bc4baSyz147064 (void) snprintf(buf, DLADM_STRSIZE, "%s", s); 272*d62bc4baSyz147064 return (buf); 273*d62bc4baSyz147064 } 274*d62bc4baSyz147064 275*d62bc4baSyz147064 /* 276*d62bc4baSyz147064 * Given a physical link media type, returns its media type string. 277*d62bc4baSyz147064 */ 278*d62bc4baSyz147064 const char * 279*d62bc4baSyz147064 dladm_media2str(uint32_t media, char *buf) 280*d62bc4baSyz147064 { 281*d62bc4baSyz147064 const char *s; 282*d62bc4baSyz147064 283*d62bc4baSyz147064 switch (media) { 284*d62bc4baSyz147064 case DL_ETHER: 285*d62bc4baSyz147064 s = "Ethernet"; 286*d62bc4baSyz147064 break; 287*d62bc4baSyz147064 case DL_WIFI: 288*d62bc4baSyz147064 s = "WiFi"; 289*d62bc4baSyz147064 break; 290*d62bc4baSyz147064 case DL_IB: 291*d62bc4baSyz147064 s = "Infiniband"; 292*d62bc4baSyz147064 break; 293*d62bc4baSyz147064 case DL_IPV4: 294*d62bc4baSyz147064 s = "IPv4Tunnel"; 295*d62bc4baSyz147064 break; 296*d62bc4baSyz147064 case DL_IPV6: 297*d62bc4baSyz147064 s = "IPv6Tunnel"; 298*d62bc4baSyz147064 break; 299*d62bc4baSyz147064 case DL_CSMACD: 300*d62bc4baSyz147064 s = "CSMA/CD"; 301*d62bc4baSyz147064 break; 302*d62bc4baSyz147064 case DL_TPB: 303*d62bc4baSyz147064 s = "TokenBus"; 304*d62bc4baSyz147064 break; 305*d62bc4baSyz147064 case DL_TPR: 306*d62bc4baSyz147064 s = "TokenRing"; 307*d62bc4baSyz147064 break; 308*d62bc4baSyz147064 case DL_METRO: 309*d62bc4baSyz147064 s = "MetroNet"; 310*d62bc4baSyz147064 break; 311*d62bc4baSyz147064 case DL_HDLC: 312*d62bc4baSyz147064 s = "HDLC"; 313*d62bc4baSyz147064 break; 314*d62bc4baSyz147064 case DL_CHAR: 315*d62bc4baSyz147064 s = "SyncCharacter"; 316*d62bc4baSyz147064 break; 317*d62bc4baSyz147064 case DL_CTCA: 318*d62bc4baSyz147064 s = "CTCA"; 319*d62bc4baSyz147064 break; 320*d62bc4baSyz147064 case DL_FDDI: 321*d62bc4baSyz147064 s = "FDDI"; 322*d62bc4baSyz147064 break; 323*d62bc4baSyz147064 case DL_FC: 324*d62bc4baSyz147064 s = "FiberChannel"; 325*d62bc4baSyz147064 break; 326*d62bc4baSyz147064 case DL_ATM: 327*d62bc4baSyz147064 s = "ATM"; 328*d62bc4baSyz147064 break; 329*d62bc4baSyz147064 case DL_IPATM: 330*d62bc4baSyz147064 s = "ATM(ClassicIP)"; 331*d62bc4baSyz147064 break; 332*d62bc4baSyz147064 case DL_X25: 333*d62bc4baSyz147064 s = "X.25"; 334*d62bc4baSyz147064 break; 335*d62bc4baSyz147064 case DL_IPX25: 336*d62bc4baSyz147064 s = "X.25(ClassicIP)"; 337*d62bc4baSyz147064 break; 338*d62bc4baSyz147064 case DL_ISDN: 339*d62bc4baSyz147064 s = "ISDN"; 340*d62bc4baSyz147064 break; 341*d62bc4baSyz147064 case DL_HIPPI: 342*d62bc4baSyz147064 s = "HIPPI"; 343*d62bc4baSyz147064 break; 344*d62bc4baSyz147064 case DL_100VG: 345*d62bc4baSyz147064 s = "100BaseVGEthernet"; 346*d62bc4baSyz147064 break; 347*d62bc4baSyz147064 case DL_100VGTPR: 348*d62bc4baSyz147064 s = "100BaseVGTokenRing"; 349*d62bc4baSyz147064 break; 350*d62bc4baSyz147064 case DL_ETH_CSMA: 351*d62bc4baSyz147064 s = "IEEE802.3"; 352*d62bc4baSyz147064 break; 353*d62bc4baSyz147064 case DL_100BT: 354*d62bc4baSyz147064 s = "100BaseT"; 355*d62bc4baSyz147064 break; 356*d62bc4baSyz147064 case DL_FRAME: 357*d62bc4baSyz147064 s = "FrameRelay"; 358*d62bc4baSyz147064 break; 359*d62bc4baSyz147064 case DL_MPFRAME: 360*d62bc4baSyz147064 s = "MPFrameRelay"; 361*d62bc4baSyz147064 break; 362*d62bc4baSyz147064 case DL_ASYNC: 363*d62bc4baSyz147064 s = "AsyncCharacter"; 364*d62bc4baSyz147064 break; 365*d62bc4baSyz147064 default: 366*d62bc4baSyz147064 s = "--"; 367*d62bc4baSyz147064 break; 368*d62bc4baSyz147064 } 369*d62bc4baSyz147064 370*d62bc4baSyz147064 (void) snprintf(buf, DLADM_STRSIZE, "%s", s); 371*d62bc4baSyz147064 return (buf); 372*d62bc4baSyz147064 } 373*d62bc4baSyz147064 3740ba2cbe9Sxc151355 dladm_status_t 3750ba2cbe9Sxc151355 i_dladm_rw_db(const char *db_file, mode_t db_perms, 3760ba2cbe9Sxc151355 dladm_status_t (*process_db)(void *, FILE *, FILE *), 3770ba2cbe9Sxc151355 void *arg, boolean_t writeop) 3780ba2cbe9Sxc151355 { 3790ba2cbe9Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 3800ba2cbe9Sxc151355 FILE *fp, *nfp = NULL; 3810ba2cbe9Sxc151355 char lock[MAXPATHLEN]; 3820ba2cbe9Sxc151355 char file[MAXPATHLEN]; 3830ba2cbe9Sxc151355 char newfile[MAXPATHLEN]; 3840ba2cbe9Sxc151355 char *db_basename; 3850ba2cbe9Sxc151355 int nfd, lock_fd; 3860ba2cbe9Sxc151355 3870ba2cbe9Sxc151355 /* 3880ba2cbe9Sxc151355 * If we are called from a boot script such as net-physical, 3890ba2cbe9Sxc151355 * it's quite likely that the root fs is still not writable. 3900ba2cbe9Sxc151355 * For this case, it's ok for the lock creation to fail since 3910ba2cbe9Sxc151355 * no one else could be accessing our configuration file. 3920ba2cbe9Sxc151355 */ 3930ba2cbe9Sxc151355 db_basename = strrchr(db_file, '/'); 3940ba2cbe9Sxc151355 if (db_basename == NULL || db_basename[1] == '\0') 3950ba2cbe9Sxc151355 return (dladm_errno2status(EINVAL)); 3960ba2cbe9Sxc151355 db_basename++; 3970ba2cbe9Sxc151355 (void) snprintf(lock, MAXPATHLEN, "/tmp/%s.lock", db_basename); 3980ba2cbe9Sxc151355 if ((lock_fd = i_dladm_lock_db 3990ba2cbe9Sxc151355 (lock, (writeop ? F_WRLCK : F_RDLCK))) < 0 && errno != EROFS) 4000ba2cbe9Sxc151355 return (dladm_errno2status(errno)); 4010ba2cbe9Sxc151355 4020ba2cbe9Sxc151355 (void) snprintf(file, MAXPATHLEN, "%s/%s", dladm_rootdir, db_file); 4030ba2cbe9Sxc151355 if ((fp = fopen(file, (writeop ? "r+" : "r"))) == NULL) { 4040ba2cbe9Sxc151355 int err = errno; 4050ba2cbe9Sxc151355 4060ba2cbe9Sxc151355 i_dladm_unlock_db(lock, lock_fd); 4070ba2cbe9Sxc151355 if (err == ENOENT) 4080ba2cbe9Sxc151355 return (DLADM_STATUS_DBNOTFOUND); 4090ba2cbe9Sxc151355 4100ba2cbe9Sxc151355 return (dladm_errno2status(err)); 4110ba2cbe9Sxc151355 } 4120ba2cbe9Sxc151355 4130ba2cbe9Sxc151355 if (writeop) { 4140ba2cbe9Sxc151355 (void) snprintf(newfile, MAXPATHLEN, "%s/%s.new", 4150ba2cbe9Sxc151355 dladm_rootdir, db_file); 4160ba2cbe9Sxc151355 if ((nfd = open(newfile, O_WRONLY | O_CREAT | O_TRUNC, 4170ba2cbe9Sxc151355 db_perms)) < 0) { 4180ba2cbe9Sxc151355 (void) fclose(fp); 4190ba2cbe9Sxc151355 i_dladm_unlock_db(lock, lock_fd); 4200ba2cbe9Sxc151355 return (dladm_errno2status(errno)); 4210ba2cbe9Sxc151355 } 4220ba2cbe9Sxc151355 4230ba2cbe9Sxc151355 if ((nfp = fdopen(nfd, "w")) == NULL) { 4240ba2cbe9Sxc151355 (void) close(nfd); 4250ba2cbe9Sxc151355 (void) fclose(fp); 4260ba2cbe9Sxc151355 (void) unlink(newfile); 4270ba2cbe9Sxc151355 i_dladm_unlock_db(lock, lock_fd); 4280ba2cbe9Sxc151355 return (dladm_errno2status(errno)); 4290ba2cbe9Sxc151355 } 4300ba2cbe9Sxc151355 } 4310ba2cbe9Sxc151355 status = (*process_db)(arg, fp, nfp); 4320ba2cbe9Sxc151355 if (!writeop || status != DLADM_STATUS_OK) 4330ba2cbe9Sxc151355 goto done; 4340ba2cbe9Sxc151355 4350ba2cbe9Sxc151355 /* 4360ba2cbe9Sxc151355 * Configuration files need to be owned by the 'dladm' user. 4370ba2cbe9Sxc151355 * If we are invoked by root, the file ownership needs to be fixed. 4380ba2cbe9Sxc151355 */ 4390ba2cbe9Sxc151355 if (getuid() == 0 || geteuid() == 0) { 4400ba2cbe9Sxc151355 if (fchown(nfd, DLADM_DB_OWNER, DLADM_DB_GROUP) < 0) { 4410ba2cbe9Sxc151355 status = dladm_errno2status(errno); 4420ba2cbe9Sxc151355 goto done; 4430ba2cbe9Sxc151355 } 4440ba2cbe9Sxc151355 } 4450ba2cbe9Sxc151355 4460ba2cbe9Sxc151355 if (fflush(nfp) == EOF) { 4470ba2cbe9Sxc151355 status = dladm_errno2status(errno); 4480ba2cbe9Sxc151355 goto done; 4490ba2cbe9Sxc151355 } 4500ba2cbe9Sxc151355 (void) fclose(fp); 4510ba2cbe9Sxc151355 (void) fclose(nfp); 4520ba2cbe9Sxc151355 4530ba2cbe9Sxc151355 if (rename(newfile, file) < 0) { 4540ba2cbe9Sxc151355 (void) unlink(newfile); 4550ba2cbe9Sxc151355 i_dladm_unlock_db(lock, lock_fd); 4560ba2cbe9Sxc151355 return (dladm_errno2status(errno)); 4570ba2cbe9Sxc151355 } 4580ba2cbe9Sxc151355 4590ba2cbe9Sxc151355 i_dladm_unlock_db(lock, lock_fd); 4600ba2cbe9Sxc151355 return (DLADM_STATUS_OK); 4610ba2cbe9Sxc151355 4620ba2cbe9Sxc151355 done: 4630ba2cbe9Sxc151355 if (nfp != NULL) { 4640ba2cbe9Sxc151355 (void) fclose(nfp); 4650ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) 4660ba2cbe9Sxc151355 (void) unlink(newfile); 4670ba2cbe9Sxc151355 } 4680ba2cbe9Sxc151355 (void) fclose(fp); 4690ba2cbe9Sxc151355 i_dladm_unlock_db(lock, lock_fd); 4700ba2cbe9Sxc151355 return (status); 4710ba2cbe9Sxc151355 } 4720ba2cbe9Sxc151355 4730ba2cbe9Sxc151355 dladm_status_t 4740ba2cbe9Sxc151355 dladm_set_rootdir(const char *rootdir) 4750ba2cbe9Sxc151355 { 4760ba2cbe9Sxc151355 DIR *dp; 4770ba2cbe9Sxc151355 4780ba2cbe9Sxc151355 if (rootdir == NULL || *rootdir != '/' || 4790ba2cbe9Sxc151355 (dp = opendir(rootdir)) == NULL) 4800ba2cbe9Sxc151355 return (DLADM_STATUS_BADARG); 4810ba2cbe9Sxc151355 4820ba2cbe9Sxc151355 (void) strncpy(dladm_rootdir, rootdir, MAXPATHLEN); 4830ba2cbe9Sxc151355 (void) closedir(dp); 4840ba2cbe9Sxc151355 return (DLADM_STATUS_OK); 4850ba2cbe9Sxc151355 } 486*d62bc4baSyz147064 487*d62bc4baSyz147064 boolean_t 488*d62bc4baSyz147064 dladm_valid_linkname(const char *link) 489*d62bc4baSyz147064 { 490*d62bc4baSyz147064 size_t len = strlen(link); 491*d62bc4baSyz147064 const char *cp; 492*d62bc4baSyz147064 493*d62bc4baSyz147064 if (len + 1 >= MAXLINKNAMELEN) 494*d62bc4baSyz147064 return (B_FALSE); 495*d62bc4baSyz147064 496*d62bc4baSyz147064 /* 497*d62bc4baSyz147064 * The link name cannot start with a digit and must end with a digit. 498*d62bc4baSyz147064 */ 499*d62bc4baSyz147064 if ((isdigit(link[0]) != 0) || (isdigit(link[len - 1]) == 0)) 500*d62bc4baSyz147064 return (B_FALSE); 501*d62bc4baSyz147064 502*d62bc4baSyz147064 /* 503*d62bc4baSyz147064 * The legal characters in a link name are: 504*d62bc4baSyz147064 * alphanumeric (a-z, A-Z, 0-9), and the underscore ('_'). 505*d62bc4baSyz147064 */ 506*d62bc4baSyz147064 for (cp = link; *cp != '\0'; cp++) { 507*d62bc4baSyz147064 if ((isalnum(*cp) == 0) && (*cp != '_')) 508*d62bc4baSyz147064 return (B_FALSE); 509*d62bc4baSyz147064 } 510*d62bc4baSyz147064 511*d62bc4baSyz147064 return (B_TRUE); 512*d62bc4baSyz147064 } 513