/* * @brief: create new buffer */ buffer_t *buffer_new(size_t size) { buffer_t *buf = NULL; buf = (buffer_t *)platform_calloc(sizeof(buffer_t)); if (buf && size) { buf->data = (unsigned char *)platform_calloc(size); buf->len = size; if (!buf->data) { platform_free(buf); buf = NULL; } } return buf; }
/* * usbrecords_add * save recovery records in array * @param[t_token] recovery token * @ret 0 - success, -1 error */ int usbrecords_add(transport_recovery_token_t *t_token) { int rc = -1; recovery_entry_t *item = (recovery_entry_t *)platform_calloc(sizeof(recovery_entry_t)); if(item) { LTRACEF("* add token data(%p)\n", t_token->token); item->t_token = t_token; item->timeout = g_recovery_timeout; platform_mutex_lock(&recovery_lock); TAILQ_INSERT_TAIL(&t_recovery_queue, item, entries); platform_mutex_unlock(&recovery_lock); rc = 0; } return rc; }
/* * @brief: set buffer data */ int buffer_setdata(buffer_t *b, unsigned char *data, size_t size) { if (b->data) { platform_free(b->data); } b->data = (unsigned char *)platform_calloc(size); if (!b->data) { return -1; } memcpy(b->data, data, size); #if LOCAL_TRACE hexdump8(b->data, MIN(size, 64)); #endif b->pos = 0; b->len = size; return 0; }
/* * @brief handle token request * mode=0:add token request * mode=1:remove token request */ static int novacom_handle_tokenrequest(device_handle_t dev, uint32_t chan, buffer_t *b, buffer_t *r, unsigned char cmd) { int rc=-1; char *hash = NULL; char *token = NULL; char *blob = NULL; /* skip version */ if ( 0 != buffer_getbyte(b, NULL) ) { LTRACEF("missing version\n"); goto out; } /* get hash */ if ( 0 != buffer_getstring(b, (unsigned char **)&hash) ) { LTRACEF("missing password hash\n"); goto out; } /* get hashed token for "remove" */ if ( (SSH_MSG_USERAUTH_TOKENREQUEST_RM == cmd) && ( 0 != buffer_getstring(b, (unsigned char **)&token) ) ) { LTRACEF("missing token hash\n"); goto out; } /* verify that password hash is good */ if ( true != auth_process_passw(hash, strlen(hash), 1) ) { LTRACEF("invalid password hash\n"); goto out; } /* process tokens */ if (SSH_MSG_USERAUTH_TOKENREQUEST_RM == cmd) { rc = auth_tokenfile_delete(token, strlen(token)); /* pickup res */ if (!rc) { buffer_putbyte(r, SSH_MSG_USERAUTH_SUCCESS); buffer_putbyte(r, 0); /* version */ buffer_putbyte(r, cmd); /* command */ } } else { blob = platform_calloc(NOVACOM_AUTHTOKEN_LEN); if (!blob) { LTRACEF("unable to allocate token\n"); goto out; } /* fill with random data */ LTRACEF("generate token\n"); rc = auth_tokenfile_buffergenerate(blob, NOVACOM_AUTHTOKEN_LEN); if (rc) { LTRACEF("unable to generate token\n"); goto out; } /* save token: creating file with name:<rnduid> */ LTRACEF("save token\n"); char *file = novacom_rnduid(dev); if (!file) { LTRACEF("unable to retrieve rnduid\n"); goto out; } rc = auth_tokenfile_create(file, blob, NOVACOM_AUTHTOKEN_LEN); platform_free(file); if (rc) { LTRACEF("unable to store token\n"); goto out; } LTRACEF("token generated && saved\n"); /* pickup res */ buffer_putbyte(r, SSH_MSG_USERAUTH_TOKEN_REPLY); buffer_putbyte(r, 0); /* version */ buffer_putbyte(r, cmd); /* command */ /* resize output buffer to fit token data */ rc = buffer_resize(r, 16 + NOVACOM_AUTHTOKEN_LEN); if (rc) goto out; rc = buffer_putblob(r, (unsigned char *)blob, NOVACOM_AUTHTOKEN_LEN); LTRACEF("token placed\n"); } out: /* error result */ if (rc) { buffer_setpos(r, 0); buffer_putbyte(r, SSH_MSG_USERAUTH_FAILURE); buffer_putbyte(r, 0); /* version */ buffer_putbyte(r, cmd); /* command */ } LTRACEF("result(%d), r->pos %d, r->size %d\n", rc, r->pos, r->len); /* free resources */ platform_free(hash); platform_free(token); platform_free(blob); return rc; }
static void *novacom_usb_rx_thread(void *arg) { novacom_usb_handle_t *handle = (novacom_usb_handle_t *)arg; transport_recovery_token_t *rec_token = NULL; ///< recovery token int rc; int packet_type; char *buf; int sniff = 1; buf = platform_calloc(MAX_MTU); platform_assert(buf != NULL); LTRACEF("start, handle %p\n", handle); handle->rx_timeout = novacom_usbll_get_timeout(handle->usbll_handle); while (!novacom_shutdown && !handle->shutdown) { platform_time_t st; int time_used; // read a block from the pmux rc = novacom_usb_read(handle, buf, novacom_usbll_get_mtu(handle->usbll_handle)); platform_get_time(&st); time_used = 0; if (rc <= 0) { platform_time_t et; unsigned int count = 0; TRACEL(LOG_ALWAYS, "%s:%d -- usbll(%08x) error: reading packet, result(%d), errno %d\n", __FUNCTION__, __LINE__, novacom_usbll_getuid(handle->usbll_handle), rc, errno); while (rc <= 0 && !handle->shutdown) { //shutdown asap platform_get_time(&et); if (platform_delta_time_msecs(&st, &et) >= g_usbio_retry_timeout) { handle->shutdown = true; break; } if (g_usbio_retry_delay > 0) { if ((g_usbio_retry_timeout-time_used) >= g_usbio_retry_delay) { usleep(g_usbio_retry_delay * 1000); time_used += g_usbio_retry_delay; } else { usleep((g_usbio_retry_timeout - time_used) * 1000); time_used = g_usbio_retry_timeout; } } rc = novacom_usb_read(handle, buf, novacom_usbll_get_mtu(handle->usbll_handle)); count++; } TRACEL(LOG_ALWAYS, "%s:%d -- usbll(%08x) reading packet, reads(%ld), duration(%dms), result(%d), last_errno %ld\n", __FUNCTION__, __LINE__, novacom_usbll_getuid(handle->usbll_handle), count, platform_delta_time_msecs(&st, &et), rc, errno); count = 0; } /* sniff */ if(sniff) { uint32_t uid = ((handle->busnum & 0x0FFFF) << 16) | (handle->devnum & 0x0FFFF); transport_recovery_token_t sniff_token; int ret; /* generate token from packet */ ret = novacom_usbll_generate_recovery_token(buf, rc, &sniff_token); if(ret == -1) { TRACEL(LOG_ERROR, "%s:%d -- Used out system resouce, exit now !!!\n", __FUNCTION__, __LINE__); abort(); } /* check queue for saved connections */ ret = usbrecords_find(&sniff_token); /* free interface recovery token */ platform_free(sniff_token.token); /* check result: create new handle, or recover */ if(ret) { LTRACEF("Unable to recover(%d)\n", ret); handle->usbll_handle = novacom_usbll_create(handle->devtype, MAX_MTU, 0, USBDEVFS_IOCTL_TIMEOUT); } else { TRACEL(LOG_ERROR, "Recovered record...\n"); handle->usbll_handle = sniff_token.user_data; } /* update uid */ novacom_usbll_setuid(handle->usbll_handle, uid); handle->rx_timeout = novacom_usbll_get_timeout(handle->usbll_handle); handle->tx_timeout = novacom_usbll_get_timeout(handle->usbll_handle); sniff = 0; } /* process */ packet_type = PACKET_TYPE_NULL; if (rc > 0) { // process it packet_type = novacom_usbll_process_packet(handle->usbll_handle, buf, rc); if (packet_type == PACKET_TYPE_BADPACKET) { platform_time_t et; TRACEF("received bad packet\n"); platform_get_time(&et); if (platform_delta_time_msecs(&st, &et) >= g_usbio_retry_timeout) { handle->shutdown = true; break; } if (g_usbio_retry_delay > 0) { if ((g_usbio_retry_timeout-time_used) >= g_usbio_retry_delay) { usleep(g_usbio_retry_delay * 1000); time_used += g_usbio_retry_delay; } else { usleep((g_usbio_retry_timeout - time_used) * 1000); time_used = g_usbio_retry_timeout; } } ///handle->shutdown = true; ///break; } else if(handle->tx_startup_wait) { platform_event_signal(&handle->tx_startup_event); } } else { #if TRACE_ZERO_LEN_PACKETS log_printf(LOG_TRACE, "RX zero len\n"); #endif } } LTRACEF("shutting down handle %p\n", handle); /* wake up tx thread (if still waits for startup) */ if(handle->tx_startup_wait) { LTRACEF("wake up tx thread\n"); platform_event_signal(&handle->tx_startup_event); } /* wait for the tx thread to exit */ LTRACEF("waiting on tx thread\n"); platform_event_wait(&handle->tx_shutdown_event); /* RX thread is responsible for cleaning up */ LTRACEF("cleaning up handle %p\n", handle); /* grab recovery token if available */ if(handle->usbll_handle) { rc = -1; rec_token = platform_calloc(sizeof(transport_recovery_token_t)); if(rec_token) { snprintf(rec_token->nduid, sizeof(rec_token->nduid), "%s", novacom_usbll_get_nduid(handle->usbll_handle)); rc = novacom_usbll_get_recovery_token(handle->usbll_handle, rec_token); if(rc != -1) { rc = usbrecords_add(rec_token); } else { LTRACEF("unable to recovery token!!!\n"); } } /* error: free memory, destroy device */ if(rc == -1) { //we should never go here. novacom_usbll_destroy(handle->usbll_handle); platform_free(rec_token); } } novacom_usb_close(handle); platform_event_destroy(&handle->tx_startup_event); platform_event_destroy(&handle->tx_shutdown_event); platform_free(handle); platform_free(buf); return NULL; }
static void *novacom_usb_tx_thread(void *arg) { novacom_usb_handle_t *handle = (novacom_usb_handle_t *)arg; int rc; struct novacom_tx_packet packet; char *buf; buf = platform_calloc(MAX_MTU); platform_assert(buf != NULL); LTRACEF("start::wait for startup event: %p\n", handle); platform_event_wait(&handle->tx_startup_event); //why waiting rx for starting ??? handle->tx_startup_wait = 0; //change status to started LTRACEF("start::startup event received, continue: %p\n", handle); handle->tx_timeout = novacom_usbll_get_timeout(handle->usbll_handle); while (!novacom_shutdown && !handle->shutdown) { // see if we have something to send packet.len = novacom_usbll_get_mtu(handle->usbll_handle); packet.buf = buf; if (novacom_usbll_prepare_tx_packet(handle->usbll_handle, &packet, 100) != TX_NO_PACKET) { // write a block back #if FAULTY_TX if (rand() < (RAND_MAX / 10)) { TRACEF("dropped tx packet\n"); } else { #endif rc = novacom_usb_write(handle, packet.buf, packet.len); if (rc < 0) { platform_time_t st; platform_time_t et; int time_used = 0; unsigned int count = 0; TRACEL(LOG_ALWAYS, "usbll(%08x) error writing packet, result(%d), errno %d\n", novacom_usbll_getuid(handle->usbll_handle), rc, errno); platform_get_time(&st); while (rc < 0 && !handle->shutdown) { //shutdown asap platform_get_time(&et); if (platform_delta_time_msecs(&st, &et) >= g_usbio_retry_timeout) { handle->shutdown = true; break; } if (g_usbio_retry_delay > 0) { if ((g_usbio_retry_timeout-time_used) >= g_usbio_retry_delay) { usleep(g_usbio_retry_delay * 1000); time_used += g_usbio_retry_delay; } else { usleep((g_usbio_retry_timeout - time_used) * 1000); time_used = g_usbio_retry_timeout; } } rc = novacom_usb_write(handle, packet.buf, packet.len); count++; } TRACEL(LOG_ALWAYS, "usbll(%08x) writing packet, writes(%ld), duration(%dms), result(%d), last_errno %ld\n", novacom_usbll_getuid(handle->usbll_handle), count, platform_delta_time_msecs(&st, &et), rc, errno); count = 0; } if (rc >=0) { TRACEF/*LOG_PRINTF*/("usbll(%08x) wrote tx packet len=%d\n", novacom_usbll_getuid(handle->usbll_handle), rc); } #if FAULTY_TX } #endif } } LTRACEF("shutting down handle %p\n", handle); platform_event_signal(&handle->tx_shutdown_event); platform_free(buf); return NULL; }
static novacom_usb_handle_t *novacom_usb_open( void ) { int rc; // usb_set_debug(100); rc = usb_find_busses(); if (rc < 0) return NULL; rc = usb_find_devices(); if (rc < 0) return NULL; struct usb_bus *bus; struct usb_device *dev; for (bus = usb_get_busses(); bus; bus = bus->next) { for (dev = bus->devices; dev; dev = dev->next) { #if USB_SCAN_TRACE log_printf(LOG_SPEW, "looking at dev %d (%s) %04x:%04x\n", dev->devnum, dev->filename, dev->descriptor.idVendor, dev->descriptor.idProduct); #endif /* try to match against our list of vendor/products */ uint i; for (i=0; usbid_list[i].name; i++) { if ((dev->descriptor.idVendor == usbid_list[i].vendor) && (dev->descriptor.idProduct == usbid_list[i].product)) { usb_dev_handle *handle = usb_open(dev); if (!handle) continue; #if USB_SCAN_TRACE log_printf(LOG_SPEW, "opened usb handle: devnum %d\n", dev->devnum); #endif int eps[2]; int iface = -1; rc = novacom_usb_find_endpoints(handle, eps, &iface); if (rc != 0) { usb_close(handle); continue; } LTRACEF("got endpoints: %x, %x\n", eps[0], eps[1]); novacom_usb_handle_t *usb_handle = platform_calloc(sizeof(novacom_usb_handle_t)); if(!usb_handle) { return NULL; } usb_handle->handle = handle; usb_handle->rxep = eps[0]; usb_handle->txep = eps[1]; usb_handle->devtype = usbid_list[i].name; usb_handle->busnum = atoi(dev->bus->dirname); usb_handle->devnum = dev->devnum; usb_handle->iface = iface; return usb_handle; } } } } return NULL; }