1*5b133f3fSguenther /* $OpenBSD: monitor.c,v 1.31 2023/03/08 04:43:05 guenther Exp $ */
2b96c0bc5Shenning
3b96c0bc5Shenning /*
45ab9ebd3Smoritz * Copyright (c) 2004 Moritz Jodeit <moritz@openbsd.org>
5b96c0bc5Shenning *
6b96c0bc5Shenning * Permission to use, copy, modify, and distribute this software for any
7b96c0bc5Shenning * purpose with or without fee is hereby granted, provided that the above
8b96c0bc5Shenning * copyright notice and this permission notice appear in all copies.
9b96c0bc5Shenning *
10b96c0bc5Shenning * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11b96c0bc5Shenning * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12b96c0bc5Shenning * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13b96c0bc5Shenning * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14b96c0bc5Shenning * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15b96c0bc5Shenning * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16b96c0bc5Shenning * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17b96c0bc5Shenning */
18b96c0bc5Shenning
19b96c0bc5Shenning #include <sys/types.h>
20b96c0bc5Shenning #include <sys/socket.h>
21b96c0bc5Shenning #include <sys/wait.h>
22b96c0bc5Shenning #include <netinet/in.h>
23b96c0bc5Shenning
24b96c0bc5Shenning #include <errno.h>
25b96c0bc5Shenning #include <fcntl.h>
26b96c0bc5Shenning #include <paths.h>
27b96c0bc5Shenning #include <pwd.h>
28b96c0bc5Shenning #include <signal.h>
29b96c0bc5Shenning #include <stdarg.h>
304239b822Smillert #include <stdint.h>
31b96c0bc5Shenning #include <stdio.h>
32b96c0bc5Shenning #include <stdlib.h>
33b96c0bc5Shenning #include <string.h>
34b96c0bc5Shenning #include <syslog.h>
35b96c0bc5Shenning #include <unistd.h>
36b96c0bc5Shenning
37b96c0bc5Shenning #include "monitor.h"
3892f68775Sragge #include "extern.h"
39b96c0bc5Shenning
40b96c0bc5Shenning enum monitor_command {
41b96c0bc5Shenning CMD_USER,
42b96c0bc5Shenning CMD_PASS,
43efa4b9efSmoritz CMD_SOCKET,
44b96c0bc5Shenning CMD_BIND
45b96c0bc5Shenning };
46b96c0bc5Shenning
47b96c0bc5Shenning enum monitor_state {
48b96c0bc5Shenning PREAUTH,
49b96c0bc5Shenning POSTAUTH
50b96c0bc5Shenning };
51b96c0bc5Shenning
52b96c0bc5Shenning extern char remotehost[];
53f7818148Shenning extern char ttyline[20];
54b96c0bc5Shenning extern int debug;
55b96c0bc5Shenning
56b96c0bc5Shenning extern void set_slave_signals(void);
57b96c0bc5Shenning
58b96c0bc5Shenning int fd_monitor = -1;
59b96c0bc5Shenning int fd_slave = -1;
60b96c0bc5Shenning int nullfd;
614a5b429cShenning pid_t slave_pid = -1;
62b96c0bc5Shenning enum monitor_state state = PREAUTH;
63b96c0bc5Shenning
64b96c0bc5Shenning void send_data(int, void *, size_t);
65b96c0bc5Shenning void recv_data(int, void *, size_t);
663e113d76Smoritz void handle_cmds(void);
67b96c0bc5Shenning void set_monitor_signals(void);
68b96c0bc5Shenning void sig_pass_to_slave(int);
69b96c0bc5Shenning void sig_chld(int);
70b96c0bc5Shenning void fatalx(char *, ...);
71b96c0bc5Shenning void debugmsg(char *, ...);
72b96c0bc5Shenning
73b96c0bc5Shenning /*
74b96c0bc5Shenning * Send data over a socket and exit if something fails.
75b96c0bc5Shenning */
76b96c0bc5Shenning void
send_data(int sock,void * buf,size_t len)77b96c0bc5Shenning send_data(int sock, void *buf, size_t len)
78b96c0bc5Shenning {
79b96c0bc5Shenning ssize_t n;
80038ca976Smoritz size_t pos = 0;
81b96c0bc5Shenning char *ptr = buf;
82b96c0bc5Shenning
83038ca976Smoritz while (len > pos) {
84038ca976Smoritz switch (n = write(sock, ptr + pos, len - pos)) {
85038ca976Smoritz case 0:
8676d1ef43Sotto kill_slave("write failure");
87038ca976Smoritz _exit(0);
88038ca976Smoritz /* NOTREACHED */
89038ca976Smoritz case -1:
90038ca976Smoritz if (errno != EINTR && errno != EAGAIN)
91b96c0bc5Shenning fatalx("send_data: %m");
92038ca976Smoritz break;
93038ca976Smoritz default:
94038ca976Smoritz pos += n;
95038ca976Smoritz }
96b96c0bc5Shenning }
97b96c0bc5Shenning }
98b96c0bc5Shenning
99b96c0bc5Shenning /*
100b96c0bc5Shenning * Receive data from socket and exit if something fails.
101b96c0bc5Shenning */
102b96c0bc5Shenning void
recv_data(int sock,void * buf,size_t len)103b96c0bc5Shenning recv_data(int sock, void *buf, size_t len)
104b96c0bc5Shenning {
105b96c0bc5Shenning ssize_t n;
106038ca976Smoritz size_t pos = 0;
107b96c0bc5Shenning char *ptr = buf;
108b96c0bc5Shenning
109038ca976Smoritz while (len > pos) {
110038ca976Smoritz switch (n = read(sock, ptr + pos, len - pos)) {
111038ca976Smoritz case 0:
112ceb6fd83Smoritz kill_slave(NULL);
113038ca976Smoritz _exit(0);
114038ca976Smoritz /* NOTREACHED */
115038ca976Smoritz case -1:
116038ca976Smoritz if (errno != EINTR && errno != EAGAIN)
117b96c0bc5Shenning fatalx("recv_data: %m");
118038ca976Smoritz break;
119038ca976Smoritz default:
120038ca976Smoritz pos += n;
121038ca976Smoritz }
122b96c0bc5Shenning }
123b96c0bc5Shenning }
124b96c0bc5Shenning
125b96c0bc5Shenning void
set_monitor_signals(void)126b96c0bc5Shenning set_monitor_signals(void)
127b96c0bc5Shenning {
128b96c0bc5Shenning struct sigaction act;
129b96c0bc5Shenning int i;
130b96c0bc5Shenning
131643f308cSmoritz sigfillset(&act.sa_mask);
1323e113d76Smoritz act.sa_flags = SA_RESTART;
133b96c0bc5Shenning
134b96c0bc5Shenning act.sa_handler = SIG_DFL;
135b96c0bc5Shenning for (i = 1; i < _NSIG; i++)
136b96c0bc5Shenning sigaction(i, &act, NULL);
137b96c0bc5Shenning
138b96c0bc5Shenning act.sa_handler = sig_chld;
139b96c0bc5Shenning sigaction(SIGCHLD, &act, NULL);
140b96c0bc5Shenning
141b96c0bc5Shenning act.sa_handler = sig_pass_to_slave;
142b96c0bc5Shenning sigaction(SIGHUP, &act, NULL);
143b96c0bc5Shenning sigaction(SIGINT, &act, NULL);
144b96c0bc5Shenning sigaction(SIGQUIT, &act, NULL);
145b96c0bc5Shenning sigaction(SIGTERM, &act, NULL);
146b96c0bc5Shenning }
147b96c0bc5Shenning
148b96c0bc5Shenning /*
149b96c0bc5Shenning * Creates the privileged monitor process. It returns twice.
150b96c0bc5Shenning * It returns 1 for the unprivileged slave process and 0 for the
151b96c0bc5Shenning * user-privileged slave process after successful authentication.
152b96c0bc5Shenning */
153b96c0bc5Shenning int
monitor_init(void)154b96c0bc5Shenning monitor_init(void)
155b96c0bc5Shenning {
156b96c0bc5Shenning struct passwd *pw;
157b96c0bc5Shenning int pair[2];
158b96c0bc5Shenning
159b96c0bc5Shenning if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, pair) == -1)
160b96c0bc5Shenning fatalx("socketpair failed");
161b96c0bc5Shenning
162b96c0bc5Shenning fd_monitor = pair[0];
163b96c0bc5Shenning fd_slave = pair[1];
164b96c0bc5Shenning
165b96c0bc5Shenning set_monitor_signals();
166b96c0bc5Shenning
167b96c0bc5Shenning slave_pid = fork();
168b96c0bc5Shenning if (slave_pid == -1)
169b96c0bc5Shenning fatalx("fork of unprivileged slave failed");
170b96c0bc5Shenning if (slave_pid == 0) {
171b96c0bc5Shenning /* Unprivileged slave */
172b96c0bc5Shenning set_slave_signals();
173b96c0bc5Shenning
174b96c0bc5Shenning if ((pw = getpwnam(FTPD_PRIVSEP_USER)) == NULL)
175b96c0bc5Shenning fatalx("privilege separation user %s not found",
176b96c0bc5Shenning FTPD_PRIVSEP_USER);
177b96c0bc5Shenning
178b96c0bc5Shenning if (chroot(pw->pw_dir) == -1)
179b96c0bc5Shenning fatalx("chroot %s: %m", pw->pw_dir);
180b96c0bc5Shenning if (chdir("/") == -1)
181b96c0bc5Shenning fatalx("chdir /: %m");
182b96c0bc5Shenning
183b96c0bc5Shenning if (setgroups(1, &pw->pw_gid) == -1)
184b96c0bc5Shenning fatalx("setgroups: %m");
18522e57725Sderaadt if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1)
18622e57725Sderaadt fatalx("setresgid failed");
18722e57725Sderaadt if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
18822e57725Sderaadt fatalx("setresuid failed");
189821c3d91Smoritz
190821c3d91Smoritz endpwent();
191b96c0bc5Shenning close(fd_slave);
192b96c0bc5Shenning return (1);
193b96c0bc5Shenning }
194b96c0bc5Shenning
195b96c0bc5Shenning setproctitle("%s: [priv pre-auth]", remotehost);
196b96c0bc5Shenning
1973e113d76Smoritz handle_cmds();
198b96c0bc5Shenning
199b96c0bc5Shenning /* User-privileged slave */
200b96c0bc5Shenning return (0);
201b96c0bc5Shenning }
202b96c0bc5Shenning
203b96c0bc5Shenning /*
204b96c0bc5Shenning * Creates the user-privileged slave process. It is called
205b96c0bc5Shenning * from the privileged monitor process and returns twice. It returns 0
206b96c0bc5Shenning * for the user-privileged slave process and 1 for the monitor process.
207b96c0bc5Shenning */
208b96c0bc5Shenning int
monitor_post_auth(void)20918a2fcc3Sjan monitor_post_auth(void)
210b96c0bc5Shenning {
211b96c0bc5Shenning slave_pid = fork();
212b96c0bc5Shenning if (slave_pid == -1)
213b96c0bc5Shenning fatalx("fork of user-privileged slave failed");
214f7818148Shenning
215f7818148Shenning snprintf(ttyline, sizeof(ttyline), "ftp%ld",
216f7818148Shenning slave_pid == 0 ? (long)getpid() : (long)slave_pid);
217f7818148Shenning
218b96c0bc5Shenning if (slave_pid == 0) {
219b96c0bc5Shenning /* User privileged slave */
220b96c0bc5Shenning close(fd_slave);
221b96c0bc5Shenning set_slave_signals();
222b96c0bc5Shenning return (0);
223b96c0bc5Shenning }
224b96c0bc5Shenning
225b96c0bc5Shenning /* We have to keep stdout open, because reply() needs it. */
226b7041c07Sderaadt if ((nullfd = open(_PATH_DEVNULL, O_RDWR)) == -1)
227b96c0bc5Shenning fatalx("cannot open %s: %m", _PATH_DEVNULL);
228b96c0bc5Shenning dup2(nullfd, STDIN_FILENO);
229b96c0bc5Shenning dup2(nullfd, STDERR_FILENO);
230b96c0bc5Shenning close(nullfd);
231b96c0bc5Shenning close(fd_monitor);
232b96c0bc5Shenning
233b96c0bc5Shenning return (1);
234b96c0bc5Shenning }
235b96c0bc5Shenning
236b96c0bc5Shenning /*
2373e113d76Smoritz * Handles commands received from the slave process. It will not return
2383e113d76Smoritz * except in one situation: After successful authentication it will
2393e113d76Smoritz * return as the user-privileged slave process.
240b96c0bc5Shenning */
2413e113d76Smoritz void
handle_cmds(void)242b96c0bc5Shenning handle_cmds(void)
243b96c0bc5Shenning {
244b96c0bc5Shenning enum monitor_command cmd;
245b96c0bc5Shenning enum auth_ret auth;
246efa4b9efSmoritz int err, s, slavequit, serrno, domain;
2473e113d76Smoritz pid_t preauth_slave_pid;
248b96c0bc5Shenning size_t len;
249f0b01e45Ssthen union sockunion sa;
250b96c0bc5Shenning socklen_t salen;
251b96c0bc5Shenning char *name, *pw;
252b96c0bc5Shenning
2533e113d76Smoritz for (;;) {
2543e113d76Smoritz recv_data(fd_slave, &cmd, sizeof(cmd));
255b96c0bc5Shenning
256b96c0bc5Shenning switch (cmd) {
257b96c0bc5Shenning case CMD_USER:
258b96c0bc5Shenning debugmsg("CMD_USER received");
259b96c0bc5Shenning
260b96c0bc5Shenning recv_data(fd_slave, &len, sizeof(len));
2614239b822Smillert if (len == SIZE_MAX)
262a8ad9a0aSmoritz fatalx("monitor received invalid user length");
263b96c0bc5Shenning if ((name = malloc(len + 1)) == NULL)
264b96c0bc5Shenning fatalx("malloc: %m");
2657fdde7a3Smoritz if (len > 0)
266b96c0bc5Shenning recv_data(fd_slave, name, len);
267b96c0bc5Shenning name[len] = '\0';
268b96c0bc5Shenning
269b96c0bc5Shenning user(name);
270b96c0bc5Shenning free(name);
271b96c0bc5Shenning break;
272b96c0bc5Shenning case CMD_PASS:
273b96c0bc5Shenning debugmsg("CMD_PASS received");
274b96c0bc5Shenning
275b96c0bc5Shenning recv_data(fd_slave, &len, sizeof(len));
2764239b822Smillert if (len == SIZE_MAX)
277a8ad9a0aSmoritz fatalx("monitor received invalid pass length");
278b96c0bc5Shenning if ((pw = malloc(len + 1)) == NULL)
279b96c0bc5Shenning fatalx("malloc: %m");
2807fdde7a3Smoritz if (len > 0)
281b96c0bc5Shenning recv_data(fd_slave, pw, len);
282b96c0bc5Shenning pw[len] = '\0';
283b96c0bc5Shenning
2843e113d76Smoritz preauth_slave_pid = slave_pid;
2853e113d76Smoritz
286b96c0bc5Shenning auth = pass(pw);
287e4c28d58Sderaadt freezero(pw, len);
288b96c0bc5Shenning
289b96c0bc5Shenning switch (auth) {
290b96c0bc5Shenning case AUTH_FAILED:
291b96c0bc5Shenning /* Authentication failure */
292b96c0bc5Shenning debugmsg("authentication failed");
293b96c0bc5Shenning slavequit = 0;
294b96c0bc5Shenning send_data(fd_slave, &slavequit,
295b96c0bc5Shenning sizeof(slavequit));
296b96c0bc5Shenning break;
297b96c0bc5Shenning case AUTH_SLAVE:
298fcba609bSjan if (pledge("stdio rpath wpath cpath inet recvfd"
299fcba609bSjan " sendfd proc tty getpw", NULL) == -1)
300fcba609bSjan fatalx("pledge");
301b96c0bc5Shenning /* User-privileged slave */
302b96c0bc5Shenning debugmsg("user-privileged slave started");
3033e113d76Smoritz return;
304b96c0bc5Shenning /* NOTREACHED */
305b96c0bc5Shenning case AUTH_MONITOR:
306fcba609bSjan if (pledge("stdio inet sendfd recvfd proc",
307fcba609bSjan NULL) == -1)
308fcba609bSjan fatalx("pledge");
309b96c0bc5Shenning /* Post-auth monitor */
310b96c0bc5Shenning debugmsg("monitor went into post-auth phase");
311b96c0bc5Shenning state = POSTAUTH;
312b96c0bc5Shenning setproctitle("%s: [priv post-auth]",
313b96c0bc5Shenning remotehost);
314b96c0bc5Shenning slavequit = 1;
315b96c0bc5Shenning
316b96c0bc5Shenning send_data(fd_slave, &slavequit,
317b96c0bc5Shenning sizeof(slavequit));
3183e113d76Smoritz
319df69c215Sderaadt while (waitpid(preauth_slave_pid, NULL, 0) == -1 &&
32095cc8c4aSderaadt errno == EINTR)
3213e113d76Smoritz ;
322b96c0bc5Shenning break;
323b96c0bc5Shenning default:
324b96c0bc5Shenning fatalx("bad return value from pass()");
325b96c0bc5Shenning /* NOTREACHED */
326b96c0bc5Shenning }
327b96c0bc5Shenning break;
328efa4b9efSmoritz case CMD_SOCKET:
329efa4b9efSmoritz debugmsg("CMD_SOCKET received");
330efa4b9efSmoritz
331efa4b9efSmoritz if (state != POSTAUTH)
332efa4b9efSmoritz fatalx("CMD_SOCKET received in invalid state");
333efa4b9efSmoritz
334efa4b9efSmoritz recv_data(fd_slave, &domain, sizeof(domain));
335efa4b9efSmoritz if (domain != AF_INET && domain != AF_INET6)
336efa4b9efSmoritz fatalx("monitor received invalid addr family");
337efa4b9efSmoritz
338efa4b9efSmoritz s = socket(domain, SOCK_STREAM, 0);
339efa4b9efSmoritz serrno = errno;
340efa4b9efSmoritz
341efa4b9efSmoritz send_fd(fd_slave, s);
342efa4b9efSmoritz if (s == -1)
343efa4b9efSmoritz send_data(fd_slave, &serrno, sizeof(serrno));
344efa4b9efSmoritz else
345efa4b9efSmoritz close(s);
346efa4b9efSmoritz break;
347b96c0bc5Shenning case CMD_BIND:
348b96c0bc5Shenning debugmsg("CMD_BIND received");
349b96c0bc5Shenning
350b96c0bc5Shenning if (state != POSTAUTH)
351b96c0bc5Shenning fatalx("CMD_BIND received in invalid state");
352b96c0bc5Shenning
353b96c0bc5Shenning s = recv_fd(fd_slave);
354b96c0bc5Shenning
355b96c0bc5Shenning recv_data(fd_slave, &salen, sizeof(salen));
356b96c0bc5Shenning if (salen == 0 || salen > sizeof(sa))
357f0b01e45Ssthen fatalx("monitor received invalid sockaddr len");
358b96c0bc5Shenning
359b96c0bc5Shenning bzero(&sa, sizeof(sa));
360b96c0bc5Shenning recv_data(fd_slave, &sa, salen);
361b96c0bc5Shenning
362f0b01e45Ssthen if (sa.su_si.si_len != salen)
363f0b01e45Ssthen fatalx("monitor received invalid sockaddr len");
364b96c0bc5Shenning
365f0b01e45Ssthen if (sa.su_si.si_family != AF_INET &&
366f0b01e45Ssthen sa.su_si.si_family != AF_INET6)
367b96c0bc5Shenning fatalx("monitor received invalid addr family");
368b96c0bc5Shenning
369f0b01e45Ssthen err = bind(s, (struct sockaddr *)&sa, salen);
370b96c0bc5Shenning serrno = errno;
371b96c0bc5Shenning
372b96c0bc5Shenning if (s >= 0)
373b96c0bc5Shenning close(s);
374b96c0bc5Shenning
375b96c0bc5Shenning send_data(fd_slave, &err, sizeof(err));
376b96c0bc5Shenning if (err == -1)
377b96c0bc5Shenning send_data(fd_slave, &serrno, sizeof(serrno));
378b96c0bc5Shenning break;
379b96c0bc5Shenning default:
380b96c0bc5Shenning fatalx("monitor received unknown command %d", cmd);
381b96c0bc5Shenning /* NOTREACHED */
382b96c0bc5Shenning }
383b96c0bc5Shenning }
384b96c0bc5Shenning }
385b96c0bc5Shenning
386b96c0bc5Shenning void
sig_pass_to_slave(int signo)387b96c0bc5Shenning sig_pass_to_slave(int signo)
388b96c0bc5Shenning {
389b96c0bc5Shenning int olderrno = errno;
390b96c0bc5Shenning
3914a5b429cShenning if (slave_pid > 0)
392b96c0bc5Shenning kill(slave_pid, signo);
393b96c0bc5Shenning
394b96c0bc5Shenning errno = olderrno;
395b96c0bc5Shenning }
396b96c0bc5Shenning
397b96c0bc5Shenning void
sig_chld(int signo)398b96c0bc5Shenning sig_chld(int signo)
399b96c0bc5Shenning {
400b96c0bc5Shenning pid_t pid;
401b96c0bc5Shenning int stat, olderrno = errno;
402b96c0bc5Shenning
403b96c0bc5Shenning do {
4043e113d76Smoritz pid = waitpid(slave_pid, &stat, WNOHANG);
4053e113d76Smoritz if (pid > 0)
4063e113d76Smoritz _exit(0);
407b96c0bc5Shenning } while (pid == -1 && errno == EINTR);
408b96c0bc5Shenning
409b96c0bc5Shenning errno = olderrno;
410b96c0bc5Shenning }
411b96c0bc5Shenning
412b96c0bc5Shenning void
kill_slave(char * reason)41376d1ef43Sotto kill_slave(char *reason)
414b96c0bc5Shenning {
41576d1ef43Sotto if (slave_pid > 0) {
416ceb6fd83Smoritz if (reason)
417ceb6fd83Smoritz syslog(LOG_NOTICE, "kill slave %d: %s",
418ceb6fd83Smoritz slave_pid, reason);
419b96c0bc5Shenning kill(slave_pid, SIGQUIT);
420b96c0bc5Shenning }
42176d1ef43Sotto }
422b96c0bc5Shenning
423b96c0bc5Shenning void
fatalx(char * fmt,...)424b96c0bc5Shenning fatalx(char *fmt, ...)
425b96c0bc5Shenning {
426b96c0bc5Shenning va_list ap;
427b96c0bc5Shenning
428b96c0bc5Shenning va_start(ap, fmt);
429b96c0bc5Shenning vsyslog(LOG_ERR, fmt, ap);
430b96c0bc5Shenning va_end(ap);
431b96c0bc5Shenning
43276d1ef43Sotto kill_slave("fatal error");
433b96c0bc5Shenning
434b96c0bc5Shenning _exit(0);
435b96c0bc5Shenning }
436b96c0bc5Shenning
437b96c0bc5Shenning void
debugmsg(char * fmt,...)438b96c0bc5Shenning debugmsg(char *fmt, ...)
439b96c0bc5Shenning {
440b96c0bc5Shenning va_list ap;
441b96c0bc5Shenning
442b96c0bc5Shenning if (debug) {
443b96c0bc5Shenning va_start(ap, fmt);
444b96c0bc5Shenning vsyslog(LOG_DEBUG, fmt, ap);
445b96c0bc5Shenning va_end(ap);
446b96c0bc5Shenning }
447b96c0bc5Shenning }
448b96c0bc5Shenning
449b96c0bc5Shenning void
monitor_user(char * name)450b96c0bc5Shenning monitor_user(char *name)
451b96c0bc5Shenning {
452b96c0bc5Shenning enum monitor_command cmd;
453b96c0bc5Shenning size_t len;
454b96c0bc5Shenning
455b96c0bc5Shenning cmd = CMD_USER;
456b96c0bc5Shenning send_data(fd_monitor, &cmd, sizeof(cmd));
457b96c0bc5Shenning
458b96c0bc5Shenning len = strlen(name);
459b96c0bc5Shenning send_data(fd_monitor, &len, sizeof(len));
460b96c0bc5Shenning if (len > 0)
461b96c0bc5Shenning send_data(fd_monitor, name, len);
462b96c0bc5Shenning }
463b96c0bc5Shenning
464b96c0bc5Shenning int
monitor_pass(char * pass)465b96c0bc5Shenning monitor_pass(char *pass)
466b96c0bc5Shenning {
467b96c0bc5Shenning enum monitor_command cmd;
468b96c0bc5Shenning int quitnow;
469b96c0bc5Shenning size_t len;
470b96c0bc5Shenning
471b96c0bc5Shenning cmd = CMD_PASS;
472b96c0bc5Shenning send_data(fd_monitor, &cmd, sizeof(cmd));
473b96c0bc5Shenning
474b96c0bc5Shenning len = strlen(pass);
475b96c0bc5Shenning send_data(fd_monitor, &len, sizeof(len));
476b96c0bc5Shenning if (len > 0)
477b96c0bc5Shenning send_data(fd_monitor, pass, len);
478b96c0bc5Shenning
479b96c0bc5Shenning recv_data(fd_monitor, &quitnow, sizeof(quitnow));
480b96c0bc5Shenning
481b96c0bc5Shenning return (quitnow);
482b96c0bc5Shenning }
483b96c0bc5Shenning
484b96c0bc5Shenning int
monitor_socket(int domain)485efa4b9efSmoritz monitor_socket(int domain)
486efa4b9efSmoritz {
487efa4b9efSmoritz enum monitor_command cmd;
488efa4b9efSmoritz int s, serrno;
489efa4b9efSmoritz
490efa4b9efSmoritz cmd = CMD_SOCKET;
491efa4b9efSmoritz send_data(fd_monitor, &cmd, sizeof(cmd));
492efa4b9efSmoritz send_data(fd_monitor, &domain, sizeof(domain));
493efa4b9efSmoritz
494efa4b9efSmoritz s = recv_fd(fd_monitor);
495efa4b9efSmoritz if (s == -1) {
496efa4b9efSmoritz recv_data(fd_monitor, &serrno, sizeof(serrno));
497efa4b9efSmoritz errno = serrno;
498efa4b9efSmoritz }
499efa4b9efSmoritz
500efa4b9efSmoritz return (s);
501efa4b9efSmoritz }
502efa4b9efSmoritz
503efa4b9efSmoritz int
monitor_bind(int s,struct sockaddr * name,socklen_t namelen)504b96c0bc5Shenning monitor_bind(int s, struct sockaddr *name, socklen_t namelen)
505b96c0bc5Shenning {
506b96c0bc5Shenning enum monitor_command cmd;
507b96c0bc5Shenning int ret, serrno;
508b96c0bc5Shenning
509b96c0bc5Shenning cmd = CMD_BIND;
510b96c0bc5Shenning send_data(fd_monitor, &cmd, sizeof(cmd));
511b96c0bc5Shenning
512b96c0bc5Shenning send_fd(fd_monitor, s);
513b96c0bc5Shenning send_data(fd_monitor, &namelen, sizeof(namelen));
514b96c0bc5Shenning send_data(fd_monitor, name, namelen);
515b96c0bc5Shenning
516b96c0bc5Shenning recv_data(fd_monitor, &ret, sizeof(ret));
517b96c0bc5Shenning if (ret == -1) {
518b96c0bc5Shenning recv_data(fd_monitor, &serrno, sizeof(serrno));
519b96c0bc5Shenning errno = serrno;
520b96c0bc5Shenning }
521b96c0bc5Shenning
522b96c0bc5Shenning return (ret);
523b96c0bc5Shenning }
524