xref: /illumos-gate/usr/src/cmd/dlmgmtd/dlmgmt_db.c (revision 6a634c9d)
1d62bc4baSyz /*
2d62bc4baSyz  * CDDL HEADER START
3d62bc4baSyz  *
4d62bc4baSyz  * The contents of this file are subject to the terms of the
5d62bc4baSyz  * Common Development and Distribution License (the "License").
6d62bc4baSyz  * You may not use this file except in compliance with the License.
7d62bc4baSyz  *
8d62bc4baSyz  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9d62bc4baSyz  * or http://www.opensolaris.org/os/licensing.
10d62bc4baSyz  * See the License for the specific language governing permissions
11d62bc4baSyz  * and limitations under the License.
12d62bc4baSyz  *
13d62bc4baSyz  * When distributing Covered Code, include this CDDL HEADER in each
14d62bc4baSyz  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15d62bc4baSyz  * If applicable, add the following below this CDDL HEADER, with the
16d62bc4baSyz  * fields enclosed by brackets "[]" replaced with your own identifying
17d62bc4baSyz  * information: Portions Copyright [yyyy] [name of copyright owner]
18d62bc4baSyz  *
19d62bc4baSyz  * CDDL HEADER END
20d62bc4baSyz  */
22d62bc4baSyz /*
2332715170SCathy Zhou  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24d62bc4baSyz  */
26d62bc4baSyz #include <assert.h>
27d62bc4baSyz #include <ctype.h>
28d62bc4baSyz #include <errno.h>
29d62bc4baSyz #include <fcntl.h>
30d62bc4baSyz #include <stdio.h>
31d62bc4baSyz #include <stdlib.h>
322b24ab6bSSebastien Roy #include <string.h>
33d62bc4baSyz #include <strings.h>
34d62bc4baSyz #include <syslog.h>
352b24ab6bSSebastien Roy #include <zone.h>
362b24ab6bSSebastien Roy #include <sys/types.h>
37d62bc4baSyz #include <sys/stat.h>
382b24ab6bSSebastien Roy #include <stropts.h>
392b24ab6bSSebastien Roy #include <sys/conf.h>
40d62bc4baSyz #include <pthread.h>
41d62bc4baSyz #include <unistd.h>
422b24ab6bSSebastien Roy #include <wait.h>
432b24ab6bSSebastien Roy #include <libcontract.h>
445b310668SDarren Reed #include <libcontract_priv.h>
452b24ab6bSSebastien Roy #include <sys/contract/process.h>
46d62bc4baSyz #include "dlmgmt_impl.h"
48d62bc4baSyz typedef enum dlmgmt_db_op {
49d62bc4baSyz 	DLMGMT_DB_OP_WRITE,
50d62bc4baSyz 	DLMGMT_DB_OP_DELETE,
51d62bc4baSyz 	DLMGMT_DB_OP_READ
52d62bc4baSyz } dlmgmt_db_op_t;
54d62bc4baSyz typedef struct dlmgmt_db_req_s {
55d62bc4baSyz 	struct dlmgmt_db_req_s	*ls_next;
56d62bc4baSyz 	dlmgmt_db_op_t		ls_op;
572b24ab6bSSebastien Roy 	char			ls_link[MAXLINKNAMELEN];
58d62bc4baSyz 	datalink_id_t		ls_linkid;
592b24ab6bSSebastien Roy 	zoneid_t		ls_zoneid;
60d62bc4baSyz 	uint32_t		ls_flags;	/* Either DLMGMT_ACTIVE or   */
61d62bc4baSyz 						/* DLMGMT_PERSIST, not both. */
62d62bc4baSyz } dlmgmt_db_req_t;
64d62bc4baSyz /*
65d62bc4baSyz  * List of pending db updates (e.g., because of a read-only filesystem).
66d62bc4baSyz  */
67d62bc4baSyz static dlmgmt_db_req_t	*dlmgmt_db_req_head = NULL;
68d62bc4baSyz static dlmgmt_db_req_t	*dlmgmt_db_req_tail = NULL;
702b24ab6bSSebastien Roy /*
712b24ab6bSSebastien Roy  * rewrite_needed is set to B_TRUE by process_link_line() if it encounters a
722b24ab6bSSebastien Roy  * line with an old format.  This will cause the file being read to be
732b24ab6bSSebastien Roy  * re-written with the current format.
742b24ab6bSSebastien Roy  */
752b24ab6bSSebastien Roy static boolean_t	rewrite_needed;
762b24ab6bSSebastien Roy 
772b24ab6bSSebastien Roy static int		dlmgmt_db_update(dlmgmt_db_op_t, const char *,
782b24ab6bSSebastien Roy 			    dlmgmt_link_t *, uint32_t);
79d62bc4baSyz static int		dlmgmt_process_db_req(dlmgmt_db_req_t *);
80d62bc4baSyz static int		dlmgmt_process_db_onereq(dlmgmt_db_req_t *, boolean_t);
81d62bc4baSyz static void		*dlmgmt_db_update_thread(void *);
822b24ab6bSSebastien Roy static boolean_t	process_link_line(char *, dlmgmt_link_t *);
83d62bc4baSyz static int		process_db_write(dlmgmt_db_req_t *, FILE *, FILE *);
842b24ab6bSSebastien Roy static int		process_db_read(dlmgmt_db_req_t *, FILE *);
85d62bc4baSyz static void		generate_link_line(dlmgmt_link_t *, boolean_t, char *);
87d62bc4baSyz #define	BUFLEN(lim, ptr)	(((lim) > (ptr)) ? ((lim) - (ptr)) : 0)
88d62bc4baSyz #define	MAXLINELEN		1024
902b24ab6bSSebastien Roy typedef void db_walk_func_t(dlmgmt_link_t *);
912b24ab6bSSebastien Roy 
92d62bc4baSyz /*
93d62bc4baSyz  * Translator functions to go from dladm_datatype_t to character strings.
94d62bc4baSyz  * Each function takes a pointer to a buffer, the size of the buffer,
95d62bc4baSyz  * the name of the attribute, and the value to be written.  The functions
96d62bc4baSyz  * return the number of bytes written to the buffer.  If the buffer is not big
97d62bc4baSyz  * enough to hold the string representing the value, then nothing is written
98d62bc4baSyz  * and 0 is returned.
99d62bc4baSyz  */
100d62bc4baSyz typedef size_t write_func_t(char *, size_t, char *, void *);
102d62bc4baSyz /*
103d62bc4baSyz  * Translator functions to read from a NULL terminated string buffer into
104d62bc4baSyz  * something of the given DLADM_TYPE_*.  The functions each return the number
105d62bc4baSyz  * of bytes read from the string buffer.  If there is an error reading data
106d62bc4baSyz  * from the buffer, then 0 is returned.  It is the caller's responsibility
107d62bc4baSyz  * to free the data allocated by these functions.
108d62bc4baSyz  */
109d62bc4baSyz typedef size_t read_func_t(char *, void **);
111d62bc4baSyz typedef struct translator_s {
112d62bc4baSyz 	const char	*type_name;
113d62bc4baSyz 	write_func_t	*write_func;
114d62bc4baSyz 	read_func_t	*read_func;
115d62bc4baSyz } translator_t;
117d62bc4baSyz /*
118d62bc4baSyz  * Translator functions, defined later but declared here so that
119d62bc4baSyz  * the translator table can be defined.
120d62bc4baSyz  */
121d62bc4baSyz static write_func_t	write_str, write_boolean, write_uint64;
122d62bc4baSyz static read_func_t	read_str, read_boolean, read_int64;
124d62bc4baSyz /*
125d62bc4baSyz  * Translator table, indexed by dladm_datatype_t.
126d62bc4baSyz  */
127d62bc4baSyz static translator_t translators[] = {
128d62bc4baSyz 	{ "string",	write_str,	read_str	},
129d62bc4baSyz 	{ "boolean",	write_boolean,	read_boolean	},
130d62bc4baSyz 	{ "int",	write_uint64,	read_int64	}
131d62bc4baSyz };
133d62bc4baSyz static size_t ntranslators = sizeof (translators) / sizeof (translator_t);
135d62bc4baSyz #define	LINK_PROPERTY_DELIMINATOR	";"
136d62bc4baSyz #define	LINK_PROPERTY_TYPE_VALUE_SEP	","
137d62bc4baSyz #define	BASE_PROPERTY_LENGTH(t, n) (strlen(translators[(t)].type_name) +\
138d62bc4baSyz 				    strlen(LINK_PROPERTY_TYPE_VALUE_SEP) +\
139d62bc4baSyz 				    strlen(LINK_PROPERTY_DELIMINATOR) +\
140d62bc4baSyz 				    strlen((n)))
141d62bc4baSyz #define	GENERATE_PROPERTY_STRING(buf, length, conv, name, type, val) \
142d62bc4baSyz 	    (snprintf((buf), (length), "%s=%s%s" conv "%s", (name), \
143d62bc4baSyz 	    translators[(type)].type_name, \
146d62bc4baSyz /*
147d62bc4baSyz  * Name of the cache file to keep the active <link name, linkid> mapping
148d62bc4baSyz  */
1492b24ab6bSSebastien Roy char	cachefile[MAXPATHLEN];
151d62bc4baSyz #define	DLMGMT_PERSISTENT_DB_PATH	"/etc/dladm/datalink.conf"
152d62bc4baSyz #define	DLMGMT_MAKE_FILE_DB_PATH(buffer, persistent)	\
153d62bc4baSyz 	(void) snprintf((buffer), MAXPATHLEN, "%s", \
154d62bc4baSyz 	(persistent) ? DLMGMT_PERSISTENT_DB_PATH : cachefile);
1562b24ab6bSSebastien Roy typedef struct zopen_arg {
1572b24ab6bSSebastien Roy 	const char	*zopen_modestr;
1582b24ab6bSSebastien Roy 	int		*zopen_pipe;
1592b24ab6bSSebastien Roy 	int		zopen_fd;
1602b24ab6bSSebastien Roy } zopen_arg_t;
1612b24ab6bSSebastien Roy 
1622b24ab6bSSebastien Roy typedef struct zrename_arg {
1632b24ab6bSSebastien Roy 	const char	*zrename_newname;
1642b24ab6bSSebastien Roy } zrename_arg_t;
1652b24ab6bSSebastien Roy 
1662b24ab6bSSebastien Roy typedef union zfoparg {
1672b24ab6bSSebastien Roy 	zopen_arg_t	zfop_openarg;
1682b24ab6bSSebastien Roy 	zrename_arg_t	zfop_renamearg;
1692b24ab6bSSebastien Roy } zfoparg_t;
1702b24ab6bSSebastien Roy 
1712b24ab6bSSebastien Roy typedef struct zfcbarg {
1722b24ab6bSSebastien Roy 	boolean_t	zfarg_inglobalzone; /* is callback in global zone? */
1732b24ab6bSSebastien Roy 	zoneid_t	zfarg_finglobalzone; /* is file in global zone? */
1742b24ab6bSSebastien Roy 	const char	*zfarg_filename;
1752b24ab6bSSebastien Roy 	zfoparg_t	*zfarg_oparg;
1762b24ab6bSSebastien Roy } zfarg_t;
1772b24ab6bSSebastien Roy #define	zfarg_openarg	zfarg_oparg->zfop_openarg
1782b24ab6bSSebastien Roy #define	zfarg_renamearg	zfarg_oparg->zfop_renamearg
1792b24ab6bSSebastien Roy 
1802b24ab6bSSebastien Roy /* zone file callback */
1812b24ab6bSSebastien Roy typedef int zfcb_t(zfarg_t *);
1822b24ab6bSSebastien Roy 
1832b24ab6bSSebastien Roy /*
1842b24ab6bSSebastien Roy  * Execute an operation on filename relative to zoneid's zone root.  If the
1852b24ab6bSSebastien Roy  * file is in the global zone, then the zfcb() callback will simply be called
1862b24ab6bSSebastien Roy  * directly.  If the file is in a non-global zone, then zfcb() will be called
1872b24ab6bSSebastien Roy  * both from the global zone's context, and from the non-global zone's context
1882b24ab6bSSebastien Roy  * (from a fork()'ed child that has entered the non-global zone).  This is
1892b24ab6bSSebastien Roy  * done to allow the callback to communicate with itself if needed (e.g. to
1902b24ab6bSSebastien Roy  * pass back the file descriptor of an opened file).
1912b24ab6bSSebastien Roy  */
1922b24ab6bSSebastien Roy static int
dlmgmt_zfop(const char * filename,zoneid_t zoneid,zfcb_t * zfcb,zfoparg_t * zfoparg)1932b24ab6bSSebastien Roy dlmgmt_zfop(const char *filename, zoneid_t zoneid, zfcb_t *zfcb,
1942b24ab6bSSebastien Roy     zfoparg_t *zfoparg)
1952b24ab6bSSebastien Roy {
1962b24ab6bSSebastien Roy 	int		ctfd;
1972b24ab6bSSebastien Roy 	int		err;
1982b24ab6bSSebastien Roy 	pid_t		childpid;