dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.lib / bridged / main.c
blob2e5eab4122e6a0821af54fe140a5e941702b3cdc
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * bridged - bridging control daemon.
31 #include <assert.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <pthread.h>
36 #include <string.h>
37 #include <signal.h>
38 #include <sys/stat.h>
39 #include <sys/types.h>
40 #include <sys/wait.h>
41 #include <syslog.h>
42 #include <locale.h>
43 #include <stropts.h>
45 #include "global.h"
47 boolean_t debugging;
48 uint32_t tablemax;
49 const char *instance_name = "default";
51 struct pollfd *fdarray;
53 dladm_handle_t dlhandle;
55 boolean_t shutting_down;
57 static pthread_t sighand;
60 * engine_lock is held while the main loop is busy calling librstp functions.
61 * Door threads take the lock to protect the library from reentrancy.
63 static pthread_mutex_t engine_lock = PTHREAD_MUTEX_INITIALIZER;
66 * These wrapper functions allow the other components in the daemon to remain
67 * ignorant of pthreads details.
69 int
70 lock_engine(void)
72 return (pthread_mutex_lock(&engine_lock));
75 void
76 unlock_engine(void)
78 (void) pthread_mutex_unlock(&engine_lock);
82 * Utility function for STREAMS ioctls.
84 ssize_t
85 strioctl(int fd, int cmd, void *buf, size_t buflen)
87 int retv;
88 struct strioctl ic;
90 ic.ic_cmd = cmd;
91 ic.ic_timout = 0;
92 ic.ic_dp = buf;
93 ic.ic_len = buflen;
94 if ((retv = ioctl(fd, I_STR, &ic)) != 0)
95 return (retv);
96 else
97 return (ic.ic_len);
100 static void
101 daemonize(void)
103 pid_t pid;
106 * A little bit of magic here. By the first fork+setsid, we
107 * disconnect from our current controlling terminal and become
108 * a session group leader. By forking again without calling
109 * setsid again, we make certain that we are not the session
110 * group leader and can never reacquire a controlling terminal.
112 if ((pid = fork()) == (pid_t)-1) {
113 syslog(LOG_ERR, "fork 1 failed");
114 exit(EXIT_FAILURE);
116 if (pid != 0) {
117 (void) wait(NULL);
118 _exit(EXIT_SUCCESS);
120 if (setsid() == (pid_t)-1) {
121 syslog(LOG_ERR, "setsid");
122 exit(EXIT_FAILURE);
124 if ((pid = fork()) == (pid_t)-1) {
125 syslog(LOG_ERR, "fork 2 failed");
126 exit(EXIT_FAILURE);
128 if (pid != 0)
129 _exit(EXIT_SUCCESS);
130 (void) chdir("/");
131 (void) umask(022);
134 static void *
135 sighandler(void *arg)
137 sigset_t sigset;
138 int sig;
139 int sigfd = (int)(uintptr_t)arg;
141 (void) sigfillset(&sigset);
143 for (;;) {
144 sig = sigwait(&sigset);
145 switch (sig) {
146 case SIGHUP:
147 (void) write(sigfd, "", 1);
148 break;
150 default:
151 if (debugging)
152 syslog(LOG_NOTICE, "%s signal, shutting down",
153 strsignal(sig));
154 shutting_down = B_TRUE;
155 break;
158 /* if we're shutting down, exit this thread */
159 if (shutting_down)
160 return (NULL);
164 static void
165 init_signalhandling(void)
167 pthread_attr_t attr;
168 int err;
169 sigset_t new;
170 int fildes[2];
172 if ((fdarray = malloc(FDOFFSET * sizeof (struct pollfd))) == NULL) {
173 syslog(LOG_ERR, "unable to allocate fdarray: %m");
174 exit(EXIT_FAILURE);
176 if (pipe(fildes) != 0) {
177 syslog(LOG_ERR, "unable to create signal pipe: %m");
178 exit(EXIT_FAILURE);
180 fdarray[0].fd = fildes[0];
181 fdarray[0].events = POLLIN;
182 assert(control_fd != -1);
183 fdarray[1].fd = control_fd;
184 fdarray[1].events = POLLIN;
186 (void) sigfillset(&new);
187 (void) pthread_sigmask(SIG_BLOCK, &new, NULL);
188 (void) pthread_attr_init(&attr);
189 (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
190 err = pthread_create(&sighand, &attr, sighandler,
191 (void *)(uintptr_t)fildes[1]);
192 if (err != 0) {
193 syslog(LOG_ERR, "cannot create signal handling thread: %s",
194 strerror(err));
195 exit(EXIT_FAILURE);
197 (void) pthread_attr_destroy(&attr);
201 main(int argc, char **argv)
203 dladm_status_t status;
204 char buf[DLADM_STRSIZE];
206 (void) setlocale(LC_ALL, "");
207 (void) textdomain(TEXT_DOMAIN);
209 shutting_down = B_FALSE;
210 openlog("bridged", LOG_PID | LOG_NDELAY, LOG_DAEMON);
212 if (argc != 2) {
213 syslog(LOG_ERR, "instance name is required");
214 exit(EXIT_FAILURE);
217 instance_name = argv[1];
219 if ((status = dladm_open(&dlhandle)) != DLADM_STATUS_OK) {
220 syslog(LOG_ERR, "%s: unable to open datalink control: %s",
221 instance_name, dladm_status2str(status, buf));
222 exit(EXIT_FAILURE);
225 status = dladm_bridge_get_privprop(instance_name, &debugging,
226 &tablemax);
227 if (status != DLADM_STATUS_OK) {
228 syslog(LOG_ERR, "%s: unable to read properties: %s",
229 instance_name, dladm_status2str(status, buf));
230 exit(EXIT_FAILURE);
233 /* Get the properties once so that we have the right initial values */
234 rstp_init();
236 open_bridge_control();
238 daemonize();
240 init_signalhandling();
241 init_door();
243 if (debugging)
244 syslog(LOG_INFO, "bridged started: instance %s", instance_name);
246 event_loop();
247 (void) pthread_cancel(sighand);
248 (void) pthread_join(sighand, NULL);
250 return (0);