1*8823STruong.Q.Nguyen@Sun.COM /*
2*8823STruong.Q.Nguyen@Sun.COM * CDDL HEADER START
3*8823STruong.Q.Nguyen@Sun.COM *
4*8823STruong.Q.Nguyen@Sun.COM * The contents of this file are subject to the terms of the
5*8823STruong.Q.Nguyen@Sun.COM * Common Development and Distribution License (the "License").
6*8823STruong.Q.Nguyen@Sun.COM * You may not use this file except in compliance with the License.
7*8823STruong.Q.Nguyen@Sun.COM *
8*8823STruong.Q.Nguyen@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*8823STruong.Q.Nguyen@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*8823STruong.Q.Nguyen@Sun.COM * See the License for the specific language governing permissions
11*8823STruong.Q.Nguyen@Sun.COM * and limitations under the License.
12*8823STruong.Q.Nguyen@Sun.COM *
13*8823STruong.Q.Nguyen@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*8823STruong.Q.Nguyen@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*8823STruong.Q.Nguyen@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*8823STruong.Q.Nguyen@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*8823STruong.Q.Nguyen@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*8823STruong.Q.Nguyen@Sun.COM *
19*8823STruong.Q.Nguyen@Sun.COM * CDDL HEADER END
20*8823STruong.Q.Nguyen@Sun.COM */
21*8823STruong.Q.Nguyen@Sun.COM
22*8823STruong.Q.Nguyen@Sun.COM /*
23*8823STruong.Q.Nguyen@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24*8823STruong.Q.Nguyen@Sun.COM * Use is subject to license terms.
25*8823STruong.Q.Nguyen@Sun.COM */
26*8823STruong.Q.Nguyen@Sun.COM
27*8823STruong.Q.Nguyen@Sun.COM /*
28*8823STruong.Q.Nguyen@Sun.COM * This file delivers svc.ipfd, the daemon that monitors changes to
29*8823STruong.Q.Nguyen@Sun.COM * firewall capable services and requests IPfilter configuration update
30*8823STruong.Q.Nguyen@Sun.COM * on behalf of the service. Essentially, the daemon listens for
31*8823STruong.Q.Nguyen@Sun.COM * service changes and forks the program that update a service's
32*8823STruong.Q.Nguyen@Sun.COM * IPfilter configuration.
33*8823STruong.Q.Nguyen@Sun.COM *
34*8823STruong.Q.Nguyen@Sun.COM * - A firewall capable SMF service can restrict network access to its
35*8823STruong.Q.Nguyen@Sun.COM * service by providing a firewall policy that can be translated into
36*8823STruong.Q.Nguyen@Sun.COM * a set of IPfilter rules. The mentioned firewall policy is stored in
37*8823STruong.Q.Nguyen@Sun.COM * firewall_config and firewall_context property groups. If one of these
38*8823STruong.Q.Nguyen@Sun.COM * two property groups exist, the service is considered to be firewall
39*8823STruong.Q.Nguyen@Sun.COM * capable.
40*8823STruong.Q.Nguyen@Sun.COM *
41*8823STruong.Q.Nguyen@Sun.COM * - A request to update service's IPfilter configuration is made for
42*8823STruong.Q.Nguyen@Sun.COM * actions that affect service's configuration or running state. The
43*8823STruong.Q.Nguyen@Sun.COM * actions are:
44*8823STruong.Q.Nguyen@Sun.COM * - enable/disable
45*8823STruong.Q.Nguyen@Sun.COM * - refresh/restart
46*8823STruong.Q.Nguyen@Sun.COM * - maintenance/clear maintenance
47*8823STruong.Q.Nguyen@Sun.COM *
48*8823STruong.Q.Nguyen@Sun.COM * Lacking a generic SMF mechanism to observe service state changes, the
49*8823STruong.Q.Nguyen@Sun.COM * daemon observe change events by listening to changes to 'general',
50*8823STruong.Q.Nguyen@Sun.COM * 'general_ovr', and 'restarter_actions' property groups. This is not a
51*8823STruong.Q.Nguyen@Sun.COM * stable interface and should be replaced when a SMF supported mechanism
52*8823STruong.Q.Nguyen@Sun.COM * becomes available.
53*8823STruong.Q.Nguyen@Sun.COM *
54*8823STruong.Q.Nguyen@Sun.COM * - The program responsible for updating service's IPfilter configuration
55*8823STruong.Q.Nguyen@Sun.COM * is /lib/svc/method/ipfilter. This program is called as:
56*8823STruong.Q.Nguyen@Sun.COM *
57*8823STruong.Q.Nguyen@Sun.COM * /lib/svc/method/ipfilter fw_update fmri
58*8823STruong.Q.Nguyen@Sun.COM *
59*8823STruong.Q.Nguyen@Sun.COM * where fmri the instance fmri of the service to be updated.
60*8823STruong.Q.Nguyen@Sun.COM */
61*8823STruong.Q.Nguyen@Sun.COM
62*8823STruong.Q.Nguyen@Sun.COM #include <stdio.h>
63*8823STruong.Q.Nguyen@Sun.COM #include <unistd.h>
64*8823STruong.Q.Nguyen@Sun.COM #include <stdlib.h>
65*8823STruong.Q.Nguyen@Sun.COM #include <assert.h>
66*8823STruong.Q.Nguyen@Sun.COM #include <errno.h>
67*8823STruong.Q.Nguyen@Sun.COM #include <sys/types.h>
68*8823STruong.Q.Nguyen@Sun.COM #include <sys/stat.h>
69*8823STruong.Q.Nguyen@Sun.COM #include <sys/wait.h>
70*8823STruong.Q.Nguyen@Sun.COM #include <fcntl.h>
71*8823STruong.Q.Nguyen@Sun.COM #include <umem.h>
72*8823STruong.Q.Nguyen@Sun.COM #include <libscf.h>
73*8823STruong.Q.Nguyen@Sun.COM #include <libscf_priv.h>
74*8823STruong.Q.Nguyen@Sun.COM #include <signal.h>
75*8823STruong.Q.Nguyen@Sun.COM #include <string.h>
76*8823STruong.Q.Nguyen@Sun.COM #include <syslog.h>
77*8823STruong.Q.Nguyen@Sun.COM
78*8823STruong.Q.Nguyen@Sun.COM #define IPFILTER_FMRI "svc:/network/ipfilter:default"
79*8823STruong.Q.Nguyen@Sun.COM #define RPCBIND_FMRI "svc:/network/rpc/bind:default"
80*8823STruong.Q.Nguyen@Sun.COM #define IPF_UPDATE_CMD "/lib/svc/method/ipfilter"
81*8823STruong.Q.Nguyen@Sun.COM
82*8823STruong.Q.Nguyen@Sun.COM #define SCF_SNAPSHOT_RUNNING "running"
83*8823STruong.Q.Nguyen@Sun.COM #define SCF_PG_FW_CONTEXT "firewall_context"
84*8823STruong.Q.Nguyen@Sun.COM #define SCF_PG_FW_CONFIG "firewall_config"
85*8823STruong.Q.Nguyen@Sun.COM #define SCF_PG_REFRESH "refresh"
86*8823STruong.Q.Nguyen@Sun.COM #define SCF_PG_INETD "inetd"
87*8823STruong.Q.Nguyen@Sun.COM
88*8823STruong.Q.Nguyen@Sun.COM #define SCF_PROPERTY_ISRPC "isrpc"
89*8823STruong.Q.Nguyen@Sun.COM
90*8823STruong.Q.Nguyen@Sun.COM #define MAX_RETRY 7
91*8823STruong.Q.Nguyen@Sun.COM #define DEV_NULL "/dev/null"
92*8823STruong.Q.Nguyen@Sun.COM
93*8823STruong.Q.Nguyen@Sun.COM static scf_handle_t *h;
94*8823STruong.Q.Nguyen@Sun.COM static ssize_t max_scf_fmri_size;
95*8823STruong.Q.Nguyen@Sun.COM static ssize_t max_scf_name_size;
96*8823STruong.Q.Nguyen@Sun.COM
97*8823STruong.Q.Nguyen@Sun.COM static scf_instance_t *inst;
98*8823STruong.Q.Nguyen@Sun.COM static scf_snapshot_t *snap;
99*8823STruong.Q.Nguyen@Sun.COM static scf_propertygroup_t *scratch_pg;
100*8823STruong.Q.Nguyen@Sun.COM static scf_property_t *scratch_prop;
101*8823STruong.Q.Nguyen@Sun.COM static scf_value_t *scratch_v;
102*8823STruong.Q.Nguyen@Sun.COM
103*8823STruong.Q.Nguyen@Sun.COM static char *scratch_fmri;
104*8823STruong.Q.Nguyen@Sun.COM static char *scratch_name;
105*8823STruong.Q.Nguyen@Sun.COM
106*8823STruong.Q.Nguyen@Sun.COM static const char *all_props[] = {
107*8823STruong.Q.Nguyen@Sun.COM SCF_PROPERTY_REFRESH, SCF_PROPERTY_RESTART, SCF_PROPERTY_MAINT_ON,
108*8823STruong.Q.Nguyen@Sun.COM SCF_PROPERTY_MAINT_ON_IMMEDIATE, SCF_PROPERTY_MAINT_ON_IMMTEMP,
109*8823STruong.Q.Nguyen@Sun.COM SCF_PROPERTY_MAINT_ON_TEMPORARY, SCF_PROPERTY_MAINT_OFF
110*8823STruong.Q.Nguyen@Sun.COM };
111*8823STruong.Q.Nguyen@Sun.COM #define ALL_PROPS_CNT 7
112*8823STruong.Q.Nguyen@Sun.COM
113*8823STruong.Q.Nguyen@Sun.COM static const char *maint_props[] = {
114*8823STruong.Q.Nguyen@Sun.COM SCF_PROPERTY_REFRESH, SCF_PROPERTY_RESTART, SCF_PROPERTY_MAINT_OFF };
115*8823STruong.Q.Nguyen@Sun.COM #define MAINT_PROPS_CNT 3
116*8823STruong.Q.Nguyen@Sun.COM
117*8823STruong.Q.Nguyen@Sun.COM static int ipfilter_update(const char *);
118*8823STruong.Q.Nguyen@Sun.COM
119*8823STruong.Q.Nguyen@Sun.COM static int
daemonize_self(void)120*8823STruong.Q.Nguyen@Sun.COM daemonize_self(void)
121*8823STruong.Q.Nguyen@Sun.COM {
122*8823STruong.Q.Nguyen@Sun.COM pid_t pid;
123*8823STruong.Q.Nguyen@Sun.COM int fd;
124*8823STruong.Q.Nguyen@Sun.COM
125*8823STruong.Q.Nguyen@Sun.COM (void) close(STDIN_FILENO);
126*8823STruong.Q.Nguyen@Sun.COM
127*8823STruong.Q.Nguyen@Sun.COM if ((fd = open(DEV_NULL, O_RDONLY)) == -1) {
128*8823STruong.Q.Nguyen@Sun.COM (void) printf("Could not open /dev/null: %s\n",
129*8823STruong.Q.Nguyen@Sun.COM strerror(errno));
130*8823STruong.Q.Nguyen@Sun.COM } else if (fd != STDIN_FILENO) {
131*8823STruong.Q.Nguyen@Sun.COM (void) dup2(fd, STDIN_FILENO);
132*8823STruong.Q.Nguyen@Sun.COM (void) close(fd);
133*8823STruong.Q.Nguyen@Sun.COM }
134*8823STruong.Q.Nguyen@Sun.COM (void) dup2(STDERR_FILENO, STDOUT_FILENO);
135*8823STruong.Q.Nguyen@Sun.COM closefrom(3);
136*8823STruong.Q.Nguyen@Sun.COM
137*8823STruong.Q.Nguyen@Sun.COM if ((pid = fork1()) < 0) {
138*8823STruong.Q.Nguyen@Sun.COM (void) printf("fork() failed: %s\n", strerror(errno));
139*8823STruong.Q.Nguyen@Sun.COM return (1);
140*8823STruong.Q.Nguyen@Sun.COM }
141*8823STruong.Q.Nguyen@Sun.COM
142*8823STruong.Q.Nguyen@Sun.COM if (pid != 0)
143*8823STruong.Q.Nguyen@Sun.COM exit(0);
144*8823STruong.Q.Nguyen@Sun.COM
145*8823STruong.Q.Nguyen@Sun.COM (void) setsid();
146*8823STruong.Q.Nguyen@Sun.COM (void) chdir("/");
147*8823STruong.Q.Nguyen@Sun.COM
148*8823STruong.Q.Nguyen@Sun.COM return (0);
149*8823STruong.Q.Nguyen@Sun.COM }
150*8823STruong.Q.Nguyen@Sun.COM
151*8823STruong.Q.Nguyen@Sun.COM static void
repository_rebind(scf_handle_t * hndl)152*8823STruong.Q.Nguyen@Sun.COM repository_rebind(scf_handle_t *hndl)
153*8823STruong.Q.Nguyen@Sun.COM {
154*8823STruong.Q.Nguyen@Sun.COM int c = 0;
155*8823STruong.Q.Nguyen@Sun.COM
156*8823STruong.Q.Nguyen@Sun.COM (void) scf_handle_unbind(hndl);
157*8823STruong.Q.Nguyen@Sun.COM while ((scf_handle_bind(hndl)) != 0) {
158*8823STruong.Q.Nguyen@Sun.COM if (c > MAX_RETRY) {
159*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON, "Repository access "
160*8823STruong.Q.Nguyen@Sun.COM "unavailable. Couldn't bind handle: %s\n",
161*8823STruong.Q.Nguyen@Sun.COM scf_strerror(scf_error()));
162*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON, "Service specific"
163*8823STruong.Q.Nguyen@Sun.COM "IPfilter configuration may not be updated "
164*8823STruong.Q.Nguyen@Sun.COM "properly\n");
165*8823STruong.Q.Nguyen@Sun.COM
166*8823STruong.Q.Nguyen@Sun.COM exit(1);
167*8823STruong.Q.Nguyen@Sun.COM } else {
168*8823STruong.Q.Nguyen@Sun.COM c++;
169*8823STruong.Q.Nguyen@Sun.COM }
170*8823STruong.Q.Nguyen@Sun.COM
171*8823STruong.Q.Nguyen@Sun.COM (void) sleep(1);
172*8823STruong.Q.Nguyen@Sun.COM }
173*8823STruong.Q.Nguyen@Sun.COM }
174*8823STruong.Q.Nguyen@Sun.COM
175*8823STruong.Q.Nguyen@Sun.COM static void
repository_notify_setup(scf_handle_t * h)176*8823STruong.Q.Nguyen@Sun.COM repository_notify_setup(scf_handle_t *h)
177*8823STruong.Q.Nguyen@Sun.COM {
178*8823STruong.Q.Nguyen@Sun.COM for (;;) {
179*8823STruong.Q.Nguyen@Sun.COM if (_scf_notify_add_pgtype(h, SCF_GROUP_FRAMEWORK) ==
180*8823STruong.Q.Nguyen@Sun.COM SCF_SUCCESS)
181*8823STruong.Q.Nguyen@Sun.COM break;
182*8823STruong.Q.Nguyen@Sun.COM
183*8823STruong.Q.Nguyen@Sun.COM switch (scf_error()) {
184*8823STruong.Q.Nguyen@Sun.COM case SCF_ERROR_CONNECTION_BROKEN:
185*8823STruong.Q.Nguyen@Sun.COM repository_rebind(h);
186*8823STruong.Q.Nguyen@Sun.COM break;
187*8823STruong.Q.Nguyen@Sun.COM
188*8823STruong.Q.Nguyen@Sun.COM case SCF_ERROR_NO_RESOURCES:
189*8823STruong.Q.Nguyen@Sun.COM (void) sleep(1);
190*8823STruong.Q.Nguyen@Sun.COM break;
191*8823STruong.Q.Nguyen@Sun.COM
192*8823STruong.Q.Nguyen@Sun.COM default:
193*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON,
194*8823STruong.Q.Nguyen@Sun.COM "Abort: Couldn't set up repository notification "
195*8823STruong.Q.Nguyen@Sun.COM "for pg type %s: %s\n", SCF_GROUP_FRAMEWORK,
196*8823STruong.Q.Nguyen@Sun.COM scf_strerror(scf_error()));
197*8823STruong.Q.Nguyen@Sun.COM abort();
198*8823STruong.Q.Nguyen@Sun.COM }
199*8823STruong.Q.Nguyen@Sun.COM }
200*8823STruong.Q.Nguyen@Sun.COM }
201*8823STruong.Q.Nguyen@Sun.COM
202*8823STruong.Q.Nguyen@Sun.COM /*
203*8823STruong.Q.Nguyen@Sun.COM * If the repository connection is lost, rebind and re-setup repository
204*8823STruong.Q.Nguyen@Sun.COM * notification. During the repository connection outage, services that
205*8823STruong.Q.Nguyen@Sun.COM * changed states wouldn't get the corresponding firewall update. To make
206*8823STruong.Q.Nguyen@Sun.COM * we're not out of sync, update the entire system firewall configuration,
207*8823STruong.Q.Nguyen@Sun.COM * invoke ipfilter_update(IPFILTER_FMRI).
208*8823STruong.Q.Nguyen@Sun.COM */
209*8823STruong.Q.Nguyen@Sun.COM static void
repository_setup()210*8823STruong.Q.Nguyen@Sun.COM repository_setup()
211*8823STruong.Q.Nguyen@Sun.COM {
212*8823STruong.Q.Nguyen@Sun.COM repository_rebind(h);
213*8823STruong.Q.Nguyen@Sun.COM repository_notify_setup(h);
214*8823STruong.Q.Nguyen@Sun.COM if (ipfilter_update(IPFILTER_FMRI) == -1) {
215*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON,
216*8823STruong.Q.Nguyen@Sun.COM "Failed to reconfigure system firewall.\n");
217*8823STruong.Q.Nguyen@Sun.COM }
218*8823STruong.Q.Nguyen@Sun.COM }
219*8823STruong.Q.Nguyen@Sun.COM
220*8823STruong.Q.Nguyen@Sun.COM static int
pg_get_prop_value(const scf_propertygroup_t * pg,const char * pname,scf_value_t * v)221*8823STruong.Q.Nguyen@Sun.COM pg_get_prop_value(const scf_propertygroup_t *pg, const char *pname,
222*8823STruong.Q.Nguyen@Sun.COM scf_value_t *v)
223*8823STruong.Q.Nguyen@Sun.COM {
224*8823STruong.Q.Nguyen@Sun.COM if (pg == NULL || pname == NULL || v == NULL)
225*8823STruong.Q.Nguyen@Sun.COM return (-1);
226*8823STruong.Q.Nguyen@Sun.COM
227*8823STruong.Q.Nguyen@Sun.COM if (scf_pg_get_property(pg, pname, scratch_prop) == -1 ||
228*8823STruong.Q.Nguyen@Sun.COM scf_property_get_value(scratch_prop, v) == -1) {
229*8823STruong.Q.Nguyen@Sun.COM switch (scf_error()) {
230*8823STruong.Q.Nguyen@Sun.COM case SCF_ERROR_NOT_FOUND:
231*8823STruong.Q.Nguyen@Sun.COM case SCF_ERROR_DELETED:
232*8823STruong.Q.Nguyen@Sun.COM break;
233*8823STruong.Q.Nguyen@Sun.COM
234*8823STruong.Q.Nguyen@Sun.COM default:
235*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON,
236*8823STruong.Q.Nguyen@Sun.COM "scf_pg_get_property failed for %s: %s\n",
237*8823STruong.Q.Nguyen@Sun.COM pname, scf_strerror(scf_error()));
238*8823STruong.Q.Nguyen@Sun.COM }
239*8823STruong.Q.Nguyen@Sun.COM return (-1);
240*8823STruong.Q.Nguyen@Sun.COM }
241*8823STruong.Q.Nguyen@Sun.COM return (0);
242*8823STruong.Q.Nguyen@Sun.COM }
243*8823STruong.Q.Nguyen@Sun.COM
244*8823STruong.Q.Nguyen@Sun.COM static int
is_correct_event(const char * fmri,const scf_propertygroup_t * pg,const boolean_t isrpc)245*8823STruong.Q.Nguyen@Sun.COM is_correct_event(const char *fmri, const scf_propertygroup_t *pg,
246*8823STruong.Q.Nguyen@Sun.COM const boolean_t isrpc)
247*8823STruong.Q.Nguyen@Sun.COM {
248*8823STruong.Q.Nguyen@Sun.COM char *state = NULL;
249*8823STruong.Q.Nguyen@Sun.COM const char **proplist = all_props;
250*8823STruong.Q.Nguyen@Sun.COM int prop_cnt = ALL_PROPS_CNT;
251*8823STruong.Q.Nguyen@Sun.COM
252*8823STruong.Q.Nguyen@Sun.COM int i, ret = 0;
253*8823STruong.Q.Nguyen@Sun.COM
254*8823STruong.Q.Nguyen@Sun.COM if (scf_pg_get_name(pg, scratch_name, max_scf_name_size) < 0) {
255*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON, "scf_pg_get_name failed: %s\n",
256*8823STruong.Q.Nguyen@Sun.COM scf_strerror(scf_error()));
257*8823STruong.Q.Nguyen@Sun.COM return (-1);
258*8823STruong.Q.Nguyen@Sun.COM }
259*8823STruong.Q.Nguyen@Sun.COM
260*8823STruong.Q.Nguyen@Sun.COM /*
261*8823STruong.Q.Nguyen@Sun.COM * We care about enable, disable, and refresh since that's
262*8823STruong.Q.Nguyen@Sun.COM * when we activate, deactivate, or change firewall policy.
263*8823STruong.Q.Nguyen@Sun.COM *
264*8823STruong.Q.Nguyen@Sun.COM * - enable/disable -> change in "general" or "general_ovr"
265*8823STruong.Q.Nguyen@Sun.COM * - refresh/restart -> change in "restarter_actions"
266*8823STruong.Q.Nguyen@Sun.COM */
267*8823STruong.Q.Nguyen@Sun.COM if (strcmp(scratch_name, SCF_PG_GENERAL) == 0 ||
268*8823STruong.Q.Nguyen@Sun.COM strcmp(scratch_name, SCF_PG_GENERAL_OVR) == 0) {
269*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_DEBUG | LOG_DAEMON, "Action: %s", scratch_name);
270*8823STruong.Q.Nguyen@Sun.COM return (1);
271*8823STruong.Q.Nguyen@Sun.COM }
272*8823STruong.Q.Nguyen@Sun.COM
273*8823STruong.Q.Nguyen@Sun.COM if ((state = smf_get_state(fmri)) == NULL) {
274*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON, "smf_get_state failed for %s: "
275*8823STruong.Q.Nguyen@Sun.COM "%s\n", fmri, scf_strerror(scf_error()));
276*8823STruong.Q.Nguyen@Sun.COM return (-1);
277*8823STruong.Q.Nguyen@Sun.COM }
278*8823STruong.Q.Nguyen@Sun.COM
279*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_DEBUG | LOG_DAEMON, "%s STATE: %s \n", fmri, state);
280*8823STruong.Q.Nguyen@Sun.COM if (strcmp(state, SCF_STATE_STRING_MAINT) == 0) {
281*8823STruong.Q.Nguyen@Sun.COM proplist = maint_props;
282*8823STruong.Q.Nguyen@Sun.COM prop_cnt = MAINT_PROPS_CNT;
283*8823STruong.Q.Nguyen@Sun.COM }
284*8823STruong.Q.Nguyen@Sun.COM
285*8823STruong.Q.Nguyen@Sun.COM /*
286*8823STruong.Q.Nguyen@Sun.COM * Only concerned with refresh, restart, and maint on|off actions.
287*8823STruong.Q.Nguyen@Sun.COM * RPC services are restarted whenever rpc/bind restarts so it's
288*8823STruong.Q.Nguyen@Sun.COM * an automatic valid event for RPC services.
289*8823STruong.Q.Nguyen@Sun.COM */
290*8823STruong.Q.Nguyen@Sun.COM if (isrpc) {
291*8823STruong.Q.Nguyen@Sun.COM ret = 1;
292*8823STruong.Q.Nguyen@Sun.COM goto out;
293*8823STruong.Q.Nguyen@Sun.COM } else if (strcmp(scratch_name, SCF_PG_RESTARTER_ACTIONS) == 0) {
294*8823STruong.Q.Nguyen@Sun.COM for (i = 0; i < prop_cnt; i++) {
295*8823STruong.Q.Nguyen@Sun.COM if (pg_get_prop_value(pg, proplist[i],
296*8823STruong.Q.Nguyen@Sun.COM scratch_v) == 0) {
297*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_DEBUG | LOG_DAEMON, "Action: %s/%s",
298*8823STruong.Q.Nguyen@Sun.COM scratch_name, proplist[i]);
299*8823STruong.Q.Nguyen@Sun.COM
300*8823STruong.Q.Nguyen@Sun.COM ret = 1;
301*8823STruong.Q.Nguyen@Sun.COM goto out;
302*8823STruong.Q.Nguyen@Sun.COM }
303*8823STruong.Q.Nguyen@Sun.COM }
304*8823STruong.Q.Nguyen@Sun.COM }
305*8823STruong.Q.Nguyen@Sun.COM
306*8823STruong.Q.Nguyen@Sun.COM out:
307*8823STruong.Q.Nguyen@Sun.COM if (state)
308*8823STruong.Q.Nguyen@Sun.COM free(state);
309*8823STruong.Q.Nguyen@Sun.COM
310*8823STruong.Q.Nguyen@Sun.COM return (ret);
311*8823STruong.Q.Nguyen@Sun.COM }
312*8823STruong.Q.Nguyen@Sun.COM
313*8823STruong.Q.Nguyen@Sun.COM static int
ipfilter_update(const char * fmri)314*8823STruong.Q.Nguyen@Sun.COM ipfilter_update(const char *fmri)
315*8823STruong.Q.Nguyen@Sun.COM {
316*8823STruong.Q.Nguyen@Sun.COM pid_t pid;
317*8823STruong.Q.Nguyen@Sun.COM int status, ret = 0;
318*8823STruong.Q.Nguyen@Sun.COM
319*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_DEBUG | LOG_DAEMON, "ipfilter_update: %s\n", fmri);
320*8823STruong.Q.Nguyen@Sun.COM
321*8823STruong.Q.Nguyen@Sun.COM /*
322*8823STruong.Q.Nguyen@Sun.COM * Start refresh in another process
323*8823STruong.Q.Nguyen@Sun.COM */
324*8823STruong.Q.Nguyen@Sun.COM if ((pid = fork1()) < 0) {
325*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON, "Couldn't fork to refresh "
326*8823STruong.Q.Nguyen@Sun.COM "ipfilter for %s: %s", fmri, strerror(errno));
327*8823STruong.Q.Nguyen@Sun.COM ret = 1;
328*8823STruong.Q.Nguyen@Sun.COM goto out;
329*8823STruong.Q.Nguyen@Sun.COM }
330*8823STruong.Q.Nguyen@Sun.COM
331*8823STruong.Q.Nguyen@Sun.COM if (pid == 0) {
332*8823STruong.Q.Nguyen@Sun.COM if (execl(IPF_UPDATE_CMD, IPF_UPDATE_CMD, "fw_update", fmri,
333*8823STruong.Q.Nguyen@Sun.COM NULL) == -1)
334*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON, "execl() failed for "
335*8823STruong.Q.Nguyen@Sun.COM "%s: %s", fmri, strerror(errno));
336*8823STruong.Q.Nguyen@Sun.COM
337*8823STruong.Q.Nguyen@Sun.COM exit(1);
338*8823STruong.Q.Nguyen@Sun.COM }
339*8823STruong.Q.Nguyen@Sun.COM
340*8823STruong.Q.Nguyen@Sun.COM /*
341*8823STruong.Q.Nguyen@Sun.COM * Parent - only one update at a time.
342*8823STruong.Q.Nguyen@Sun.COM */
343*8823STruong.Q.Nguyen@Sun.COM (void) wait(&status);
344*8823STruong.Q.Nguyen@Sun.COM if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
345*8823STruong.Q.Nguyen@Sun.COM ret = 1;
346*8823STruong.Q.Nguyen@Sun.COM
347*8823STruong.Q.Nguyen@Sun.COM out:
348*8823STruong.Q.Nguyen@Sun.COM if (ret == 1)
349*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON, "Firewall update failed "
350*8823STruong.Q.Nguyen@Sun.COM "for: %s\n", fmri);
351*8823STruong.Q.Nguyen@Sun.COM
352*8823STruong.Q.Nguyen@Sun.COM return (ret);
353*8823STruong.Q.Nguyen@Sun.COM }
354*8823STruong.Q.Nguyen@Sun.COM
355*8823STruong.Q.Nguyen@Sun.COM /*
356*8823STruong.Q.Nguyen@Sun.COM * Determine whether a given instance is a RPC service. Repository and
357*8823STruong.Q.Nguyen@Sun.COM * libscf errors are treated as if the service isn't an RPC service,
358*8823STruong.Q.Nguyen@Sun.COM * returning B_FALSE to indicate validation failure.
359*8823STruong.Q.Nguyen@Sun.COM */
360*8823STruong.Q.Nguyen@Sun.COM static boolean_t
service_is_rpc(const scf_instance_t * inst)361*8823STruong.Q.Nguyen@Sun.COM service_is_rpc(const scf_instance_t *inst)
362*8823STruong.Q.Nguyen@Sun.COM {
363*8823STruong.Q.Nguyen@Sun.COM scf_snapshot_t *lsnap = NULL;
364*8823STruong.Q.Nguyen@Sun.COM uint8_t isrpc;
365*8823STruong.Q.Nguyen@Sun.COM
366*8823STruong.Q.Nguyen@Sun.COM if (scf_instance_get_snapshot(inst, SCF_SNAPSHOT_RUNNING, snap) != 0) {
367*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_DEBUG | LOG_DAEMON,
368*8823STruong.Q.Nguyen@Sun.COM "Could not get running snapshot, using editing value\n");
369*8823STruong.Q.Nguyen@Sun.COM } else {
370*8823STruong.Q.Nguyen@Sun.COM lsnap = snap;
371*8823STruong.Q.Nguyen@Sun.COM }
372*8823STruong.Q.Nguyen@Sun.COM
373*8823STruong.Q.Nguyen@Sun.COM if (scf_instance_get_pg_composed(inst, lsnap, SCF_PG_INETD,
374*8823STruong.Q.Nguyen@Sun.COM scratch_pg) == -1) {
375*8823STruong.Q.Nguyen@Sun.COM switch (scf_error()) {
376*8823STruong.Q.Nguyen@Sun.COM case SCF_ERROR_NOT_FOUND:
377*8823STruong.Q.Nguyen@Sun.COM case SCF_ERROR_DELETED:
378*8823STruong.Q.Nguyen@Sun.COM break;
379*8823STruong.Q.Nguyen@Sun.COM
380*8823STruong.Q.Nguyen@Sun.COM default:
381*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON,
382*8823STruong.Q.Nguyen@Sun.COM "scf_instance_get_pg_composed failed: %s\n",
383*8823STruong.Q.Nguyen@Sun.COM scf_strerror(scf_error()));
384*8823STruong.Q.Nguyen@Sun.COM return (B_FALSE);
385*8823STruong.Q.Nguyen@Sun.COM }
386*8823STruong.Q.Nguyen@Sun.COM
387*8823STruong.Q.Nguyen@Sun.COM if (scf_instance_get_pg_composed(inst, lsnap,
388*8823STruong.Q.Nguyen@Sun.COM SCF_PG_FW_CONTEXT, scratch_pg) == -1) {
389*8823STruong.Q.Nguyen@Sun.COM switch (scf_error()) {
390*8823STruong.Q.Nguyen@Sun.COM case SCF_ERROR_NOT_FOUND:
391*8823STruong.Q.Nguyen@Sun.COM case SCF_ERROR_DELETED:
392*8823STruong.Q.Nguyen@Sun.COM break;
393*8823STruong.Q.Nguyen@Sun.COM
394*8823STruong.Q.Nguyen@Sun.COM default:
395*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON,
396*8823STruong.Q.Nguyen@Sun.COM "scf_instance_get_pg_composed failed: %s\n",
397*8823STruong.Q.Nguyen@Sun.COM scf_strerror(scf_error()));
398*8823STruong.Q.Nguyen@Sun.COM }
399*8823STruong.Q.Nguyen@Sun.COM return (B_FALSE);
400*8823STruong.Q.Nguyen@Sun.COM }
401*8823STruong.Q.Nguyen@Sun.COM }
402*8823STruong.Q.Nguyen@Sun.COM
403*8823STruong.Q.Nguyen@Sun.COM if (pg_get_prop_value(scratch_pg, SCF_PROPERTY_ISRPC, scratch_v) == -1)
404*8823STruong.Q.Nguyen@Sun.COM return (B_FALSE);
405*8823STruong.Q.Nguyen@Sun.COM
406*8823STruong.Q.Nguyen@Sun.COM if (scf_value_get_boolean(scratch_v, &isrpc) == -1) {
407*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON, "scf_value_get_boolean failed: "
408*8823STruong.Q.Nguyen@Sun.COM "%s\n", scf_strerror(scf_error()));
409*8823STruong.Q.Nguyen@Sun.COM return (B_FALSE);
410*8823STruong.Q.Nguyen@Sun.COM }
411*8823STruong.Q.Nguyen@Sun.COM
412*8823STruong.Q.Nguyen@Sun.COM if (isrpc)
413*8823STruong.Q.Nguyen@Sun.COM return (B_TRUE);
414*8823STruong.Q.Nguyen@Sun.COM else
415*8823STruong.Q.Nguyen@Sun.COM return (B_FALSE);
416*8823STruong.Q.Nguyen@Sun.COM }
417*8823STruong.Q.Nguyen@Sun.COM
418*8823STruong.Q.Nguyen@Sun.COM static int
instance_has_firewall(scf_instance_t * inst)419*8823STruong.Q.Nguyen@Sun.COM instance_has_firewall(scf_instance_t *inst)
420*8823STruong.Q.Nguyen@Sun.COM {
421*8823STruong.Q.Nguyen@Sun.COM scf_snapshot_t *lsnap = NULL;
422*8823STruong.Q.Nguyen@Sun.COM
423*8823STruong.Q.Nguyen@Sun.COM if (scf_instance_get_snapshot(inst, SCF_SNAPSHOT_RUNNING, snap) == -1) {
424*8823STruong.Q.Nguyen@Sun.COM switch (scf_error()) {
425*8823STruong.Q.Nguyen@Sun.COM case SCF_ERROR_CONNECTION_BROKEN:
426*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON,
427*8823STruong.Q.Nguyen@Sun.COM "scf_instance_get_snapshot failed: %s\n",
428*8823STruong.Q.Nguyen@Sun.COM scf_strerror(scf_error()));
429*8823STruong.Q.Nguyen@Sun.COM repository_setup();
430*8823STruong.Q.Nguyen@Sun.COM return (-1);
431*8823STruong.Q.Nguyen@Sun.COM
432*8823STruong.Q.Nguyen@Sun.COM case SCF_ERROR_DELETED:
433*8823STruong.Q.Nguyen@Sun.COM default:
434*8823STruong.Q.Nguyen@Sun.COM /*
435*8823STruong.Q.Nguyen@Sun.COM * If running snapshot is not available for
436*8823STruong.Q.Nguyen@Sun.COM * other reasons, fall back to current values.
437*8823STruong.Q.Nguyen@Sun.COM */
438*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_DEBUG | LOG_DAEMON, "Could not get "
439*8823STruong.Q.Nguyen@Sun.COM "running snapshot, using current value\n");
440*8823STruong.Q.Nguyen@Sun.COM }
441*8823STruong.Q.Nguyen@Sun.COM } else {
442*8823STruong.Q.Nguyen@Sun.COM lsnap = snap;
443*8823STruong.Q.Nguyen@Sun.COM }
444*8823STruong.Q.Nguyen@Sun.COM
445*8823STruong.Q.Nguyen@Sun.COM /*
446*8823STruong.Q.Nguyen@Sun.COM * Update service's IPfilter configuration if either
447*8823STruong.Q.Nguyen@Sun.COM * SCF_PG_FW_CONTEXT or SCF_PG_FW_CONFIG exists.
448*8823STruong.Q.Nguyen@Sun.COM */
449*8823STruong.Q.Nguyen@Sun.COM if (scf_instance_get_pg_composed(inst, lsnap, SCF_PG_FW_CONTEXT,
450*8823STruong.Q.Nguyen@Sun.COM scratch_pg) == 0) {
451*8823STruong.Q.Nguyen@Sun.COM return (1);
452*8823STruong.Q.Nguyen@Sun.COM } else {
453*8823STruong.Q.Nguyen@Sun.COM switch (scf_error()) {
454*8823STruong.Q.Nguyen@Sun.COM case SCF_ERROR_NOT_FOUND:
455*8823STruong.Q.Nguyen@Sun.COM case SCF_ERROR_DELETED:
456*8823STruong.Q.Nguyen@Sun.COM break;
457*8823STruong.Q.Nguyen@Sun.COM
458*8823STruong.Q.Nguyen@Sun.COM case SCF_ERROR_CONNECTION_BROKEN:
459*8823STruong.Q.Nguyen@Sun.COM repository_setup();
460*8823STruong.Q.Nguyen@Sun.COM /* FALLTHROUGH */
461*8823STruong.Q.Nguyen@Sun.COM default:
462*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON,
463*8823STruong.Q.Nguyen@Sun.COM "scf_instance_get_pg_composed failed: %s\n",
464*8823STruong.Q.Nguyen@Sun.COM scf_strerror(scf_error()));
465*8823STruong.Q.Nguyen@Sun.COM return (-1);
466*8823STruong.Q.Nguyen@Sun.COM }
467*8823STruong.Q.Nguyen@Sun.COM }
468*8823STruong.Q.Nguyen@Sun.COM
469*8823STruong.Q.Nguyen@Sun.COM if (scf_instance_get_pg_composed(inst, lsnap, SCF_PG_FW_CONFIG,
470*8823STruong.Q.Nguyen@Sun.COM scratch_pg) == -1) {
471*8823STruong.Q.Nguyen@Sun.COM /*
472*8823STruong.Q.Nguyen@Sun.COM * It's either a non-firewall service or a failure to
473*8823STruong.Q.Nguyen@Sun.COM * read firewall pg, just continue and listen for
474*8823STruong.Q.Nguyen@Sun.COM * future events.
475*8823STruong.Q.Nguyen@Sun.COM */
476*8823STruong.Q.Nguyen@Sun.COM switch (scf_error()) {
477*8823STruong.Q.Nguyen@Sun.COM case SCF_ERROR_NOT_FOUND:
478*8823STruong.Q.Nguyen@Sun.COM case SCF_ERROR_DELETED:
479*8823STruong.Q.Nguyen@Sun.COM return (0);
480*8823STruong.Q.Nguyen@Sun.COM
481*8823STruong.Q.Nguyen@Sun.COM case SCF_ERROR_CONNECTION_BROKEN:
482*8823STruong.Q.Nguyen@Sun.COM repository_setup();
483*8823STruong.Q.Nguyen@Sun.COM /* FALLTHROUGH */
484*8823STruong.Q.Nguyen@Sun.COM default:
485*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON,
486*8823STruong.Q.Nguyen@Sun.COM "scf_instance_get_pg_composed failed: %s\n",
487*8823STruong.Q.Nguyen@Sun.COM scf_strerror(scf_error()));
488*8823STruong.Q.Nguyen@Sun.COM return (-1);
489*8823STruong.Q.Nguyen@Sun.COM }
490*8823STruong.Q.Nguyen@Sun.COM }
491*8823STruong.Q.Nguyen@Sun.COM return (1);
492*8823STruong.Q.Nguyen@Sun.COM }
493*8823STruong.Q.Nguyen@Sun.COM
494*8823STruong.Q.Nguyen@Sun.COM static int
repository_event_process(scf_propertygroup_t * pg)495*8823STruong.Q.Nguyen@Sun.COM repository_event_process(scf_propertygroup_t *pg)
496*8823STruong.Q.Nguyen@Sun.COM {
497*8823STruong.Q.Nguyen@Sun.COM boolean_t isrpc = B_FALSE;
498*8823STruong.Q.Nguyen@Sun.COM int res;
499*8823STruong.Q.Nguyen@Sun.COM
500*8823STruong.Q.Nguyen@Sun.COM /*
501*8823STruong.Q.Nguyen@Sun.COM * Figure out it's a firewall capable instance and call ipfilter_update
502*8823STruong.Q.Nguyen@Sun.COM * if it is.
503*8823STruong.Q.Nguyen@Sun.COM */
504*8823STruong.Q.Nguyen@Sun.COM if (scf_pg_get_parent_instance(pg, inst) == -1) {
505*8823STruong.Q.Nguyen@Sun.COM /* Not an error if pg doesn't belong to a valid instance */
506*8823STruong.Q.Nguyen@Sun.COM if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) {
507*8823STruong.Q.Nguyen@Sun.COM return (0);
508*8823STruong.Q.Nguyen@Sun.COM }
509*8823STruong.Q.Nguyen@Sun.COM
510*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON, "scf_pg_get_parent_instance "
511*8823STruong.Q.Nguyen@Sun.COM "failed: %s\n", scf_strerror(scf_error()));
512*8823STruong.Q.Nguyen@Sun.COM
513*8823STruong.Q.Nguyen@Sun.COM if (scf_error() == SCF_ERROR_CONNECTION_BROKEN)
514*8823STruong.Q.Nguyen@Sun.COM repository_setup();
515*8823STruong.Q.Nguyen@Sun.COM
516*8823STruong.Q.Nguyen@Sun.COM return (1);
517*8823STruong.Q.Nguyen@Sun.COM }
518*8823STruong.Q.Nguyen@Sun.COM
519*8823STruong.Q.Nguyen@Sun.COM if (scf_instance_to_fmri(inst, scratch_fmri, max_scf_fmri_size) == -1) {
520*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON, "scf_instance_to_fmri "
521*8823STruong.Q.Nguyen@Sun.COM "failed: %s\n", scf_strerror(scf_error()));
522*8823STruong.Q.Nguyen@Sun.COM
523*8823STruong.Q.Nguyen@Sun.COM if (scf_error() == SCF_ERROR_CONNECTION_BROKEN)
524*8823STruong.Q.Nguyen@Sun.COM repository_setup();
525*8823STruong.Q.Nguyen@Sun.COM
526*8823STruong.Q.Nguyen@Sun.COM return (1);
527*8823STruong.Q.Nguyen@Sun.COM }
528*8823STruong.Q.Nguyen@Sun.COM
529*8823STruong.Q.Nguyen@Sun.COM if (strcmp(scratch_fmri, IPFILTER_FMRI) == 0) {
530*8823STruong.Q.Nguyen@Sun.COM return (0);
531*8823STruong.Q.Nguyen@Sun.COM }
532*8823STruong.Q.Nguyen@Sun.COM
533*8823STruong.Q.Nguyen@Sun.COM isrpc = service_is_rpc(inst);
534*8823STruong.Q.Nguyen@Sun.COM
535*8823STruong.Q.Nguyen@Sun.COM /*
536*8823STruong.Q.Nguyen@Sun.COM * If it's not an event we're interested in, returns success.
537*8823STruong.Q.Nguyen@Sun.COM */
538*8823STruong.Q.Nguyen@Sun.COM res = is_correct_event(scratch_fmri, pg, isrpc);
539*8823STruong.Q.Nguyen@Sun.COM if (res == -1) {
540*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON,
541*8823STruong.Q.Nguyen@Sun.COM "is_correct_event failed for %s.\n", scratch_fmri);
542*8823STruong.Q.Nguyen@Sun.COM return (1);
543*8823STruong.Q.Nguyen@Sun.COM } else if (res == 0) {
544*8823STruong.Q.Nguyen@Sun.COM return (0);
545*8823STruong.Q.Nguyen@Sun.COM }
546*8823STruong.Q.Nguyen@Sun.COM
547*8823STruong.Q.Nguyen@Sun.COM /*
548*8823STruong.Q.Nguyen@Sun.COM * Proceed only if instance has firewall policy.
549*8823STruong.Q.Nguyen@Sun.COM */
550*8823STruong.Q.Nguyen@Sun.COM res = instance_has_firewall(inst);
551*8823STruong.Q.Nguyen@Sun.COM if (res == -1) {
552*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON,
553*8823STruong.Q.Nguyen@Sun.COM "instance_has_firewall failed for %s.\n", scratch_fmri);
554*8823STruong.Q.Nguyen@Sun.COM return (1);
555*8823STruong.Q.Nguyen@Sun.COM } else if (res == 0) {
556*8823STruong.Q.Nguyen@Sun.COM return (0);
557*8823STruong.Q.Nguyen@Sun.COM }
558*8823STruong.Q.Nguyen@Sun.COM
559*8823STruong.Q.Nguyen@Sun.COM if (ipfilter_update(scratch_fmri) == -1) {
560*8823STruong.Q.Nguyen@Sun.COM return (1);
561*8823STruong.Q.Nguyen@Sun.COM }
562*8823STruong.Q.Nguyen@Sun.COM
563*8823STruong.Q.Nguyen@Sun.COM return (0);
564*8823STruong.Q.Nguyen@Sun.COM }
565*8823STruong.Q.Nguyen@Sun.COM
566*8823STruong.Q.Nguyen@Sun.COM static int
repository_event_wait()567*8823STruong.Q.Nguyen@Sun.COM repository_event_wait()
568*8823STruong.Q.Nguyen@Sun.COM {
569*8823STruong.Q.Nguyen@Sun.COM scf_propertygroup_t *pg;
570*8823STruong.Q.Nguyen@Sun.COM char *fmri, *scratch;
571*8823STruong.Q.Nguyen@Sun.COM const char *inst_name, *pg_name;
572*8823STruong.Q.Nguyen@Sun.COM ssize_t res;
573*8823STruong.Q.Nguyen@Sun.COM
574*8823STruong.Q.Nguyen@Sun.COM if ((fmri = umem_alloc(max_scf_fmri_size, UMEM_DEFAULT)) == NULL) {
575*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON, "Out of memory");
576*8823STruong.Q.Nguyen@Sun.COM return (1);
577*8823STruong.Q.Nguyen@Sun.COM }
578*8823STruong.Q.Nguyen@Sun.COM
579*8823STruong.Q.Nguyen@Sun.COM if ((scratch = umem_alloc(max_scf_fmri_size, UMEM_DEFAULT)) == NULL) {
580*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON, "Out of memory");
581*8823STruong.Q.Nguyen@Sun.COM return (1);
582*8823STruong.Q.Nguyen@Sun.COM }
583*8823STruong.Q.Nguyen@Sun.COM
584*8823STruong.Q.Nguyen@Sun.COM if ((pg = scf_pg_create(h)) == NULL) {
585*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON, "scf_pg_create failed: %s\n",
586*8823STruong.Q.Nguyen@Sun.COM scf_strerror(scf_error()));
587*8823STruong.Q.Nguyen@Sun.COM return (1);
588*8823STruong.Q.Nguyen@Sun.COM }
589*8823STruong.Q.Nguyen@Sun.COM
590*8823STruong.Q.Nguyen@Sun.COM repository_notify_setup(h);
591*8823STruong.Q.Nguyen@Sun.COM
592*8823STruong.Q.Nguyen@Sun.COM for (;;) {
593*8823STruong.Q.Nguyen@Sun.COM /*
594*8823STruong.Q.Nguyen@Sun.COM * Calling _scf_notify_wait which will block this thread
595*8823STruong.Q.Nguyen@Sun.COM * until it's notified of a framework event.
596*8823STruong.Q.Nguyen@Sun.COM *
597*8823STruong.Q.Nguyen@Sun.COM * Note: fmri is only set on delete events.
598*8823STruong.Q.Nguyen@Sun.COM */
599*8823STruong.Q.Nguyen@Sun.COM res = _scf_notify_wait(pg, fmri, max_scf_fmri_size);
600*8823STruong.Q.Nguyen@Sun.COM if (res < 0) {
601*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON, "_scf_notify_wait "
602*8823STruong.Q.Nguyen@Sun.COM "failed: %s\n", scf_strerror(scf_error()));
603*8823STruong.Q.Nguyen@Sun.COM repository_setup();
604*8823STruong.Q.Nguyen@Sun.COM } else if (res == 0) {
605*8823STruong.Q.Nguyen@Sun.COM if (repository_event_process(pg))
606*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON, "Service may have "
607*8823STruong.Q.Nguyen@Sun.COM "incorrect IPfilter configuration\n");
608*8823STruong.Q.Nguyen@Sun.COM } else {
609*8823STruong.Q.Nguyen@Sun.COM /*
610*8823STruong.Q.Nguyen@Sun.COM * The received event is a deletion of a service,
611*8823STruong.Q.Nguyen@Sun.COM * instance or pg. If it's a deletion of an instance,
612*8823STruong.Q.Nguyen@Sun.COM * update the instance's IPfilter configuration.
613*8823STruong.Q.Nguyen@Sun.COM */
614*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_DEBUG | LOG_DAEMON, "Deleted: %s", fmri);
615*8823STruong.Q.Nguyen@Sun.COM
616*8823STruong.Q.Nguyen@Sun.COM (void) strlcpy(scratch, fmri, max_scf_fmri_size);
617*8823STruong.Q.Nguyen@Sun.COM if (scf_parse_svc_fmri(scratch, NULL, NULL, &inst_name,
618*8823STruong.Q.Nguyen@Sun.COM &pg_name, NULL) != SCF_SUCCESS)
619*8823STruong.Q.Nguyen@Sun.COM continue;
620*8823STruong.Q.Nguyen@Sun.COM
621*8823STruong.Q.Nguyen@Sun.COM if (inst_name != NULL && pg_name == NULL) {
622*8823STruong.Q.Nguyen@Sun.COM (void) ipfilter_update(fmri);
623*8823STruong.Q.Nguyen@Sun.COM }
624*8823STruong.Q.Nguyen@Sun.COM }
625*8823STruong.Q.Nguyen@Sun.COM }
626*8823STruong.Q.Nguyen@Sun.COM
627*8823STruong.Q.Nguyen@Sun.COM /*NOTREACHED*/
628*8823STruong.Q.Nguyen@Sun.COM }
629*8823STruong.Q.Nguyen@Sun.COM
630*8823STruong.Q.Nguyen@Sun.COM int
main()631*8823STruong.Q.Nguyen@Sun.COM main()
632*8823STruong.Q.Nguyen@Sun.COM {
633*8823STruong.Q.Nguyen@Sun.COM if (daemonize_self() == 1)
634*8823STruong.Q.Nguyen@Sun.COM return (1);
635*8823STruong.Q.Nguyen@Sun.COM
636*8823STruong.Q.Nguyen@Sun.COM max_scf_fmri_size = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH) + 1;
637*8823STruong.Q.Nguyen@Sun.COM max_scf_name_size = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
638*8823STruong.Q.Nguyen@Sun.COM
639*8823STruong.Q.Nguyen@Sun.COM assert(max_scf_fmri_size > 0);
640*8823STruong.Q.Nguyen@Sun.COM assert(max_scf_name_size > 0);
641*8823STruong.Q.Nguyen@Sun.COM
642*8823STruong.Q.Nguyen@Sun.COM if ((h = scf_handle_create(SCF_VERSION)) == NULL) {
643*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON, "scf_handle_create failed: %s\n",
644*8823STruong.Q.Nguyen@Sun.COM scf_strerror(scf_error()));
645*8823STruong.Q.Nguyen@Sun.COM return (1);
646*8823STruong.Q.Nguyen@Sun.COM }
647*8823STruong.Q.Nguyen@Sun.COM
648*8823STruong.Q.Nguyen@Sun.COM repository_rebind(h);
649*8823STruong.Q.Nguyen@Sun.COM
650*8823STruong.Q.Nguyen@Sun.COM scratch_fmri = umem_alloc(max_scf_fmri_size, UMEM_DEFAULT);
651*8823STruong.Q.Nguyen@Sun.COM scratch_name = umem_alloc(max_scf_name_size, UMEM_DEFAULT);
652*8823STruong.Q.Nguyen@Sun.COM
653*8823STruong.Q.Nguyen@Sun.COM if (scratch_fmri == NULL || scratch_name == NULL) {
654*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON, "Out of memory");
655*8823STruong.Q.Nguyen@Sun.COM return (1);
656*8823STruong.Q.Nguyen@Sun.COM }
657*8823STruong.Q.Nguyen@Sun.COM
658*8823STruong.Q.Nguyen@Sun.COM inst = scf_instance_create(h);
659*8823STruong.Q.Nguyen@Sun.COM snap = scf_snapshot_create(h);
660*8823STruong.Q.Nguyen@Sun.COM scratch_pg = scf_pg_create(h);
661*8823STruong.Q.Nguyen@Sun.COM scratch_prop = scf_property_create(h);
662*8823STruong.Q.Nguyen@Sun.COM scratch_v = scf_value_create(h);
663*8823STruong.Q.Nguyen@Sun.COM
664*8823STruong.Q.Nguyen@Sun.COM if (inst == NULL || snap == NULL || scratch_pg == NULL ||
665*8823STruong.Q.Nguyen@Sun.COM scratch_prop == NULL || scratch_v == NULL) {
666*8823STruong.Q.Nguyen@Sun.COM syslog(LOG_ERR | LOG_DAEMON, "Initialization failed: %s\n",
667*8823STruong.Q.Nguyen@Sun.COM scf_strerror(scf_error()));
668*8823STruong.Q.Nguyen@Sun.COM return (1);
669*8823STruong.Q.Nguyen@Sun.COM }
670*8823STruong.Q.Nguyen@Sun.COM
671*8823STruong.Q.Nguyen@Sun.COM return (repository_event_wait());
672*8823STruong.Q.Nguyen@Sun.COM }
673