2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1999 University of Maryland at College Park
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of U.M. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. U.M. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Authors: the Amanda Development Team. Its members are listed in a
24 * file named AUTHORS, in the root directory of this distribution.
28 * $Id: amandad.c,v 1.18 2006/08/21 20:17:09 martinea Exp $
30 * handle client-host side of Amanda network communications, including
31 * security checks, execution of the proper service, and acking the
39 #include "amfeatures.h"
48 #define REP_TIMEOUT (6*60*60) /* secs for service to reply */
49 #define ACK_TIMEOUT 10 /* XXX should be configurable */
51 #define amandad_debug(i, ...) do { \
52 if ((i) <= debug_amandad) { \
53 dbprintf(__VA_ARGS__); \
58 * These are the actions for entering the state machine
60 typedef enum { A_START, A_RECVPKT, A_RECVREP, A_PENDING, A_FINISH, A_CONTINUE,
61 A_SENDNAK, A_TIMEOUT } action_t;
64 * This is a state in the state machine. It is a function pointer to
65 * the function that actually implements the state.
67 struct active_service;
68 typedef action_t (*state_t)(struct active_service *, action_t, pkt_t *);
71 * This structure describes an active running service.
73 * An active service is something running that we have received
74 * a request for. This structure holds info on that service, including
75 * file descriptors for data, etc, as well as the security handle
76 * for communications with the amanda server.
78 struct active_service {
79 char *cmd; /* name of command we ran */
80 char *arguments; /* arguments we sent it */
81 security_handle_t *security_handle; /* remote server */
82 state_t state; /* how far this has progressed */
83 pid_t pid; /* pid of subprocess */
84 int send_partial_reply; /* send PREP packet */
85 int reqfd; /* pipe to write requests */
86 int repfd; /* pipe to read replies */
87 event_handle_t *ev_repfd; /* read event handle for repfd */
88 event_handle_t *ev_reptimeout; /* timeout for rep data */
89 pkt_t rep_pkt; /* rep packet we're sending out */
90 char *repbuf; /* buffer to read the rep into */
91 size_t bufsize; /* length of repbuf */
92 size_t repbufsize; /* length of repbuf */
93 int repretry; /* times we'll retry sending the rep */
95 * General user streams to the process, and their equivalent
98 struct datafd_handle {
99 int fd_read; /* pipe to child process */
100 int fd_write; /* pipe to child process */
101 event_handle_t *ev_read; /* it's read event handle */
102 event_handle_t *ev_write; /* it's write event handle */
103 security_stream_t *netfd; /* stream to amanda server */
104 struct active_service *as; /* pointer back to our enclosure */
105 } data[DATA_FD_COUNT];
106 char databuf[NETWORK_BLOCK_BYTES]; /* buffer to relay netfd data in */
107 TAILQ_ENTRY(active_service) tq; /* queue handle */
111 * Here are the services that we allow.
113 static struct services {
124 #define NSERVICES (int)(sizeof(services) / sizeof(services[0]))
127 * Queue of outstanding requests that we are running.
130 TAILQ_HEAD(, active_service) tailq;
133 TAILQ_HEAD_INITIALIZER(serviceq.tailq), 0
136 static int wait_30s = 1;
137 static int exit_on_qlength = 1;
138 static char *auth = NULL;
139 static kencrypt_type amandad_kencrypt = KENCRYPT_NONE;
141 int main(int argc, char **argv);
143 static int allocstream(struct active_service *, int);
144 static void exit_check(void *);
145 static void protocol_accept(security_handle_t *, pkt_t *);
146 static void state_machine(struct active_service *, action_t, pkt_t *);
148 static action_t s_sendack(struct active_service *, action_t, pkt_t *);
149 static action_t s_repwait(struct active_service *, action_t, pkt_t *);
150 static action_t s_processrep(struct active_service *, action_t, pkt_t *);
151 static action_t s_sendrep(struct active_service *, action_t, pkt_t *);
152 static action_t s_ackwait(struct active_service *, action_t, pkt_t *);
154 static void repfd_recv(void *);
155 static void timeout_repfd(void *);
156 static void protocol_recv(void *, pkt_t *, security_status_t);
157 static void process_readnetfd(void *);
158 static void process_writenetfd(void *, void *, ssize_t);
159 static struct active_service *service_new(security_handle_t *,
160 const char *, const char *);
161 static void service_delete(struct active_service *);
162 static int writebuf(struct active_service *, const void *, size_t);
163 static ssize_t do_sendpkt(security_handle_t *handle, pkt_t *pkt);
164 static char *amandad_get_security_conf (char *, void *);
166 static const char *state2str(state_t);
167 static const char *action2str(action_t);
177 const security_driver_t *secdrv;
179 char *pgm = "amandad"; /* in case argv[0] is not set */
180 #if defined(USE_REUSEADDR)
186 * Configure program for internationalization:
187 * 1) Only set the message locale for now.
188 * 2) Set textdomain for all amanda related programs to "amanda"
189 * We don't want to be forced to support dozens of message catalogs.
191 setlocale(LC_MESSAGES, "C");
192 textdomain("amanda");
198 * When called via inetd, it is not uncommon to forget to put the
199 * argv[0] value on the config line. On some systems (e.g. Solaris)
200 * this causes argv and/or argv[0] to be NULL, so we have to be
201 * careful getting our name.
203 if ((argv == NULL) || (argv[0] == NULL)) {
204 pgm = "amandad"; /* in case argv[0] is not set */
206 pgm = basename(argv[0]); /* Strip of leading path get debug name */
209 dbopen(DBG_SUBDIR_AMANDAD);
212 error(_("argv == NULL\n"));
216 /* Don't die when child closes pipe */
217 signal(SIGPIPE, SIG_IGN);
219 config_init(CONFIG_INIT_CLIENT, NULL);
221 check_running_as(RUNNING_AS_CLIENT_LOGIN);
223 erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG);
226 * ad-hoc argument parsing
228 * We accept -auth=[authentication type]
232 * We also add a list of services that amandad can launch
235 in = 0; out = 1; /* default to stdin/stdout */
237 for (i = 1; i < argc; i++) {
239 * accept -krb4 as an alias for -auth=krb4 (for compatibility)
241 if (strcmp(argv[i], "-krb4") == 0) {
242 argv[i] = "-auth=krb4";
248 * Get a driver for a security type specified after -auth=
250 else if (strncmp(argv[i], "-auth=", strlen("-auth=")) == 0) {
251 argv[i] += strlen("-auth=");
252 secdrv = security_getdriver(argv[i]);
254 if (secdrv == NULL) {
255 error(_("no driver for security type '%s'\n"), argv[i]);
262 * If -no-exit is specified, always run even after requests have
265 else if (strcmp(argv[i], "-no-exit") == 0) {
271 * Allow us to directly bind to a udp port for debugging.
272 * This may only apply to some security types.
274 else if (strncmp(argv[i], "-udp=", strlen("-udp=")) == 0) {
276 struct sockaddr_in6 sin;
278 struct sockaddr_in sin;
281 argv[i] += strlen("-udp=");
283 in = out = socket(AF_INET6, SOCK_DGRAM, 0);
285 in = out = socket(AF_INET, SOCK_DGRAM, 0);
288 error(_("can't create dgram socket: %s\n"), strerror(errno));
292 r = setsockopt(in, SOL_SOCKET, SO_REUSEADDR,
293 (void *)&on, (socklen_t)sizeof(on));
295 dbprintf(_("amandad: setsockopt(SO_REUSEADDR) failed: %s\n"),
301 sin.sin6_family = (sa_family_t)AF_INET6;
302 sin.sin6_addr = in6addr_any;
303 sin.sin6_port = (in_port_t)htons((in_port_t)atoi(argv[i]));
305 sin.sin_family = (sa_family_t)AF_INET;
306 sin.sin_addr.s_addr = INADDR_ANY;
307 sin.sin_port = (in_port_t)htons((in_port_t)atoi(argv[i]));
309 if (bind(in, (struct sockaddr *)&sin, (socklen_t)sizeof(sin)) < 0) {
310 error(_("can't bind to port %d: %s\n"), atoi(argv[i]),
316 * Ditto for tcp ports.
318 else if (strncmp(argv[i], "-tcp=", strlen("-tcp=")) == 0) {
320 struct sockaddr_in6 sin;
322 struct sockaddr_in sin;
327 argv[i] += strlen("-tcp=");
329 sock = socket(AF_INET6, SOCK_STREAM, 0);
331 sock = socket(AF_INET, SOCK_STREAM, 0);
334 error(_("can't create tcp socket: %s\n"), strerror(errno));
338 r = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
339 (void *)&on, (socklen_t)sizeof(on));
341 dbprintf(_("amandad: setsockopt(SO_REUSEADDR) failed: %s\n"),
346 sin.sin6_family = (sa_family_t)AF_INET6;
347 sin.sin6_addr = in6addr_any;
348 sin.sin6_port = (in_port_t)htons((in_port_t)atoi(argv[i]));
350 sin.sin_family = (sa_family_t)AF_INET;
351 sin.sin_addr.s_addr = INADDR_ANY;
352 sin.sin_port = (in_port_t)htons((in_port_t)atoi(argv[i]));
354 if (bind(sock, (struct sockaddr *)&sin, (socklen_t)sizeof(sin)) < 0) {
355 error(_("can't bind to port %d: %s\n"), atoi(argv[i]),
360 n = (socklen_t)sizeof(sin);
361 in = out = accept(sock, (struct sockaddr *)&sin, &n);
364 * It must be a service name
367 /* clear all services */
369 for (j = 0; j < (int)NSERVICES; j++)
370 services[j].active = 0;
374 if(strcmp(argv[i],"amdump") == 0) {
375 services[0].active = 1;
376 services[1].active = 1;
377 services[2].active = 1;
378 services[3].active = 1;
381 for (j = 0; j < (int)NSERVICES; j++)
382 if (strcmp(services[j].name, argv[i]) == 0)
384 if (j == (int)NSERVICES) {
385 dbprintf(_("%s: invalid service\n"), argv[i]);
388 services[j].active = 1;
394 * If no security type specified, use BSD
396 if (secdrv == NULL) {
397 secdrv = security_getdriver("BSD");
399 if (secdrv == NULL) {
400 error(_("no driver for default security type 'BSD'\n"));
405 if(strcasecmp(auth, "rsh") == 0 ||
406 strcasecmp(auth, "ssh") == 0 ||
407 strcasecmp(auth, "bsdtcp") == 0) {
416 dbprintf(_("version %s\n"), version());
417 for (i = 0; version_info[i] != NULL; i++) {
418 dbprintf(" %s", version_info[i]);
421 if (! (argc >= 1 && argv != NULL && argv[0] != NULL)) {
422 dbprintf(_("WARNING: argv[0] not defined: check inetd.conf\n"));
426 * Schedule to call protocol_accept() when new security handles
427 * are created on stdin.
429 security_accept(secdrv, amandad_get_security_conf, in, out, protocol_accept, NULL);
432 * Schedule an event that will try to exit every 30 seconds if there
433 * are no requests outstanding.
436 (void)event_register((event_id_t)30, EV_TIME, exit_check, &no_exit);
439 * Call event_loop() with an arg of 0, telling it to block until all
440 * events are completed.
451 * This runs periodically and checks to see if we have any active services
452 * still running. If we don't, then we quit.
460 assert(cookie != NULL);
461 no_exit = *(int *)cookie;
464 * If things are still running, then don't exit.
466 if (serviceq.qlength > 0)
470 * If the caller asked us to never exit, then we're done
480 * Handles new incoming protocol handles. This is a callback for
481 * security_accept(), which gets called when new handles are detected.
485 security_handle_t * handle,
489 struct active_service *as;
490 char *pktbody, *tok, *service, *arguments;
491 char *service_path = NULL;
497 * If handle is NULL, then the connection is closed.
504 * If pkt is NULL, then there was a problem with the new connection.
507 dbprintf(_("accept error: %s\n"), security_geterror(handle));
508 pkt_init(&pkt_out, P_NAK, "ERROR %s\n", security_geterror(handle));
509 do_sendpkt(handle, &pkt_out);
510 amfree(pkt_out.body);
511 security_close(handle);
515 dbprintf(_("accept recv %s pkt:\n<<<<<\n%s>>>>>\n"),
516 pkt_type2str(pkt->type), pkt->body);
519 * If this is not a REQ packet, just forget about it.
521 if (pkt->type != P_REQ) {
522 dbprintf(_("received unexpected %s packet:\n<<<<<\n%s>>>>>\n\n"),
523 pkt_type2str(pkt->type), pkt->body);
524 security_close(handle);
528 pktbody = service = arguments = NULL;
532 * Parse out the service and arguments
535 pktbody = stralloc(pkt->body);
537 tok = strtok(pktbody, " ");
540 if (strcmp(tok, "SERVICE") != 0)
543 tok = strtok(NULL, " \n");
546 service = stralloc(tok);
548 /* we call everything else 'arguments' */
549 tok = strtok(NULL, "");
552 arguments = stralloc(tok);
554 /* see if it's one we allow */
555 for (i = 0; i < (int)NSERVICES; i++)
556 if (services[i].active == 1 && strcmp(services[i].name, service) == 0)
558 if (i == (int)NSERVICES) {
559 dbprintf(_("%s: invalid service\n"), service);
560 pkt_init(&pkt_out, P_NAK, _("ERROR %s: invalid service, add '%s' as argument to amandad\n"), service, service);
564 service_path = vstralloc(amlibexecdir, "/", service, versionsuffix(), NULL);
565 if (access(service_path, X_OK) < 0) {
566 dbprintf(_("can't execute %s: %s\n"), service_path, strerror(errno));
567 pkt_init(&pkt_out, P_NAK,
568 _("ERROR execute access to \"%s\" denied\n"),
573 /* see if its already running */
574 for (as = TAILQ_FIRST(&serviceq.tailq); as != NULL;
575 as = TAILQ_NEXT(as, tq)) {
576 if (strcmp(as->cmd, service_path) == 0 &&
577 strcmp(as->arguments, arguments) == 0) {
578 dbprintf(_("%s %s: already running, acking req\n"),
580 pkt_init_empty(&pkt_out, P_ACK);
581 goto send_pkt_out_no_delete;
586 * create a new service instance, and send the arguments down
589 dbprintf(_("creating new service: %s\n%s\n"), service, arguments);
590 as = service_new(handle, service_path, arguments);
591 if (writebuf(as, arguments, strlen(arguments)) < 0) {
592 const char *errmsg = strerror(errno);
593 dbprintf(_("error sending arguments to %s: %s\n"), service, errmsg);
594 pkt_init(&pkt_out, P_NAK, _("ERROR error writing arguments to %s: %s\n"),
602 amfree(service_path);
606 * Move to the sendack state, and start up the state
609 as->state = s_sendack;
610 state_machine(as, A_START, NULL);
614 pkt_init(&pkt_out, P_NAK, _("ERROR invalid REQ\n"));
615 dbprintf(_("received invalid %s packet:\n<<<<<\n%s>>>>>\n\n"),
616 pkt_type2str(pkt->type), pkt->body);
621 send_pkt_out_no_delete:
623 amfree(service_path);
626 do_sendpkt(handle, &pkt_out);
627 security_close(handle);
628 amfree(pkt_out.body);
632 * Handles incoming protocol packets. Routes responses to the proper
637 struct active_service * as,
645 amandad_debug(1, _("state_machine: %p entering\n"), as);
647 curstate = as->state;
648 amandad_debug(1, _("state_machine: %p curstate=%s action=%s\n"), as,
649 state2str(curstate), action2str(action));
650 retaction = (*curstate)(as, action, pkt);
651 amandad_debug(1, _("state_machine: %p curstate=%s returned %s (nextstate=%s)\n"),
652 as, state2str(curstate), action2str(retaction),
653 state2str(as->state));
657 * State has queued up and is now blocking on input.
660 amandad_debug(1, _("state_machine: %p leaving (A_PENDING)\n"), as);
664 * service has switched states. Loop.
670 * state has determined that the packet it received was bogus.
671 * Send a nak, and return.
674 dbprintf(_("received unexpected %s packet\n"),
675 pkt_type2str(pkt->type));
676 dbprintf(_("<<<<<\n%s----\n\n"), pkt->body);
677 pkt_init(&nak, P_NAK, _("ERROR unexpected packet type %s\n"),
678 pkt_type2str(pkt->type));
679 do_sendpkt(as->security_handle, &nak);
681 security_recvpkt(as->security_handle, protocol_recv, as, -1);
682 amandad_debug(1, _("state_machine: %p leaving (A_SENDNAK)\n"), as);
686 * Service is done. Remove it and finish.
689 amandad_debug(1, _("state_machine: %p leaving (A_FINISH)\n"), as);
702 * This state just sends an ack. After that, we move to the repwait
703 * state to wait for REP data to arrive from the subprocess.
707 struct active_service * as,
713 (void)action; /* Quiet unused parameter warning */
714 (void)pkt; /* Quiet unused parameter warning */
716 pkt_init_empty(&ack, P_ACK);
717 if (do_sendpkt(as->security_handle, &ack) < 0) {
718 dbprintf(_("error sending ACK: %s\n"),
719 security_geterror(as->security_handle));
726 * move to the repwait state
727 * Setup a listener for data on the reply fd, but also
728 * listen for packets over the wire, as the server may
729 * poll us if we take a long time.
730 * Setup a timeout that will fire if it takes too long to
733 as->state = s_repwait;
734 as->ev_repfd = event_register((event_id_t)as->repfd, EV_READFD, repfd_recv, as);
735 as->ev_reptimeout = event_register(REP_TIMEOUT, EV_TIME,
737 security_recvpkt(as->security_handle, protocol_recv, as, -1);
742 * This is the repwait state. We have responded to the initial REQ with
743 * an ACK, and we are now waiting for the process we spawned to pass us
744 * data to send in a REP.
748 struct active_service * as,
762 * We normally shouldn't receive any packets while waiting
763 * for our REP data, but in some cases we do.
765 if (action == A_RECVPKT) {
768 * Another req for something that's running. Just send an ACK
769 * and go back and wait for more data.
771 if (pkt->type == P_REQ) {
772 dbprintf(_("received dup P_REQ packet, ACKing it\n"));
773 amfree(as->rep_pkt.body);
774 pkt_init_empty(&as->rep_pkt, P_ACK);
775 do_sendpkt(as->security_handle, &as->rep_pkt);
776 security_recvpkt(as->security_handle, protocol_recv, as, -1);
779 /* something unexpected. Nak it */
783 if (action == A_TIMEOUT) {
784 amfree(as->rep_pkt.body);
785 pkt_init(&as->rep_pkt, P_NAK, _("ERROR timeout on reply pipe\n"));
786 dbprintf(_("%s timed out waiting for REP data\n"), as->cmd);
787 do_sendpkt(as->security_handle, &as->rep_pkt);
791 assert(action == A_RECVREP);
792 if(as->bufsize == 0) {
793 as->bufsize = NETWORK_BLOCK_BYTES;
794 as->repbuf = alloc(as->bufsize);
798 n = read(as->repfd, as->repbuf + as->repbufsize,
799 as->bufsize - as->repbufsize - 1);
800 } while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
802 const char *errstr = strerror(errno);
803 dbprintf(_("read error on reply pipe: %s\n"), errstr);
804 amfree(as->rep_pkt.body);
805 pkt_init(&as->rep_pkt, P_NAK, _("ERROR read error on reply pipe: %s\n"),
807 do_sendpkt(as->security_handle, &as->rep_pkt);
811 /* If end of service, wait for process status */
814 pid = waitpid(as->pid, &retstat, WNOHANG);
815 while (t<5 && pid == 0) {
818 pid = waitpid(as->pid, &retstat, WNOHANG);
823 if (! WIFEXITED(retstat)) {
825 code = WTERMSIG(retstat);
826 } else if (WEXITSTATUS(retstat) != 0) {
828 code = WEXITSTATUS(retstat);
831 dbprintf(_("service %s failed: pid %u exited with %s %d\n"),
832 (as->cmd)?as->cmd:_("??UNKONWN??"),
836 _("ERROR service %s failed: pid %u exited with %s %d\n"),
837 (as->cmd)?as->cmd:_("??UNKONWN??"), (unsigned)as->pid,
839 if (as->repbufsize + strlen(msg) >= (as->bufsize - 1)) {
841 repbuf_temp = alloc(as->bufsize);
842 memcpy(repbuf_temp, as->repbuf, as->repbufsize + 1);
844 as->repbuf = repbuf_temp;
846 strcpy(as->repbuf + as->repbufsize, msg);
847 as->repbufsize += strlen(msg);
853 * If we got some data, go back and wait for more, or EOF. Nul terminate
856 as->repbuf[n + as->repbufsize] = '\0';
859 if(as->repbufsize >= (as->bufsize - 1)) {
861 repbuf_temp = alloc(as->bufsize);
862 memcpy(repbuf_temp, as->repbuf, as->repbufsize + 1);
864 as->repbuf = repbuf_temp;
866 else if(as->send_partial_reply) {
867 amfree(as->rep_pkt.body);
868 pkt_init(&as->rep_pkt, P_PREP, "%s", as->repbuf);
869 do_sendpkt(as->security_handle, &as->rep_pkt);
870 amfree(as->rep_pkt.body);
871 pkt_init_empty(&as->rep_pkt, P_REP);
878 * If we got 0, then we hit EOF. Process the data and release
883 assert(as->ev_repfd != NULL);
884 event_release(as->ev_repfd);
887 assert(as->ev_reptimeout != NULL);
888 event_release(as->ev_reptimeout);
889 as->ev_reptimeout = NULL;
891 as->state = s_processrep;
897 * After we have read in all of the rep data, we process it and send
898 * it out as a REP packet.
902 struct active_service * as,
908 (void)action; /* Quiet unused parameter warning */
909 (void)pkt; /* Quiet unused parameter warning */
912 * Copy the rep lines into the outgoing packet.
914 * If this line is a CONNECT, translate it
915 * Format is "CONNECT <tag> <handle> <tag> <handle> etc...
918 * CONNECT DATA 4 MESG 5 INDEX 6
920 * The tags are arbitrary. The handles are in the DATA_FD pool.
921 * We need to map these to security streams and pass them back
922 * to the amanda server. If the handle is -1, then we don't map.
924 if (strncmp_const(as->repbuf,"KENCRYPT\n") == 0) {
925 amandad_kencrypt = KENCRYPT_WILL_DO;
926 repbuf = stralloc(as->repbuf + 9);
928 repbuf = stralloc(as->repbuf);
930 amfree(as->rep_pkt.body);
931 pkt_init_empty(&as->rep_pkt, P_REP);
932 tok = strtok(repbuf, " ");
935 if (strcmp(tok, "CONNECT") == 0) {
936 char *line, *nextbuf;
938 /* Save the entire line */
939 line = strtok(NULL, "\n");
940 /* Save the buf following the line */
941 nextbuf = strtok(NULL, "");
943 if (line == NULL || nextbuf == NULL)
946 pkt_cat(&as->rep_pkt, "CONNECT");
948 /* loop over the id/handle pairs */
951 tok = strtok(line, " ");
952 line = NULL; /* keep working from line */
955 pkt_cat(&as->rep_pkt, " %s", tok);
958 tok = strtok(NULL, " \n");
961 /* convert the handle into something the server can process */
962 pkt_cat(&as->rep_pkt, " %d", allocstream(as, atoi(tok)));
964 pkt_cat(&as->rep_pkt, "\n%s", nextbuf);
967 pkt_cat(&as->rep_pkt, "%s", as->repbuf);
971 * We've setup our REP packet in as->rep_pkt. Now move to the transmission
974 as->state = s_sendrep;
975 as->repretry = getconf_int(CNF_REP_TRIES);
981 * This is the state where we send the REP we just collected from our child.
985 struct active_service * as,
989 (void)action; /* Quiet unused parameter warning */
990 (void)pkt; /* Quiet unused parameter warning */
993 * Transmit it and move to the ack state.
995 do_sendpkt(as->security_handle, &as->rep_pkt);
996 security_recvpkt(as->security_handle, protocol_recv, as, ACK_TIMEOUT);
997 as->state = s_ackwait;
1002 * This is the state in which we wait for the server to ACK the REP
1007 struct active_service * as,
1011 struct datafd_handle *dh;
1015 * If we got a timeout, try again, but eventually give up.
1017 if (action == A_TIMEOUT) {
1018 if (--as->repretry > 0) {
1019 as->state = s_sendrep;
1020 return (A_CONTINUE);
1022 dbprintf(_("timeout waiting for ACK for our REP\n"));
1025 amandad_debug(1, _("received ACK, now opening streams\n"));
1027 assert(action == A_RECVPKT);
1029 if (pkt->type == P_REQ) {
1030 dbprintf(_("received dup P_REQ packet, resending REP\n"));
1031 as->state = s_sendrep;
1032 return (A_CONTINUE);
1035 if (pkt->type != P_ACK)
1038 if (amandad_kencrypt == KENCRYPT_WILL_DO) {
1039 amandad_kencrypt = KENCRYPT_YES;
1043 * Got the ack, now open the pipes
1045 for (dh = &as->data[0]; dh < &as->data[DATA_FD_COUNT]; dh++) {
1046 if (dh->netfd == NULL)
1048 if (security_stream_accept(dh->netfd) < 0) {
1049 dbprintf(_("stream %td accept failed: %s\n"),
1050 dh - &as->data[0], security_geterror(as->security_handle));
1051 security_stream_close(dh->netfd);
1055 /* setup an event for reads from it */
1056 dh->ev_read = event_register((event_id_t)dh->fd_read, EV_READFD,
1057 process_readnetfd, dh);
1059 security_stream_read(dh->netfd, process_writenetfd, dh);
1064 * Pipes are open, so auth them. Count them at the same time.
1066 for (npipes = 0, dh = &as->data[0]; dh < &as->data[DATA_FD_COUNT]; dh++) {
1067 if (dh->netfd == NULL)
1069 if (security_stream_auth(dh->netfd) < 0) {
1070 security_stream_close(dh->netfd);
1072 event_release(dh->ev_read);
1073 event_release(dh->ev_write);
1075 dh->ev_write = NULL;
1082 * If no pipes are open, then we're done. Otherwise, just start running.
1083 * The event handlers on all of the pipes will take it from here.
1085 amandad_debug(1, _("at end of s_ackwait, npipes is %d\n"), npipes);
1089 security_close(as->security_handle);
1090 as->security_handle = NULL;
1096 * Called when a repfd has received data
1102 struct active_service *as = cookie;
1105 assert(as->ev_repfd != NULL);
1107 state_machine(as, A_RECVREP, NULL);
1111 * Called when a repfd has timed out
1117 struct active_service *as = cookie;
1120 assert(as->ev_reptimeout != NULL);
1122 state_machine(as, A_TIMEOUT, NULL);
1126 * Called when a handle has received data
1132 security_status_t status)
1134 struct active_service *as = cookie;
1140 dbprintf(_("received %s pkt:\n<<<<<\n%s>>>>>\n"),
1141 pkt_type2str(pkt->type), pkt->body);
1142 state_machine(as, A_RECVPKT, pkt);
1145 dbprintf(_("timeout\n"));
1146 state_machine(as, A_TIMEOUT, NULL);
1149 dbprintf(_("receive error: %s\n"),
1150 security_geterror(as->security_handle));
1156 * This is a generic relay function that just reads data from one of
1157 * the process's pipes and passes it up the equivalent security_stream_t
1164 struct datafd_handle *dh = cookie;
1165 struct active_service *as = dh->as;
1171 n = read(dh->fd_read, as->databuf, SIZEOF(as->databuf));
1172 } while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
1178 pkt_init(&nak, P_NAK, _("A ERROR data descriptor %d broken: %s\n"),
1179 dh->fd_read, strerror(errno));
1183 * Process has closed the pipe. Just remove this event handler.
1184 * If all pipes are closed, shut down this service.
1187 event_release(dh->ev_read);
1189 if(dh->ev_write == NULL) {
1190 security_stream_close(dh->netfd);
1193 for (dh = &as->data[0]; dh < &as->data[DATA_FD_COUNT]; dh++) {
1194 if (dh->netfd != NULL)
1200 if (security_stream_write(dh->netfd, as->databuf, (size_t)n) < 0) {
1201 /* stream has croaked */
1202 pkt_init(&nak, P_NAK, _("ERROR write error on stream %d: %s\n"),
1203 security_stream_id(dh->netfd),
1204 security_stream_geterror(dh->netfd));
1210 do_sendpkt(as->security_handle, &nak);
1216 * This is a generic relay function that just read data from one of
1217 * the security_stream_t and passes it up the equivalent process's pipes
1225 struct datafd_handle *dh;
1227 assert(cookie != NULL);
1230 if (dh->fd_write <= 0) {
1231 dbprintf(_("process_writenetfd: dh->fd_write <= 0\n"));
1232 } else if (size > 0) {
1233 fullwrite(dh->fd_write, buf, (size_t)size);
1234 security_stream_read(dh->netfd, process_writenetfd, dh);
1237 aclose(dh->fd_write);
1243 * Convert a local stream handle (DATA_FD...) into something that
1244 * can be sent to the amanda server.
1246 * Returns a number that should be sent to the server in the REP packet.
1250 struct active_service * as,
1253 struct datafd_handle *dh;
1255 /* if the handle is -1, then we don't bother */
1259 /* make sure the handle's kosher */
1260 if (handle < DATA_FD_OFFSET || handle >= DATA_FD_OFFSET + DATA_FD_COUNT)
1263 /* get a pointer into our handle array */
1264 dh = &as->data[handle - DATA_FD_OFFSET];
1266 /* make sure we're not already using the net handle */
1267 if (dh->netfd != NULL)
1270 /* allocate a stream from the security layer and return */
1271 dh->netfd = security_stream_server(as->security_handle);
1272 if (dh->netfd == NULL) {
1273 dbprintf(_("couldn't open stream to server: %s\n"),
1274 security_geterror(as->security_handle));
1279 * convert the stream into a numeric id that can be sent to the
1282 return (security_stream_id(dh->netfd));
1286 * Create a new service instance
1288 static struct active_service *
1290 security_handle_t * security_handle,
1292 const char * arguments)
1295 int data_read[DATA_FD_COUNT + 1][2];
1296 int data_write[DATA_FD_COUNT + 1][2];
1297 struct active_service *as;
1301 assert(security_handle != NULL);
1302 assert(cmd != NULL);
1303 assert(arguments != NULL);
1305 /* a plethora of pipes */
1306 for (i = 0; i < DATA_FD_COUNT + 1; i++) {
1307 if (pipe(data_read[i]) < 0) {
1308 error(_("pipe: %s\n"), strerror(errno));
1311 if (pipe(data_write[i]) < 0) {
1312 error(_("pipe: %s\n"), strerror(errno));
1317 switch(pid = fork()) {
1319 error(_("could not fork service %s: %s\n"), cmd, strerror(errno));
1323 * The parent. Close the far ends of our pipes and return.
1325 as = alloc(SIZEOF(*as));
1326 as->cmd = stralloc(cmd);
1327 as->arguments = stralloc(arguments);
1328 as->security_handle = security_handle;
1331 as->send_partial_reply = 0;
1332 if(strcmp(cmd+(strlen(cmd)-8), "sendsize") == 0) {
1333 g_option_t *g_options;
1334 char *option_str, *p;
1336 option_str = stralloc(as->arguments+8);
1337 p = strchr(option_str,'\n');
1340 g_options = parse_g_options(option_str, 1);
1341 if(am_has_feature(g_options->features, fe_partial_estimate)) {
1342 as->send_partial_reply = 1;
1344 free_g_options(g_options);
1348 /* write to the request pipe */
1349 aclose(data_read[0][0]);
1350 as->reqfd = data_read[0][1];
1353 * read from the reply pipe
1355 as->repfd = data_write[0][0];
1356 aclose(data_write[0][1]);
1357 as->ev_repfd = NULL;
1362 as->rep_pkt.body = NULL;
1365 * read from the rest of the general-use pipes
1366 * (netfds are opened as the client requests them)
1368 for (i = 0; i < DATA_FD_COUNT; i++) {
1369 aclose(data_read[i + 1][1]);
1370 aclose(data_write[i + 1][0]);
1371 as->data[i].fd_read = data_read[i + 1][0];
1372 as->data[i].fd_write = data_write[i + 1][1];
1373 as->data[i].ev_read = NULL;
1374 as->data[i].ev_write = NULL;
1375 as->data[i].netfd = NULL;
1376 as->data[i].as = as;
1379 /* add it to the service queue */
1380 /* increment the active service count */
1381 TAILQ_INSERT_TAIL(&serviceq.tailq, as, tq);
1387 * The child. Put our pipes in their advertised locations
1392 * The data stream is stdin in the new process
1394 if (dup2(data_read[0][0], 0) < 0) {
1395 error(_("dup %d to %d failed: %s\n"), data_read[0][0], 0,
1399 aclose(data_read[0][0]);
1400 aclose(data_read[0][1]);
1403 * The reply stream is stdout
1405 if (dup2(data_write[0][1], 1) < 0) {
1406 error(_("dup %d to %d failed: %s\n"), data_write[0][1], 1,
1409 aclose(data_write[0][0]);
1410 aclose(data_write[0][1]);
1412 for (i = 0; i < DATA_FD_COUNT; i++) {
1413 aclose(data_read[i + 1][0]);
1414 aclose(data_write[i + 1][1]);
1418 * Make sure they are not open in the range DATA_FD_OFFSET to
1419 * DATA_FD_OFFSET + DATA_FD_COUNT*2 - 1
1421 for (i = 0; i < DATA_FD_COUNT; i++) {
1422 while(data_read[i + 1][1] >= DATA_FD_OFFSET &&
1423 data_read[i + 1][1] <= DATA_FD_OFFSET + DATA_FD_COUNT*2 - 1) {
1424 newfd = dup(data_read[i + 1][1]);
1426 error(_("Can't dup out off DATA_FD range"));
1427 data_read[i + 1][1] = newfd;
1429 while(data_write[i + 1][0] >= DATA_FD_OFFSET &&
1430 data_write[i + 1][0] <= DATA_FD_OFFSET + DATA_FD_COUNT*2 - 1) {
1431 newfd = dup(data_write[i + 1][0]);
1433 error(_("Can't dup out off DATA_FD range"));
1434 data_write[i + 1][0] = newfd;
1437 for (i = 0; i < DATA_FD_COUNT*2; i++)
1438 close(DATA_FD_OFFSET + i);
1441 * The rest start at the offset defined in amandad.h, and continue
1442 * through the internal defined.
1444 for (i = 0; i < DATA_FD_COUNT; i++) {
1445 if (dup2(data_read[i + 1][1], i*2 + DATA_FD_OFFSET) < 0) {
1446 error(_("dup %d to %d failed: %s\n"), data_read[i + 1][1],
1447 i + DATA_FD_OFFSET, strerror(errno));
1449 aclose(data_read[i + 1][1]);
1451 if (dup2(data_write[i + 1][0], i*2 + 1 + DATA_FD_OFFSET) < 0) {
1452 error(_("dup %d to %d failed: %s\n"), data_write[i + 1][0],
1453 i + DATA_FD_OFFSET, strerror(errno));
1455 aclose(data_write[i + 1][0]);
1458 /* close all unneeded fd */
1459 close(STDERR_FILENO);
1460 debug_dup_stderr_to_debug();
1461 safe_fd(DATA_FD_OFFSET, DATA_FD_COUNT*2);
1463 execle(cmd, cmd, "amandad", auth, (char *)NULL, safe_env());
1464 error(_("could not exec service %s: %s\n"), cmd, strerror(errno));
1471 * Unallocate a service instance
1475 struct active_service * as)
1478 struct datafd_handle *dh;
1480 amandad_debug(1, _("closing service: %s\n"),
1481 (as->cmd)?as->cmd:_("??UNKONWN??"));
1485 assert(as->cmd != NULL);
1488 assert(as->arguments != NULL);
1489 amfree(as->arguments);
1491 if (as->reqfd != -1)
1493 if (as->repfd != -1)
1496 if (as->ev_repfd != NULL)
1497 event_release(as->ev_repfd);
1498 if (as->ev_reptimeout != NULL)
1499 event_release(as->ev_reptimeout);
1501 for (i = 0; i < DATA_FD_COUNT; i++) {
1504 aclose(dh->fd_read);
1505 aclose(dh->fd_write);
1507 if (dh->netfd != NULL)
1508 security_stream_close(dh->netfd);
1510 if (dh->ev_read != NULL)
1511 event_release(dh->ev_read);
1512 if (dh->ev_write != NULL)
1513 event_release(dh->ev_write);
1516 if (as->security_handle != NULL)
1517 security_close(as->security_handle);
1519 assert(as->pid > 0);
1520 kill(as->pid, SIGTERM);
1521 waitpid(as->pid, NULL, WNOHANG);
1523 TAILQ_REMOVE(&serviceq.tailq, as, tq);
1524 assert(serviceq.qlength > 0);
1528 amfree(as->arguments);
1530 amfree(as->rep_pkt.body);
1533 if(exit_on_qlength == 0 && serviceq.qlength == 0) {
1540 * Like 'fullwrite', but does the work in a child process so pipelines
1545 struct active_service * as,
1552 switch (pid=fork()) {
1557 waitpid(pid, NULL, WNOHANG);
1558 return 0; /* this is the parent */
1560 case 0: /* this is the child */
1562 writesize = fullwrite(as->reqfd, bufp, size);
1563 exit(writesize != (ssize_t)size);
1571 security_handle_t * handle,
1574 dbprintf(_("sending %s pkt:\n<<<<<\n%s>>>>>\n"),
1575 pkt_type2str(pkt->type), pkt->body);
1577 return security_sendpkt(handle, pkt);
1583 * Convert a state into a string
1589 static const struct {
1593 #define X(state) { state, stringize(state) }
1603 for (i = 0; i < (int)(sizeof(states) / sizeof(states[0])); i++)
1604 if (state == states[i].state)
1605 return (states[i].str);
1606 return (_("INVALID STATE"));
1610 * Convert an action into a string
1616 static const struct {
1620 #define X(action) { action, stringize(action) }
1633 for (i = 0; i < (int)(sizeof(actions) / sizeof(actions[0])); i++)
1634 if (action == actions[i].action)
1635 return (actions[i].str);
1636 return (_("UNKNOWN ACTION"));
1640 amandad_get_security_conf(
1644 (void)arg; /* Quiet unused parameter warning */
1646 if (!string || !*string)
1649 if (strcmp(string, "kencrypt")==0) {
1650 if (amandad_kencrypt == KENCRYPT_YES)