Esempio n. 1
0
static int process_rqt_cmd(const struct rqt_box *rqt)
{
	ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box));
	memset(rsp, 0, sizeof(struct rsp_box));

	rsp->rsp = rqt->rqt;
	rsp->rsp_data = rqt->rqt_data;

	switch (rqt->rqt_data) {
	case RQT_CMD_REBOOT:
		debug("TARGET RESET\n");
		send_rsp(rsp);
		g_dnl_unregister();
		dfu_free_entities();
#ifdef CONFIG_THOR_RESET_OFF
		return RESET_DONE;
#endif
		run_command("reset", 0);
		break;
	case RQT_CMD_POWEROFF:
	case RQT_CMD_EFSCLEAR:
		send_rsp(rsp);
	default:
		printf("Command not supported -> cmd: %d\n", rqt->rqt_data);
		return -EINVAL;
	}

	return true;
}
Esempio n. 2
0
static int recv_greeting(req_t *req)
{
/*  Performs the initial handshake with the client
 *    (SOMEDAY including authentication & encryption, if needed).
 *  Returns 0 if the greeting is valid, or -1 on error.
 */
    int n;
    char buf[MAX_SOCK_LINE];
    Lex l;
    int done = 0;
    int tok;

    assert(req->sd >= 0);

    if ((n = read_line(req->sd, buf, sizeof(buf))) < 0) {
        log_msg(LOG_NOTICE, "Unable to read greeting from <%s:%d>: %s",
            req->fqdn, req->port, strerror(errno));
        return(-1);
    }
    else if (n == 0) {
        log_msg(LOG_NOTICE, "Connection terminated by <%s:%d>",
            req->fqdn, req->port);
        return(-1);
    }

    DPRINTF((5, "Received greeting: %s", buf));

    l = lex_create(buf, proto_strs);
    while (!done) {
        tok = lex_next(l);
        switch(tok) {
        case CONMAN_TOK_HELLO:
            parse_greeting(l, req);
            break;
        case LEX_EOF:
        case LEX_EOL:
            done = 1;
            break;
        default:
            break;
        }
    }
    lex_destroy(l);

    /*  Validate greeting.
     */
    if (!req->user) {
        req->user = create_string("unknown");
        send_rsp(req, CONMAN_ERR_BAD_REQUEST,
            "Invalid greeting: no user specified");
        return(-1);
    }

    /*  Send response to greeting.
     */
    return(send_rsp(req, CONMAN_ERR_NONE, NULL));
}
Esempio n. 3
0
static int perform_monitor_cmd(req_t *req, server_conf_t *conf)
{
/*  Performs the MONITOR command, placing the client in a
 *    "read-only" session with a single console.
 *  Returns 0 if the command succeeds, or -1 on error.
 */
    obj_t *client;
    obj_t *console;

    assert(req->sd >= 0);
    assert(req->command == CONMAN_CMD_MONITOR);
    assert(list_count(req->consoles) == 1);

    log_msg(LOG_INFO, "Client <%s@%s:%d> issued monitor command",
        req->user, req->fqdn, req->port);

    if (send_rsp(req, CONMAN_ERR_NONE, NULL) < 0)
        return(-1);
    client = create_client_obj(conf, req);
    console = list_peek(req->consoles);
    assert(is_console_obj(console));
    link_objs(console, client);
    check_console_state(console, client);
    return(0);
}
Esempio n. 4
0
static int query_consoles_via_regex(
    server_conf_t *conf, req_t *req, List matches)
{
/*  Match request patterns against console names using regular expressions.
 */
    char *p;
    ListIterator i;
    char buf[MAX_SOCK_LINE];
    int rc;
    regex_t rex;
    regmatch_t match;
    obj_t *obj;

    /*  An empty list for the QUERY command matches all consoles.
     */
    if (list_is_empty(req->consoles)) {
        p = create_string(".*");
        list_append(req->consoles, p);
    }

    /*  Combine console patterns via alternation to create single regex.
     */
    i = list_iterator_create(req->consoles);
    strlcpy(buf, list_next(i), sizeof(buf));
    while ((p = list_next(i))) {
        strlcat(buf, "|", sizeof(buf));
        strlcat(buf, p, sizeof(buf));
    }
    list_iterator_destroy(i);

    /*  Initialize 'rex' to silence "uninitialized use" warnings.
     */
    memset(&rex, 0, sizeof(rex));

    /*  Compile regex for searching server's console objs.
     */
    rc = regcomp(&rex, buf, REG_EXTENDED | REG_ICASE);
    if (rc != 0) {
        if (regerror(rc, &rex, buf, sizeof(buf)) > sizeof(buf))
            log_msg(LOG_WARNING, "Got regerror() buffer overrun");
        regfree(&rex);
        send_rsp(req, CONMAN_ERR_BAD_REGEX, buf);
        return(-1);
    }

    /*  Search objs for console names matching console patterns in the request.
     */
    i = list_iterator_create(conf->objs);
    while ((obj = list_next(i))) {
        if (!is_console_obj(obj))
            continue;
        if (!regexec(&rex, obj->name, 1, &match, 0)
          && (match.rm_so == 0) && (match.rm_eo == strlen(obj->name)))
            list_append(matches, obj);
    }
    list_iterator_destroy(i);
    regfree(&rex);
    return(0);
}
Esempio n. 5
0
void timer_device::rcv_rqst (unsigned long ofs, unsigned char be,
                             unsigned char *data, bool bWrite)
{
    bool bErr = false;

    if (bWrite)
        this->write (ofs, be, data, bErr);
    else
        this->read (ofs, be, data, bErr);

    send_rsp (bErr);
}
Esempio n. 6
0
void ramdac_device::rcv_rqst (uint32_t ofs, uint8_t be,
                              uint8_t *data, bool bWrite)
{

    bool bErr = false;

    if(bWrite){
        this->write(ofs, be, data, bErr);
    }else{
        this->read(ofs, be, data, bErr);
    }

    send_rsp(bErr);

    return;
}
Esempio n. 7
0
void sl_timer_device::rcv_rqst (unsigned long ofs, unsigned char be,
                                unsigned char *data, bool bWrite)
{

    bool bErr = false;

    if(bWrite){
        this->write(ofs, be, data, bErr);
    }else{
        this->read(ofs, be, data, bErr);
    }

    send_rsp(bErr);

    return;
}
Esempio n. 8
0
static int validate_req(req_t *req)
{
/*  Validates the given request.
 *  Returns 0 if the request is valid, or -1 on error.
 */
    if (list_is_empty(req->consoles)) {
        send_rsp(req, CONMAN_ERR_NO_CONSOLES, "Found no matching consoles");
        return(-1);
    }
    if (check_too_many_consoles(req) < 0)
        return(-1);
    if (check_busy_consoles(req) < 0)
        return(-1);

    return(0);
}
Esempio n. 9
0
static int perform_connect_cmd(req_t *req, server_conf_t *conf)
{
/*  Performs the CONNECT command.  If a single console is specified,
 *    the client is placed in a "read-write" session with that console.
 *    Otherwise, the client is placed in a "write-only" broadcast session
 *    affecting multiple consoles.
 *  Returns 0 if the command succeeds, or -1 on error.
 */
    obj_t *client;
    obj_t *console;
    ListIterator i;

    assert(req->sd >= 0);
    assert(req->command == CONMAN_CMD_CONNECT);

    log_msg(LOG_INFO, "Client <%s@%s:%d> issued connect command",
        req->user, req->fqdn, req->port);

    if (send_rsp(req, CONMAN_ERR_NONE, NULL) < 0)
        return(-1);
    client = create_client_obj(conf, req);

    if (list_count(req->consoles) == 1) {
        /*
         *  Unicast connection (R/W).
         */
        console = list_peek(req->consoles);
        assert(is_console_obj(console));
        link_objs(client, console);
        link_objs(console, client);
        check_console_state(console, client);
    }
    else {
        /*
         *  Broadcast connection (W/O).
         */
        i = list_iterator_create(req->consoles);
        while ((console = list_next(i))) {
            assert(is_console_obj(console));
            link_objs(client, console);
            check_console_state(console, client);
        }
        list_iterator_destroy(i);
    }
    return(0);
}
Esempio n. 10
0
static int perform_query_cmd(req_t *req)
{
/*  Performs the QUERY command, returning a list of consoles that
 *    matches the console patterns given in the client's request.
 *  Returns 0 if the command succeeds, or -1 on error.
 *  Since this cmd is processed entirely by this thread,
 *    the client socket connection is closed once it is finished.
 */
    assert(req->sd >= 0);
    assert(req->command == CONMAN_CMD_QUERY);
    assert(!list_is_empty(req->consoles));

    log_msg(LOG_INFO, "Client <%s@%s:%d> issued query command",
        req->user, req->fqdn, req->port);

    if (send_rsp(req, CONMAN_ERR_NONE, NULL) < 0)
        return(-1);
    destroy_req(req);
    return(0);
}
Esempio n. 11
0
static int check_too_many_consoles(req_t *req)
{
/*  Checks to see if the request matches too many consoles
 *    for the given command.
 *  A MONITOR command can only affect a single console, as can a
 *    CONNECT command unless the broadcast option is enabled.
 *  Returns 0 if the request is valid, or -1 on error.
 */
    ListIterator i;
    obj_t *obj;
    char buf[MAX_SOCK_LINE];

    assert(!list_is_empty(req->consoles));

    if (req->command == CONMAN_CMD_QUERY)
        return(0);
    if (list_count(req->consoles) == 1)
        return(0);
    if ((req->command == CONMAN_CMD_CONNECT) && (req->enableBroadcast))
        return(0);

    snprintf(buf, sizeof(buf), "Found %d matching consoles",
        list_count(req->consoles));
    send_rsp(req, CONMAN_ERR_TOO_MANY_CONSOLES, buf);

    /*  FIXME? Replace with single write_n()?
     */
    i = list_iterator_create(req->consoles);
    while ((obj = list_next(i))) {
        strlcpy(buf, obj->name, sizeof(buf));
        strlcat(buf, "\n", sizeof(buf));
        if (write_n(req->sd, buf, strlen(buf)) < 0) {
            log_msg(LOG_NOTICE, "Unable to write to <%s:%d>: %s",
                req->fqdn, req->port, strerror(errno));
            break;
        }
    }
    list_iterator_destroy(i);
    return(-1);
}
Esempio n. 12
0
static int process_rqt_info(const struct rqt_box *rqt)
{
	ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box));
	memset(rsp, 0, sizeof(struct rsp_box));

	rsp->rsp = rqt->rqt;
	rsp->rsp_data = rqt->rqt_data;

	switch (rqt->rqt_data) {
	case RQT_INFO_VER_PROTOCOL:
		rsp->int_data[0] = VER_PROTOCOL_MAJOR;
		rsp->int_data[1] = VER_PROTOCOL_MINOR;
		break;
	case RQT_INIT_VER_HW:
		snprintf(rsp->str_data[0], sizeof(rsp->str_data[0]),
			 "%x", checkboard());
		break;
	case RQT_INIT_VER_BOOT:
		sprintf(rsp->str_data[0], "%s", U_BOOT_VERSION);
		break;
	case RQT_INIT_VER_KERNEL:
		sprintf(rsp->str_data[0], "%s", "k unknown");
		break;
	case RQT_INIT_VER_PLATFORM:
		sprintf(rsp->str_data[0], "%s", "p unknown");
		break;
	case RQT_INIT_VER_CSC:
		sprintf(rsp->str_data[0], "%s", "c unknown");
		break;
	default:
		return -EINVAL;
	}

	send_rsp(rsp);
	return true;
}
Esempio n. 13
0
static long long int process_rqt_download(const struct rqt_box *rqt)
{
	ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box));
	static long long int left, ret_head;
	int file_type, ret = 0;
	static int cnt;

	memset(rsp, 0, sizeof(struct rsp_box));
	rsp->rsp = rqt->rqt;
	rsp->rsp_data = rqt->rqt_data;

	switch (rqt->rqt_data) {
	case RQT_DL_INIT:
		thor_file_size = rqt->int_data[0];
		debug("INIT: total %d bytes\n", rqt->int_data[0]);
		break;
	case RQT_DL_FILE_INFO:
		file_type = rqt->int_data[0];
		if (file_type == FILE_TYPE_PIT) {
			puts("PIT table file - not supported\n");
			rsp->ack = -ENOTSUPP;
			ret = rsp->ack;
			break;
		}

		thor_file_size = rqt->int_data[1];
		memcpy(f_name, rqt->str_data[0], F_NAME_BUF_SIZE);

		debug("INFO: name(%s, %d), size(%llu), type(%d)\n",
		      f_name, 0, thor_file_size, file_type);

		rsp->int_data[0] = THOR_PACKET_SIZE;

		alt_setting_num = dfu_get_alt(f_name);
		if (alt_setting_num < 0) {
			error("Alt setting [%d] to write not found!",
			      alt_setting_num);
			rsp->ack = -ENODEV;
			ret = rsp->ack;
		}
		break;
	case RQT_DL_FILE_START:
		send_rsp(rsp);
		ret_head = download_head(thor_file_size, THOR_PACKET_SIZE,
					 &left, &cnt);
		if (ret_head < 0) {
			left = 0;
			cnt = 0;
		}
		return ret_head;
	case RQT_DL_FILE_END:
		debug("DL FILE_END\n");
		rsp->ack = download_tail(left, cnt);
		ret = rsp->ack;
		left = 0;
		cnt = 0;
		break;
	case RQT_DL_EXIT:
		debug("DL EXIT\n");
		break;
	default:
		error("Operation not supported: %d", rqt->rqt_data);
		ret = -ENOTSUPP;
	}

	send_rsp(rsp);
	return ret;
}
Esempio n. 14
0
static int check_busy_consoles(req_t *req)
{
/*  Checks to see if a "writable" request affects any consoles
 *    that are currently busy (unless the force or join option is enabled).
 *  Returns 0 if the request is valid, or -1 on error.
 */
    List busy;
    ListIterator i;
    obj_t *console;
    obj_t *writer;
    int gotBcast;
    char *tty;
    time_t t;
    char *delta;
    char buf[MAX_LINE];

    assert(!list_is_empty(req->consoles));

    if ((req->command == CONMAN_CMD_QUERY)
      || (req->command == CONMAN_CMD_MONITOR))
        return(0);
    if (req->enableForce || req->enableJoin)
        return(0);

    busy = list_create(NULL);
    i = list_iterator_create(req->consoles);
    while ((console = list_next(i))) {
        assert(is_console_obj(console));
        if (!list_is_empty(console->writers))
            list_append(busy, console);
    }
    list_iterator_destroy(i);

    if (list_is_empty(busy)) {
        list_destroy(busy);
        return(0);
    }

    if (list_count(busy) == 1) {
        snprintf(buf, sizeof(buf), "Found console already in use");
    }
    else {
        snprintf(buf, sizeof(buf), "Found %d consoles already in use",
            list_count(busy));
    }
    send_rsp(req, CONMAN_ERR_BUSY_CONSOLES, buf);

    /*  Note: the "busy" list contains object references,
     *    so they DO NOT get destroyed here when removed from the list.
     */
    while ((console = list_pop(busy))) {

        i = list_iterator_create(console->writers);
        while ((writer = list_next(i))) {

            assert(is_client_obj(writer));
            x_pthread_mutex_lock(&writer->bufLock);
            t = writer->aux.client.timeLastRead;
            gotBcast = list_is_empty(writer->writers);
            tty = writer->aux.client.req->tty;
            x_pthread_mutex_unlock(&writer->bufLock);
            delta = create_time_delta_string(t, -1);

            snprintf(buf, sizeof(buf),
                "Console [%s] open %s by <%s@%s>%s%s (idle %s).\n",
                console->name, (gotBcast ? "B/C" : "R/W"),
                writer->aux.client.req->user, writer->aux.client.req->host,
                (tty ? " on " : ""), (tty ? tty : ""),
                (delta ? delta : "???"));
            buf[sizeof(buf) - 2] = '\n';
            buf[sizeof(buf) - 1] = '\0';
            if (delta)
                free(delta);
            if (write_n(req->sd, buf, strlen(buf)) < 0) {
                log_msg(LOG_NOTICE, "Unable to write to <%s:%d>: %s",
                    req->fqdn, req->port, strerror(errno));
                break;
            }
        }
        list_iterator_destroy(i);
    }
    list_destroy(busy);
    return(-1);
}