24 static void signal_handler(int sig) {
26 error("segmentation fault");
29 } else if (sig != SIGCHLD) {
30 fatal("unhandled signal %d", sig);
34 static void setup_slave_sigs(void) {
36 memset(&sa, 0, sizeof(sa));
37 sigemptyset(&sa.sa_mask);
38 sa.sa_handler = signal_handler;
40 sigaction(SIGCHLD, &sa, NULL);
41 sigaction(SIGSEGV, &sa, NULL);
43 signal(SIGINT, SIG_DFL);
44 signal(SIGTERM, SIG_DFL);
45 signal(SIGPIPE, SIG_IGN);
51 static void setup_client(int client, struct sockaddr *addr) {
52 struct sctp_event_subscribe events;
53 memset(&events, 0, sizeof(events));
54 events.sctp_data_io_event = 1;
55 events.sctp_address_event = 1;
56 events.sctp_send_failure_event = 1;
57 events.sctp_peer_error_event = 1;
58 events.sctp_partial_delivery_event = 1;
59 events.sctp_adaptation_layer_event = 1;
61 if (setsockopt(client, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events)))
62 fatalpe("setsockopt(SCTP_EVENTS)");
65 static void handle_auth_message(struct strbuf *in, struct strbuf *out) {
66 gss_buffer_desc incoming_tok, outgoing_tok;
67 OM_uint32 maj_stat, min_stat;
69 incoming_tok.value = in->buf;
70 incoming_tok.length = in->len;
72 process_server_token(&incoming_tok, &outgoing_tok);
74 strbuf_add(out, outgoing_tok.value, outgoing_tok.length);
76 if (outgoing_tok.length) {
77 maj_stat = gss_release_buffer(&min_stat, &outgoing_tok);
78 if (maj_stat != GSS_S_COMPLETE)
79 gss_fatal("gss_release_buffer", maj_stat, min_stat);
83 static void handle_op_message(uint32_t in_type, struct strbuf *in, struct strbuf *out) {
84 struct op *op = get_local_op(in_type);
87 debug("running op: %s", op->name);
90 fatal("operation %x does not exist", in_type);
93 if (!client_username())
94 fatal("unathenticated");
96 make_env(envp, "LANG", "C", "CEO_USER", client_username(),
97 "CEO_CONFIG_DIR", config_dir, NULL);
98 char *argv[] = { op->path, NULL, };
100 if (spawnvemu(op->path, argv, envp, in, out, 0, op->user))
101 fatal("child %s failed", op->path);
104 fatal("no response from op");
109 static void handle_one_message(int sock, struct sctp_meta *in_meta, struct strbuf *in) {
110 struct strbuf out = STRBUF_INIT;
111 uint32_t ppid = in_meta->sinfo.sinfo_ppid;
113 if (ppid == MSG_AUTH)
114 handle_auth_message(in, &out);
116 handle_op_message(ppid, in, &out);
118 if (out.len && sctp_sendmsg(sock, out.buf, out.len,
119 (sa *)&in_meta->from, in_meta->fromlen, ppid,
121 fatalpe("sctp_sendmsg");
123 strbuf_release(&out);
126 void slave_main(int sock, struct sockaddr *addr) {
127 char addrstr[INET_ADDRSTRLEN];
128 struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
129 struct sctp_meta msg_meta;
130 struct strbuf msg = STRBUF_INIT;
132 if (addr->sa_family != AF_INET)
133 fatal("unsupported address family %d", addr->sa_family);
135 if (!inet_ntop(AF_INET, &addr_in->sin_addr, addrstr, sizeof(addrstr)))
136 fatalpe("inet_ntop");
138 notice("accepted connection from %s", addrstr);
141 setup_client(sock, addr);
144 if (!receive_one_message(sock, &msg_meta, &msg))
146 handle_one_message(sock, &msg_meta, &msg);
149 notice("connection closed by peer %s", addrstr);
151 strbuf_release(&msg);
153 /* stuff allocated by dmaster */