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 */
21d62bc4baSyz
22d62bc4baSyz /*
2332715170SCathy Zhou * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24d62bc4baSyz */
25d62bc4baSyz
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"
47d62bc4baSyz
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;
53d62bc4baSyz
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;
63d62bc4baSyz
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;
69d62bc4baSyz
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 *);
86d62bc4baSyz
87d62bc4baSyz #define BUFLEN(lim, ptr) (((lim) > (ptr)) ? ((lim) - (ptr)) : 0)
88d62bc4baSyz #define MAXLINELEN 1024
89d62bc4baSyz
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 *);
101d62bc4baSyz
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 **);
110d62bc4baSyz
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;
116d62bc4baSyz
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;
123d62bc4baSyz
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 };
132d62bc4baSyz
133d62bc4baSyz static size_t ntranslators = sizeof (translators) / sizeof (translator_t);
134d62bc4baSyz
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, \
144d62bc4baSyz LINK_PROPERTY_TYPE_VALUE_SEP, (val), LINK_PROPERTY_DELIMINATOR))
145d62bc4baSyz
146d62bc4baSyz /*
147d62bc4baSyz * Name of the cache file to keep the active <link name, linkid> mapping
148d62bc4baSyz */
1492b24ab6bSSebastien Roy char cachefile[MAXPATHLEN];
150d62bc4baSyz
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);
155d62bc4baSyz
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;
199