Exemple #1
0
static void
meta_command(struct sockaddr_in *from, char *command)
{
    Server	*s;
    char	*cmd, *name, *dummy;

    parse_connect(command, &cmd, &name, &dummy);
    s = serv_name2server(name); 
    if (!strcmp(cmd + 1, "connect")) {
	char		buf[128];
	Server	       *local;

	if (!s) {
	    s = promiscuous_connect(from, name);
	    if (!s) {
		return;
	    }
	} else if (verify_servers && !verify_server(s, from)) {
	    return;
	}
	s->connected = 1;
	s->last_msgid = -1;
	writelog();
	fprintf(stderr, "Server %s (%s %d) connected\n", s->name, s->hostname,
		s->port);
	local = serv_id2server(0);
	sprintf(buf, "*connectok %s\n", local->name);
	sendto(yo_sock, buf, strlen(buf), 0, (struct sockaddr *) from,
		sizeof(*from));
	connect_server(s->id);
    } else if (!strcmp(cmd + 1, "connectok")) {
	if (!s) {
	    s = promiscuous_connect(from, name);
	    if (!s) {
		return;
	    }
	} else if (verify_servers && !verify_server(s, from)) {
	    return;
	}
	s->connected = 1;
	s->last_msgid = -1;
	writelog();
	fprintf(stderr, "Server %s (%s %d) connected ok\n", s->name,
		s->hostname, s->port);
	connect_server(s->id);
    } else if (!strcmp(cmd + 1, "disconnect")) {
	if (!s) {
	    return;
	}
	s->connected = 0;
	writelog();
	fprintf(stderr, "Server %s (%s %d) disconnected\n", s->name,
		s->hostname, s->port);
	disconnect_server(s->id);
    } else {
	if (!s) {
	    return;
	}
	writelog();
	fprintf(stderr, "Unknown metacommand \"%s\" from server %s\n",
		command, s->name);
    }
}
int main(int argc, char **argv)
{
    int opt;
    char *domname = NULL;
    libvchan_t *data_vchan = NULL;
    int data_port;
    int data_domain;
    int msg_type;
    int s;
    int just_exec = 0;
    int connect_existing = 0;
    char *local_cmdline = NULL;
    char *remote_cmdline = NULL;
    char *request_id;
    char *src_domain_name = NULL;
    int src_domain_id = 0; /* if not -c given, the process is run in dom0 */
    struct service_params svc_params;
    while ((opt = getopt(argc, argv, "d:l:ec:tT")) != -1) {
        switch (opt) {
            case 'd':
                domname = strdup(optarg);
                break;
            case 'l':
                local_cmdline = strdup(optarg);
                break;
            case 'e':
                just_exec = 1;
                break;
            case 'c':
                parse_connect(optarg, &request_id, &src_domain_name, &src_domain_id);
                connect_existing = 1;
                is_service = 1;
                break;
            case 't':
                replace_esc_stdout = 1;
                break;
            case 'T':
                replace_esc_stderr = 1;
                break;
            default:
                usage(argv[0]);
        }
    }
    if (optind >= argc || !domname)
        usage(argv[0]);
    remote_cmdline = argv[optind];

    register_exec_func(&do_exec);

    if (just_exec + connect_existing + (local_cmdline != 0) > 1) {
        fprintf(stderr, "ERROR: only one of -e, -l, -c can be specified\n");
        usage(argv[0]);
    }

    if (strcmp(domname, "dom0") == 0 && !connect_existing) {
        fprintf(stderr, "ERROR: when target domain is 'dom0', -c must be specified\n");
        usage(argv[0]);
    }

    if (strcmp(domname, "dom0") == 0) {
        if (connect_existing) {
            msg_type = MSG_SERVICE_CONNECT;
            strncpy(svc_params.ident, request_id, sizeof(svc_params.ident));
        } else if (just_exec)
            msg_type = MSG_JUST_EXEC;
        else
            msg_type = MSG_EXEC_CMDLINE;
        assert(src_domain_name);
        setenv("QREXEC_REMOTE_DOMAIN", src_domain_name, 1);
        s = connect_unix_socket(src_domain_name);
        negotiate_connection_params(s,
                0, /* dom0 */
                msg_type,
                connect_existing ? (void*)&svc_params : (void*)remote_cmdline,
                connect_existing ? sizeof(svc_params) : strlen(remote_cmdline) + 1,
                &data_domain,
                &data_port);

        prepare_local_fds(remote_cmdline);
        if (connect_existing)
            data_vchan = libvchan_client_init(data_domain, data_port);
        else {
            data_vchan = libvchan_server_init(data_domain, data_port,
                    VCHAN_BUFFER_SIZE, VCHAN_BUFFER_SIZE);
            while (data_vchan && libvchan_is_open(data_vchan) == VCHAN_WAITING)
                libvchan_wait(data_vchan);
        }
        if (!data_vchan || !libvchan_is_open(data_vchan)) {
            fprintf(stderr, "Failed to open data vchan connection\n");
            do_exit(1);
        }
        if (handle_agent_handshake(data_vchan, connect_existing) < 0)
            do_exit(1);
        select_loop(data_vchan);
    } else {
        if (just_exec)
            msg_type = MSG_JUST_EXEC;
        else
            msg_type = MSG_EXEC_CMDLINE;
        s = connect_unix_socket(domname);
        negotiate_connection_params(s,
                src_domain_id,
                msg_type,
                remote_cmdline,
                strlen(remote_cmdline) + 1,
                &data_domain,
                &data_port);
        close(s);
        setenv("QREXEC_REMOTE_DOMAIN", domname, 1);
        prepare_local_fds(local_cmdline);
        if (connect_existing) {
            s = connect_unix_socket(src_domain_name);
            send_service_connect(s, request_id, data_domain, data_port);
            close(s);
        } else {
            data_vchan = libvchan_server_init(data_domain, data_port,
                    VCHAN_BUFFER_SIZE, VCHAN_BUFFER_SIZE);
            if (!data_vchan) {
                fprintf(stderr, "Failed to start data vchan server\n");
                do_exit(1);
            }
            while (libvchan_is_open(data_vchan) == VCHAN_WAITING)
                libvchan_wait(data_vchan);
            if (!libvchan_is_open(data_vchan)) {
                fprintf(stderr, "Failed to open data vchan connection\n");
                do_exit(1);
            }
            if (handle_agent_handshake(data_vchan, 0) < 0)
                do_exit(1);
            select_loop(data_vchan);
        }
    }
    return 0;
}