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; }
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)); }
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); }
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); }
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); }
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; }
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; }
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); }
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); }
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); }
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); }
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; }
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; }
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); }