1*58e6ee5fSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0
2*58e6ee5fSAndroid Build Coastguard Worker /*
3*58e6ee5fSAndroid Build Coastguard Worker * Copyright (C) 2018 VMware Inc, Slavomir Kaslev <[email protected]>
4*58e6ee5fSAndroid Build Coastguard Worker *
5*58e6ee5fSAndroid Build Coastguard Worker * based on prior implementation by Yoshihiro Yunomae
6*58e6ee5fSAndroid Build Coastguard Worker * Copyright (C) 2013 Hitachi, Ltd.
7*58e6ee5fSAndroid Build Coastguard Worker * Yoshihiro YUNOMAE <[email protected]>
8*58e6ee5fSAndroid Build Coastguard Worker */
9*58e6ee5fSAndroid Build Coastguard Worker
10*58e6ee5fSAndroid Build Coastguard Worker #include <errno.h>
11*58e6ee5fSAndroid Build Coastguard Worker #include <fcntl.h>
12*58e6ee5fSAndroid Build Coastguard Worker #include <getopt.h>
13*58e6ee5fSAndroid Build Coastguard Worker #include <signal.h>
14*58e6ee5fSAndroid Build Coastguard Worker #include <stdbool.h>
15*58e6ee5fSAndroid Build Coastguard Worker #include <stdio.h>
16*58e6ee5fSAndroid Build Coastguard Worker #include <stdlib.h>
17*58e6ee5fSAndroid Build Coastguard Worker #include <sys/socket.h>
18*58e6ee5fSAndroid Build Coastguard Worker #include <sys/wait.h>
19*58e6ee5fSAndroid Build Coastguard Worker #include <unistd.h>
20*58e6ee5fSAndroid Build Coastguard Worker #include <pthread.h>
21*58e6ee5fSAndroid Build Coastguard Worker
22*58e6ee5fSAndroid Build Coastguard Worker #include "trace-local.h"
23*58e6ee5fSAndroid Build Coastguard Worker #include "trace-msg.h"
24*58e6ee5fSAndroid Build Coastguard Worker
25*58e6ee5fSAndroid Build Coastguard Worker #define dprint(fmt, ...) tracecmd_debug(fmt, ##__VA_ARGS__)
26*58e6ee5fSAndroid Build Coastguard Worker
make_vsocks(int nr,int * fds,unsigned int * ports)27*58e6ee5fSAndroid Build Coastguard Worker static void make_vsocks(int nr, int *fds, unsigned int *ports)
28*58e6ee5fSAndroid Build Coastguard Worker {
29*58e6ee5fSAndroid Build Coastguard Worker unsigned int port;
30*58e6ee5fSAndroid Build Coastguard Worker int i, fd, ret;
31*58e6ee5fSAndroid Build Coastguard Worker
32*58e6ee5fSAndroid Build Coastguard Worker for (i = 0; i < nr; i++) {
33*58e6ee5fSAndroid Build Coastguard Worker fd = trace_vsock_make_any();
34*58e6ee5fSAndroid Build Coastguard Worker if (fd < 0)
35*58e6ee5fSAndroid Build Coastguard Worker die("Failed to open vsocket");
36*58e6ee5fSAndroid Build Coastguard Worker
37*58e6ee5fSAndroid Build Coastguard Worker ret = trace_vsock_get_port(fd, &port);
38*58e6ee5fSAndroid Build Coastguard Worker if (ret < 0)
39*58e6ee5fSAndroid Build Coastguard Worker die("Failed to get vsocket address");
40*58e6ee5fSAndroid Build Coastguard Worker
41*58e6ee5fSAndroid Build Coastguard Worker fds[i] = fd;
42*58e6ee5fSAndroid Build Coastguard Worker ports[i] = port;
43*58e6ee5fSAndroid Build Coastguard Worker }
44*58e6ee5fSAndroid Build Coastguard Worker }
45*58e6ee5fSAndroid Build Coastguard Worker
make_net(int nr,int * fds,unsigned int * ports)46*58e6ee5fSAndroid Build Coastguard Worker static void make_net(int nr, int *fds, unsigned int *ports)
47*58e6ee5fSAndroid Build Coastguard Worker {
48*58e6ee5fSAndroid Build Coastguard Worker int port;
49*58e6ee5fSAndroid Build Coastguard Worker int i, fd;
50*58e6ee5fSAndroid Build Coastguard Worker int start_port = START_PORT_SEARCH;
51*58e6ee5fSAndroid Build Coastguard Worker
52*58e6ee5fSAndroid Build Coastguard Worker for (i = 0; i < nr; i++) {
53*58e6ee5fSAndroid Build Coastguard Worker port = trace_net_search(start_port, &fd, USE_TCP);
54*58e6ee5fSAndroid Build Coastguard Worker if (port < 0)
55*58e6ee5fSAndroid Build Coastguard Worker die("Failed to open socket");
56*58e6ee5fSAndroid Build Coastguard Worker if (listen(fd, 5) < 0)
57*58e6ee5fSAndroid Build Coastguard Worker die("Failed to listen on port %d\n", port);
58*58e6ee5fSAndroid Build Coastguard Worker fds[i] = fd;
59*58e6ee5fSAndroid Build Coastguard Worker ports[i] = port;
60*58e6ee5fSAndroid Build Coastguard Worker dprint("CPU[%d]: fd:%d port:%d\n", i, fd, port);
61*58e6ee5fSAndroid Build Coastguard Worker start_port = port + 1;
62*58e6ee5fSAndroid Build Coastguard Worker }
63*58e6ee5fSAndroid Build Coastguard Worker }
64*58e6ee5fSAndroid Build Coastguard Worker
make_sockets(int nr,int * fds,unsigned int * ports,const char * network)65*58e6ee5fSAndroid Build Coastguard Worker static void make_sockets(int nr, int *fds, unsigned int *ports,
66*58e6ee5fSAndroid Build Coastguard Worker const char * network)
67*58e6ee5fSAndroid Build Coastguard Worker {
68*58e6ee5fSAndroid Build Coastguard Worker if (network)
69*58e6ee5fSAndroid Build Coastguard Worker return make_net(nr, fds, ports);
70*58e6ee5fSAndroid Build Coastguard Worker else
71*58e6ee5fSAndroid Build Coastguard Worker return make_vsocks(nr, fds, ports);
72*58e6ee5fSAndroid Build Coastguard Worker }
73*58e6ee5fSAndroid Build Coastguard Worker
open_agent_fifos(int nr_cpus,int * fds)74*58e6ee5fSAndroid Build Coastguard Worker static int open_agent_fifos(int nr_cpus, int *fds)
75*58e6ee5fSAndroid Build Coastguard Worker {
76*58e6ee5fSAndroid Build Coastguard Worker char path[PATH_MAX];
77*58e6ee5fSAndroid Build Coastguard Worker int i, fd, ret;
78*58e6ee5fSAndroid Build Coastguard Worker
79*58e6ee5fSAndroid Build Coastguard Worker for (i = 0; i < nr_cpus; i++) {
80*58e6ee5fSAndroid Build Coastguard Worker snprintf(path, sizeof(path), VIRTIO_FIFO_FMT, i);
81*58e6ee5fSAndroid Build Coastguard Worker fd = open(path, O_WRONLY);
82*58e6ee5fSAndroid Build Coastguard Worker if (fd < 0) {
83*58e6ee5fSAndroid Build Coastguard Worker ret = -errno;
84*58e6ee5fSAndroid Build Coastguard Worker goto cleanup;
85*58e6ee5fSAndroid Build Coastguard Worker }
86*58e6ee5fSAndroid Build Coastguard Worker
87*58e6ee5fSAndroid Build Coastguard Worker fds[i] = fd;
88*58e6ee5fSAndroid Build Coastguard Worker }
89*58e6ee5fSAndroid Build Coastguard Worker
90*58e6ee5fSAndroid Build Coastguard Worker return 0;
91*58e6ee5fSAndroid Build Coastguard Worker
92*58e6ee5fSAndroid Build Coastguard Worker cleanup:
93*58e6ee5fSAndroid Build Coastguard Worker while (--i >= 0)
94*58e6ee5fSAndroid Build Coastguard Worker close(fds[i]);
95*58e6ee5fSAndroid Build Coastguard Worker
96*58e6ee5fSAndroid Build Coastguard Worker return ret;
97*58e6ee5fSAndroid Build Coastguard Worker }
98*58e6ee5fSAndroid Build Coastguard Worker
get_clock(int argc,char ** argv)99*58e6ee5fSAndroid Build Coastguard Worker static char *get_clock(int argc, char **argv)
100*58e6ee5fSAndroid Build Coastguard Worker {
101*58e6ee5fSAndroid Build Coastguard Worker int i;
102*58e6ee5fSAndroid Build Coastguard Worker
103*58e6ee5fSAndroid Build Coastguard Worker if (!argc || !argv)
104*58e6ee5fSAndroid Build Coastguard Worker return NULL;
105*58e6ee5fSAndroid Build Coastguard Worker
106*58e6ee5fSAndroid Build Coastguard Worker for (i = 0; i < argc - 1; i++) {
107*58e6ee5fSAndroid Build Coastguard Worker if (!strcmp("-C", argv[i]))
108*58e6ee5fSAndroid Build Coastguard Worker return argv[i+1];
109*58e6ee5fSAndroid Build Coastguard Worker }
110*58e6ee5fSAndroid Build Coastguard Worker return NULL;
111*58e6ee5fSAndroid Build Coastguard Worker }
112*58e6ee5fSAndroid Build Coastguard Worker
trace_print_connection(int fd,const char * network)113*58e6ee5fSAndroid Build Coastguard Worker static void trace_print_connection(int fd, const char *network)
114*58e6ee5fSAndroid Build Coastguard Worker {
115*58e6ee5fSAndroid Build Coastguard Worker int ret;
116*58e6ee5fSAndroid Build Coastguard Worker
117*58e6ee5fSAndroid Build Coastguard Worker if (network)
118*58e6ee5fSAndroid Build Coastguard Worker ret = trace_net_print_connection(fd);
119*58e6ee5fSAndroid Build Coastguard Worker else
120*58e6ee5fSAndroid Build Coastguard Worker ret = trace_vsock_print_connection(fd);
121*58e6ee5fSAndroid Build Coastguard Worker if (ret < 0)
122*58e6ee5fSAndroid Build Coastguard Worker tracecmd_debug("Could not print connection fd:%d\n", fd);
123*58e6ee5fSAndroid Build Coastguard Worker }
124*58e6ee5fSAndroid Build Coastguard Worker
agent_handle(int sd,int nr_cpus,int page_size,const char * network)125*58e6ee5fSAndroid Build Coastguard Worker static void agent_handle(int sd, int nr_cpus, int page_size, const char *network)
126*58e6ee5fSAndroid Build Coastguard Worker {
127*58e6ee5fSAndroid Build Coastguard Worker struct tracecmd_tsync_protos *tsync_protos = NULL;
128*58e6ee5fSAndroid Build Coastguard Worker struct tracecmd_time_sync *tsync = NULL;
129*58e6ee5fSAndroid Build Coastguard Worker struct tracecmd_msg_handle *msg_handle;
130*58e6ee5fSAndroid Build Coastguard Worker char *tsync_proto = NULL;
131*58e6ee5fSAndroid Build Coastguard Worker unsigned long long trace_id;
132*58e6ee5fSAndroid Build Coastguard Worker unsigned int remote_id;
133*58e6ee5fSAndroid Build Coastguard Worker unsigned int local_id;
134*58e6ee5fSAndroid Build Coastguard Worker unsigned int tsync_port = 0;
135*58e6ee5fSAndroid Build Coastguard Worker unsigned int *ports;
136*58e6ee5fSAndroid Build Coastguard Worker char **argv = NULL;
137*58e6ee5fSAndroid Build Coastguard Worker int argc = 0;
138*58e6ee5fSAndroid Build Coastguard Worker bool use_fifos;
139*58e6ee5fSAndroid Build Coastguard Worker int *fds;
140*58e6ee5fSAndroid Build Coastguard Worker int ret;
141*58e6ee5fSAndroid Build Coastguard Worker int fd;
142*58e6ee5fSAndroid Build Coastguard Worker
143*58e6ee5fSAndroid Build Coastguard Worker fds = calloc(nr_cpus, sizeof(*fds));
144*58e6ee5fSAndroid Build Coastguard Worker ports = calloc(nr_cpus, sizeof(*ports));
145*58e6ee5fSAndroid Build Coastguard Worker if (!fds || !ports)
146*58e6ee5fSAndroid Build Coastguard Worker die("Failed to allocate memory");
147*58e6ee5fSAndroid Build Coastguard Worker
148*58e6ee5fSAndroid Build Coastguard Worker msg_handle = tracecmd_msg_handle_alloc(sd, 0);
149*58e6ee5fSAndroid Build Coastguard Worker if (!msg_handle)
150*58e6ee5fSAndroid Build Coastguard Worker die("Failed to allocate message handle");
151*58e6ee5fSAndroid Build Coastguard Worker
152*58e6ee5fSAndroid Build Coastguard Worker ret = tracecmd_msg_recv_trace_req(msg_handle, &argc, &argv,
153*58e6ee5fSAndroid Build Coastguard Worker &use_fifos, &trace_id,
154*58e6ee5fSAndroid Build Coastguard Worker &tsync_protos);
155*58e6ee5fSAndroid Build Coastguard Worker if (ret < 0)
156*58e6ee5fSAndroid Build Coastguard Worker die("Failed to receive trace request");
157*58e6ee5fSAndroid Build Coastguard Worker
158*58e6ee5fSAndroid Build Coastguard Worker if (use_fifos && open_agent_fifos(nr_cpus, fds))
159*58e6ee5fSAndroid Build Coastguard Worker use_fifos = false;
160*58e6ee5fSAndroid Build Coastguard Worker
161*58e6ee5fSAndroid Build Coastguard Worker if (!use_fifos)
162*58e6ee5fSAndroid Build Coastguard Worker make_sockets(nr_cpus, fds, ports, network);
163*58e6ee5fSAndroid Build Coastguard Worker if (tsync_protos && tsync_protos->names) {
164*58e6ee5fSAndroid Build Coastguard Worker if (network) {
165*58e6ee5fSAndroid Build Coastguard Worker /* For now just use something */
166*58e6ee5fSAndroid Build Coastguard Worker remote_id = 2;
167*58e6ee5fSAndroid Build Coastguard Worker local_id = 1;
168*58e6ee5fSAndroid Build Coastguard Worker tsync_port = trace_net_search(START_PORT_SEARCH, &fd, USE_TCP);
169*58e6ee5fSAndroid Build Coastguard Worker if (listen(fd, 5) < 0)
170*58e6ee5fSAndroid Build Coastguard Worker die("Failed to listen on %d\n", tsync_port);
171*58e6ee5fSAndroid Build Coastguard Worker } else {
172*58e6ee5fSAndroid Build Coastguard Worker if (get_vsocket_params(msg_handle->fd, &local_id,
173*58e6ee5fSAndroid Build Coastguard Worker &remote_id)) {
174*58e6ee5fSAndroid Build Coastguard Worker warning("Failed to get local and remote ids");
175*58e6ee5fSAndroid Build Coastguard Worker /* Just make something up */
176*58e6ee5fSAndroid Build Coastguard Worker remote_id = -1;
177*58e6ee5fSAndroid Build Coastguard Worker local_id = -2;
178*58e6ee5fSAndroid Build Coastguard Worker }
179*58e6ee5fSAndroid Build Coastguard Worker fd = trace_vsock_make_any();
180*58e6ee5fSAndroid Build Coastguard Worker if (fd >= 0 &&
181*58e6ee5fSAndroid Build Coastguard Worker trace_vsock_get_port(fd, &tsync_port) < 0) {
182*58e6ee5fSAndroid Build Coastguard Worker close(fd);
183*58e6ee5fSAndroid Build Coastguard Worker fd = -1;
184*58e6ee5fSAndroid Build Coastguard Worker }
185*58e6ee5fSAndroid Build Coastguard Worker }
186*58e6ee5fSAndroid Build Coastguard Worker if (fd >= 0) {
187*58e6ee5fSAndroid Build Coastguard Worker tsync = tracecmd_tsync_with_host(fd, tsync_protos,
188*58e6ee5fSAndroid Build Coastguard Worker get_clock(argc, argv),
189*58e6ee5fSAndroid Build Coastguard Worker remote_id, local_id);
190*58e6ee5fSAndroid Build Coastguard Worker }
191*58e6ee5fSAndroid Build Coastguard Worker if (tsync) {
192*58e6ee5fSAndroid Build Coastguard Worker tracecmd_tsync_get_selected_proto(tsync, &tsync_proto);
193*58e6ee5fSAndroid Build Coastguard Worker } else {
194*58e6ee5fSAndroid Build Coastguard Worker warning("Failed to negotiate timestamps synchronization with the host");
195*58e6ee5fSAndroid Build Coastguard Worker if (fd >= 0)
196*58e6ee5fSAndroid Build Coastguard Worker close(fd);
197*58e6ee5fSAndroid Build Coastguard Worker }
198*58e6ee5fSAndroid Build Coastguard Worker }
199*58e6ee5fSAndroid Build Coastguard Worker trace_id = tracecmd_generate_traceid();
200*58e6ee5fSAndroid Build Coastguard Worker ret = tracecmd_msg_send_trace_resp(msg_handle, nr_cpus, page_size,
201*58e6ee5fSAndroid Build Coastguard Worker ports, use_fifos, trace_id,
202*58e6ee5fSAndroid Build Coastguard Worker tsync_proto, tsync_port);
203*58e6ee5fSAndroid Build Coastguard Worker if (ret < 0)
204*58e6ee5fSAndroid Build Coastguard Worker die("Failed to send trace response");
205*58e6ee5fSAndroid Build Coastguard Worker
206*58e6ee5fSAndroid Build Coastguard Worker trace_record_agent(msg_handle, nr_cpus, fds, argc, argv,
207*58e6ee5fSAndroid Build Coastguard Worker use_fifos, trace_id, network);
208*58e6ee5fSAndroid Build Coastguard Worker
209*58e6ee5fSAndroid Build Coastguard Worker if (tsync) {
210*58e6ee5fSAndroid Build Coastguard Worker tracecmd_tsync_with_host_stop(tsync);
211*58e6ee5fSAndroid Build Coastguard Worker tracecmd_tsync_free(tsync);
212*58e6ee5fSAndroid Build Coastguard Worker }
213*58e6ee5fSAndroid Build Coastguard Worker
214*58e6ee5fSAndroid Build Coastguard Worker if (tsync_protos) {
215*58e6ee5fSAndroid Build Coastguard Worker free(tsync_protos->names);
216*58e6ee5fSAndroid Build Coastguard Worker free(tsync_protos);
217*58e6ee5fSAndroid Build Coastguard Worker }
218*58e6ee5fSAndroid Build Coastguard Worker free(argv[0]);
219*58e6ee5fSAndroid Build Coastguard Worker free(argv);
220*58e6ee5fSAndroid Build Coastguard Worker free(ports);
221*58e6ee5fSAndroid Build Coastguard Worker free(fds);
222*58e6ee5fSAndroid Build Coastguard Worker tracecmd_msg_handle_close(msg_handle);
223*58e6ee5fSAndroid Build Coastguard Worker exit(0);
224*58e6ee5fSAndroid Build Coastguard Worker }
225*58e6ee5fSAndroid Build Coastguard Worker
226*58e6ee5fSAndroid Build Coastguard Worker static volatile pid_t handler_pid;
227*58e6ee5fSAndroid Build Coastguard Worker
handle_sigchld(int sig)228*58e6ee5fSAndroid Build Coastguard Worker static void handle_sigchld(int sig)
229*58e6ee5fSAndroid Build Coastguard Worker {
230*58e6ee5fSAndroid Build Coastguard Worker int wstatus;
231*58e6ee5fSAndroid Build Coastguard Worker pid_t pid;
232*58e6ee5fSAndroid Build Coastguard Worker
233*58e6ee5fSAndroid Build Coastguard Worker for (;;) {
234*58e6ee5fSAndroid Build Coastguard Worker pid = waitpid(-1, &wstatus, WNOHANG);
235*58e6ee5fSAndroid Build Coastguard Worker if (pid <= 0)
236*58e6ee5fSAndroid Build Coastguard Worker break;
237*58e6ee5fSAndroid Build Coastguard Worker
238*58e6ee5fSAndroid Build Coastguard Worker if (pid == handler_pid)
239*58e6ee5fSAndroid Build Coastguard Worker handler_pid = 0;
240*58e6ee5fSAndroid Build Coastguard Worker }
241*58e6ee5fSAndroid Build Coastguard Worker }
242*58e6ee5fSAndroid Build Coastguard Worker
do_fork()243*58e6ee5fSAndroid Build Coastguard Worker static pid_t do_fork()
244*58e6ee5fSAndroid Build Coastguard Worker {
245*58e6ee5fSAndroid Build Coastguard Worker /* in debug mode, we do not fork off children */
246*58e6ee5fSAndroid Build Coastguard Worker if (tracecmd_get_debug())
247*58e6ee5fSAndroid Build Coastguard Worker return 0;
248*58e6ee5fSAndroid Build Coastguard Worker
249*58e6ee5fSAndroid Build Coastguard Worker return fork();
250*58e6ee5fSAndroid Build Coastguard Worker }
251*58e6ee5fSAndroid Build Coastguard Worker
agent_serve(unsigned int port,bool do_daemon,const char * network)252*58e6ee5fSAndroid Build Coastguard Worker static void agent_serve(unsigned int port, bool do_daemon, const char *network)
253*58e6ee5fSAndroid Build Coastguard Worker {
254*58e6ee5fSAndroid Build Coastguard Worker struct sockaddr_storage net_addr;
255*58e6ee5fSAndroid Build Coastguard Worker struct sockaddr *addr = NULL;
256*58e6ee5fSAndroid Build Coastguard Worker socklen_t *addr_len_p = NULL;
257*58e6ee5fSAndroid Build Coastguard Worker socklen_t addr_len = sizeof(net_addr);
258*58e6ee5fSAndroid Build Coastguard Worker int sd, cd, nr_cpus;
259*58e6ee5fSAndroid Build Coastguard Worker unsigned int cid;
260*58e6ee5fSAndroid Build Coastguard Worker pid_t pid;
261*58e6ee5fSAndroid Build Coastguard Worker
262*58e6ee5fSAndroid Build Coastguard Worker signal(SIGCHLD, handle_sigchld);
263*58e6ee5fSAndroid Build Coastguard Worker
264*58e6ee5fSAndroid Build Coastguard Worker if (network) {
265*58e6ee5fSAndroid Build Coastguard Worker addr = (struct sockaddr *)&net_addr;
266*58e6ee5fSAndroid Build Coastguard Worker addr_len_p = &addr_len;
267*58e6ee5fSAndroid Build Coastguard Worker }
268*58e6ee5fSAndroid Build Coastguard Worker
269*58e6ee5fSAndroid Build Coastguard Worker nr_cpus = tracecmd_count_cpus();
270*58e6ee5fSAndroid Build Coastguard Worker page_size = getpagesize();
271*58e6ee5fSAndroid Build Coastguard Worker
272*58e6ee5fSAndroid Build Coastguard Worker if (network) {
273*58e6ee5fSAndroid Build Coastguard Worker sd = trace_net_make(port, USE_TCP);
274*58e6ee5fSAndroid Build Coastguard Worker if (listen(sd, 5) < 0)
275*58e6ee5fSAndroid Build Coastguard Worker die("Failed to listen on %d\n", port);
276*58e6ee5fSAndroid Build Coastguard Worker } else
277*58e6ee5fSAndroid Build Coastguard Worker sd = trace_vsock_make(port);
278*58e6ee5fSAndroid Build Coastguard Worker if (sd < 0)
279*58e6ee5fSAndroid Build Coastguard Worker die("Failed to open socket");
280*58e6ee5fSAndroid Build Coastguard Worker tracecmd_tsync_init();
281*58e6ee5fSAndroid Build Coastguard Worker
282*58e6ee5fSAndroid Build Coastguard Worker if (!network) {
283*58e6ee5fSAndroid Build Coastguard Worker cid = trace_vsock_local_cid();
284*58e6ee5fSAndroid Build Coastguard Worker if (cid >= 0)
285*58e6ee5fSAndroid Build Coastguard Worker printf("listening on @%u:%u\n", cid, port);
286*58e6ee5fSAndroid Build Coastguard Worker }
287*58e6ee5fSAndroid Build Coastguard Worker
288*58e6ee5fSAndroid Build Coastguard Worker if (do_daemon && daemon(1, 0))
289*58e6ee5fSAndroid Build Coastguard Worker die("daemon");
290*58e6ee5fSAndroid Build Coastguard Worker
291*58e6ee5fSAndroid Build Coastguard Worker for (;;) {
292*58e6ee5fSAndroid Build Coastguard Worker cd = accept(sd, addr, addr_len_p);
293*58e6ee5fSAndroid Build Coastguard Worker if (cd < 0) {
294*58e6ee5fSAndroid Build Coastguard Worker if (errno == EINTR)
295*58e6ee5fSAndroid Build Coastguard Worker continue;
296*58e6ee5fSAndroid Build Coastguard Worker die("accept");
297*58e6ee5fSAndroid Build Coastguard Worker }
298*58e6ee5fSAndroid Build Coastguard Worker if (tracecmd_get_debug())
299*58e6ee5fSAndroid Build Coastguard Worker trace_print_connection(cd, network);
300*58e6ee5fSAndroid Build Coastguard Worker
301*58e6ee5fSAndroid Build Coastguard Worker if (network && !trace_net_cmp_connection(&net_addr, network)) {
302*58e6ee5fSAndroid Build Coastguard Worker dprint("Client does not match '%s'\n", network);
303*58e6ee5fSAndroid Build Coastguard Worker close(cd);
304*58e6ee5fSAndroid Build Coastguard Worker continue;
305*58e6ee5fSAndroid Build Coastguard Worker }
306*58e6ee5fSAndroid Build Coastguard Worker
307*58e6ee5fSAndroid Build Coastguard Worker if (handler_pid)
308*58e6ee5fSAndroid Build Coastguard Worker goto busy;
309*58e6ee5fSAndroid Build Coastguard Worker
310*58e6ee5fSAndroid Build Coastguard Worker pid = do_fork();
311*58e6ee5fSAndroid Build Coastguard Worker if (pid == 0) {
312*58e6ee5fSAndroid Build Coastguard Worker close(sd);
313*58e6ee5fSAndroid Build Coastguard Worker signal(SIGCHLD, SIG_DFL);
314*58e6ee5fSAndroid Build Coastguard Worker agent_handle(cd, nr_cpus, page_size, network);
315*58e6ee5fSAndroid Build Coastguard Worker }
316*58e6ee5fSAndroid Build Coastguard Worker if (pid > 0)
317*58e6ee5fSAndroid Build Coastguard Worker handler_pid = pid;
318*58e6ee5fSAndroid Build Coastguard Worker
319*58e6ee5fSAndroid Build Coastguard Worker busy:
320*58e6ee5fSAndroid Build Coastguard Worker close(cd);
321*58e6ee5fSAndroid Build Coastguard Worker }
322*58e6ee5fSAndroid Build Coastguard Worker }
323*58e6ee5fSAndroid Build Coastguard Worker
324*58e6ee5fSAndroid Build Coastguard Worker enum {
325*58e6ee5fSAndroid Build Coastguard Worker OPT_verbose = 254,
326*58e6ee5fSAndroid Build Coastguard Worker DO_DEBUG = 255
327*58e6ee5fSAndroid Build Coastguard Worker };
328*58e6ee5fSAndroid Build Coastguard Worker
trace_agent(int argc,char ** argv)329*58e6ee5fSAndroid Build Coastguard Worker void trace_agent(int argc, char **argv)
330*58e6ee5fSAndroid Build Coastguard Worker {
331*58e6ee5fSAndroid Build Coastguard Worker bool do_daemon = false;
332*58e6ee5fSAndroid Build Coastguard Worker unsigned int port = TRACE_AGENT_DEFAULT_PORT;
333*58e6ee5fSAndroid Build Coastguard Worker const char *network = NULL;
334*58e6ee5fSAndroid Build Coastguard Worker
335*58e6ee5fSAndroid Build Coastguard Worker if (argc < 2)
336*58e6ee5fSAndroid Build Coastguard Worker usage(argv);
337*58e6ee5fSAndroid Build Coastguard Worker
338*58e6ee5fSAndroid Build Coastguard Worker if (strcmp(argv[1], "agent") != 0)
339*58e6ee5fSAndroid Build Coastguard Worker usage(argv);
340*58e6ee5fSAndroid Build Coastguard Worker
341*58e6ee5fSAndroid Build Coastguard Worker for (;;) {
342*58e6ee5fSAndroid Build Coastguard Worker int c, option_index = 0;
343*58e6ee5fSAndroid Build Coastguard Worker static struct option long_options[] = {
344*58e6ee5fSAndroid Build Coastguard Worker {"port", required_argument, NULL, 'p'},
345*58e6ee5fSAndroid Build Coastguard Worker {"help", no_argument, NULL, '?'},
346*58e6ee5fSAndroid Build Coastguard Worker {"debug", no_argument, NULL, DO_DEBUG},
347*58e6ee5fSAndroid Build Coastguard Worker {"verbose", optional_argument, NULL, OPT_verbose},
348*58e6ee5fSAndroid Build Coastguard Worker {NULL, 0, NULL, 0}
349*58e6ee5fSAndroid Build Coastguard Worker };
350*58e6ee5fSAndroid Build Coastguard Worker
351*58e6ee5fSAndroid Build Coastguard Worker c = getopt_long(argc-1, argv+1, "+hp:DN:",
352*58e6ee5fSAndroid Build Coastguard Worker long_options, &option_index);
353*58e6ee5fSAndroid Build Coastguard Worker if (c == -1)
354*58e6ee5fSAndroid Build Coastguard Worker break;
355*58e6ee5fSAndroid Build Coastguard Worker switch (c) {
356*58e6ee5fSAndroid Build Coastguard Worker case 'h':
357*58e6ee5fSAndroid Build Coastguard Worker usage(argv);
358*58e6ee5fSAndroid Build Coastguard Worker break;
359*58e6ee5fSAndroid Build Coastguard Worker case 'N':
360*58e6ee5fSAndroid Build Coastguard Worker network = optarg;
361*58e6ee5fSAndroid Build Coastguard Worker break;
362*58e6ee5fSAndroid Build Coastguard Worker case 'p':
363*58e6ee5fSAndroid Build Coastguard Worker port = atoi(optarg);
364*58e6ee5fSAndroid Build Coastguard Worker break;
365*58e6ee5fSAndroid Build Coastguard Worker case 'D':
366*58e6ee5fSAndroid Build Coastguard Worker do_daemon = true;
367*58e6ee5fSAndroid Build Coastguard Worker break;
368*58e6ee5fSAndroid Build Coastguard Worker case DO_DEBUG:
369*58e6ee5fSAndroid Build Coastguard Worker tracecmd_set_debug(true);
370*58e6ee5fSAndroid Build Coastguard Worker break;
371*58e6ee5fSAndroid Build Coastguard Worker case OPT_verbose:
372*58e6ee5fSAndroid Build Coastguard Worker if (trace_set_verbose(optarg) < 0)
373*58e6ee5fSAndroid Build Coastguard Worker die("invalid verbose level %s", optarg);
374*58e6ee5fSAndroid Build Coastguard Worker break;
375*58e6ee5fSAndroid Build Coastguard Worker default:
376*58e6ee5fSAndroid Build Coastguard Worker usage(argv);
377*58e6ee5fSAndroid Build Coastguard Worker }
378*58e6ee5fSAndroid Build Coastguard Worker }
379*58e6ee5fSAndroid Build Coastguard Worker
380*58e6ee5fSAndroid Build Coastguard Worker if (optind < argc-1)
381*58e6ee5fSAndroid Build Coastguard Worker usage(argv);
382*58e6ee5fSAndroid Build Coastguard Worker
383*58e6ee5fSAndroid Build Coastguard Worker agent_serve(port, do_daemon, network);
384*58e6ee5fSAndroid Build Coastguard Worker }
385