void * tcp_recv_loop(void *recv_pkt) { PACKET rpkt; int acpt_idx, acpt_sidx; acpt_idx = accept_idx; acpt_sidx = accept_sidx; memcpy(&rpkt, recv_pkt, sizeof(PACKET)); pthread_mutex_unlock(&tcp_exec_lock); #if 0 add_accept_pid(getpid(), acpt_idx, acpt_sidx); #endif while (pkt_recv(&rpkt) != -1) { if (pkt_exec(rpkt, acpt_idx) < 0) { goto close; break; } else pkt_free(&rpkt, 0); } close: pkt_free(&rpkt, 1); close_accept(acpt_idx, acpt_sidx); return NULL; }
int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Prepare packet pkt_init(pkt, UsbInterruptRead); pkt_addint(pkt, dev->fd); pkt_addint(pkt, ep); pkt_addint(pkt, size); pkt_addint(pkt, timeout); pkt_send(pkt, fd); // Get response int res = -1; if(pkt_recv(fd, pkt) > 0 && pkt_op(pkt) == UsbInterruptRead) { Iterator it; pkt_begin(pkt, &it); res = iter_getint(&it); if(res > 0) { int minlen = (res > size) ? size : res; memcpy(bytes, it.val, minlen); } } // Return response pkt_release(); debug_msg("returned %d", res); return res; }
int usb_get_driver_np(usb_dev_handle *dev, int interface, char *name, unsigned int namelen) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Send packet pkt_init(pkt, UsbGetKernelDriver); pkt_addint(pkt, dev->fd); pkt_addint(pkt, interface); pkt_adduint(pkt, namelen); pkt_send(pkt, fd); // Get response int res = -1; if(pkt_recv(fd, pkt) > 0 && pkt_op(pkt) == UsbGetKernelDriver) { Iterator it; pkt_begin(pkt, &it); res = iter_getint(&it); // Error if(res) { error_msg("%s: could not get bound driver", __func__); } // Save string strncpy(name, iter_getstr(&it), namelen - 1); name[namelen - 1] = '\0'; } pkt_release(); debug_msg("returned %d (%s)", res, name); return res; }
int usb_set_altinterface(usb_dev_handle *dev, int alternate) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Prepare packet pkt_init(pkt, UsbSetAltInterface); pkt_addint(pkt, dev->fd); pkt_addint(pkt, alternate); pkt_send(pkt, fd); // Get response int res = -1; if(pkt_recv(fd, pkt) > 0 && pkt_op(pkt) == UsbSetAltInterface) { Iterator it; pkt_begin(pkt, &it); // Read result res = iter_getint(&it); // Read callback configuration alternate = iter_getint(&it); } // Save configuration dev->altsetting = alternate; // Return response pkt_release(); debug_msg("returned %d", res); return res; }
/* libusb(5): * Interrupt transfers. */ int usb_interrupt_write(usb_dev_handle *dev, int ep, usb_buf_t bytes, int size, int timeout) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Prepare packet pkt_init(pkt, UsbInterruptWrite); pkt_addint(pkt, dev->fd); pkt_addint(pkt, ep); pkt_addstr(pkt, size, bytes); pkt_addint(pkt, timeout); pkt_send(pkt, fd); // Get response int res = -1; if(pkt_recv(fd, pkt) > 0 && pkt_op(pkt) == UsbInterruptWrite) { Iterator it; pkt_begin(pkt, &it); res = iter_getint(&it); } // Return response pkt_release(); debug_msg("returned %d", res); return res; }
int usb_reset(usb_dev_handle *dev) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Prepare packet pkt_init(pkt, UsbReset); pkt_addint(pkt, dev->fd); pkt_send(pkt, fd); // Get response int res = -1; if(pkt_recv(fd, pkt) > 0 && pkt_op(pkt) == UsbReset) { Iterator it; pkt_begin(pkt, &it); // Read result res = iter_getint(&it); } // Return response pkt_release(); debug_msg("returned %d", res); return res; }
int usb_close(usb_dev_handle *dev) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Send packet pkt_init(pkt, UsbClose); pkt_addint(pkt, dev->fd); pkt_send(pkt, fd); // Free device free(dev); // Get response int res = -1; if(pkt_recv(fd, pkt) > 0 && pkt_op(pkt) == UsbClose) { Iterator it; pkt_begin(pkt, &it); res = iter_getint(&it); } pkt_release(); debug_msg("returned %d", res); return res; }
usb_dev_handle *usb_open(struct usb_device *dev) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Send packet pkt_init(pkt, UsbOpen); pkt_adduint(pkt, dev->bus->location); pkt_adduint(pkt, dev->devnum); pkt_send(pkt, fd); // Get response int res = -1, devfd = -1; if(pkt_recv(fd, pkt) > 0 && pkt_op(pkt) == UsbOpen) { Iterator it; pkt_begin(pkt, &it); res = iter_getint(&it); devfd = iter_getint(&it); } // Evaluate usb_dev_handle* udev = NULL; if(res >= 0) { udev = malloc(sizeof(usb_dev_handle)); udev->fd = devfd; udev->device = dev; udev->bus = dev->bus; udev->config = udev->interface = udev->altsetting = -1; } pkt_release(); debug_msg("returned %d (fd %d)", res, devfd); return udev; }
static int __mpkt_recv(unsigned int type, struct lo_packet **putback, bool list_retrieval) { const struct ccgfs_pkt_header *hdr; struct lo_packet *pkt; pkt = pkt_recv(in_fd); if (!list_retrieval) pthread_mutex_unlock(&net_lock); if (pkt == NULL) { fprintf(stderr, "%s: %s\n", __func__, strerror(errno)); pthread_kill(main_thread_id, SIGTERM); return -ENOTCONN; } hdr = pkt->data; if (hdr->opcode == CCGFS_ERRNO_RESPONSE) { int32_t ret = pkt_shift_32(pkt); pkt_destroy(pkt); /* May happen as a result of a write() */ if (ret >= 0) return ret; return arch_errno(ret); } if (hdr->opcode != type) { pkt_destroy(pkt); *putback = NULL; return -EIO; } *putback = pkt; return list_retrieval; }
int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Prepare packet pkt_init(pkt, UsbControlMsg); pkt_addint(pkt, dev->fd); pkt_addint(pkt, requesttype); pkt_addint(pkt, request); pkt_addint(pkt, value); pkt_addint(pkt, index); pkt_addstr(pkt, size, bytes); pkt_addint(pkt, timeout); pkt_send(pkt, fd); // Get response int res = -1; if(pkt_recv(fd, pkt) > 0 && pkt_op(pkt) == UsbControlMsg) { Iterator it; pkt_begin(pkt, &it); res = iter_getint(&it); if(res > 0) { int minlen = (res > size) ? size : res; memcpy(bytes, it.val, minlen); } } // Return response pkt_release(); debug_msg("returned %d", res); return res; }
int usb_detach_kernel_driver_np(usb_dev_handle *dev, int interface) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Send packet pkt_init(pkt, UsbDetachKernelDriver); pkt_addint(pkt, dev->fd); pkt_addint(pkt, interface); pkt_send(pkt, fd); // Get response int res = -1; if(pkt_recv(fd, pkt) > 0 && pkt_op(pkt) == UsbDetachKernelDriver) { Iterator it; pkt_begin(pkt, &it); res = iter_getint(&it); } pkt_release(); debug_msg("returned %d", res); return res; }
/** Find busses on remote host. \warning Does not transfer busses to local virtual bus list. */ int usb_find_busses(void) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Initialize pkt pkt_init(pkt, UsbFindBusses); pkt_send(pkt, fd); // Get number of changes int res = 0; Iterator it; if(pkt_recv(fd, pkt) > 0 && pkt_op(pkt) == UsbFindBusses) { if(pkt_begin(pkt, &it) != NULL) { res = iter_getint(&it); } } // Return remote result pkt_release(); debug_msg("returned %d", res); return res; }
/* * udp_daemon: Takes care of receiving udp packets. * `passed_argv' is a pointer to a udp_daemon_argv struct */ void * udp_daemon(void *passed_argv) { struct udp_daemon_argv argv; struct udp_exec_pkt_argv exec_pkt_argv; interface *ifs; int max_sk_idx, dev_sk[me.cur_ifs_n]; PACKET rpkt; fd_set fdset; int ret, i, err; u_short udp_port; pthread_t thread; pthread_attr_t t_attr; #ifdef DEBUG int select_errors = 0; #endif memcpy(&argv, passed_argv, sizeof(struct udp_daemon_argv)); udp_port = argv.port; setzero(&exec_pkt_argv, sizeof(struct udp_exec_pkt_argv)); if (argv.flags & UDP_THREAD_FOR_EACH_PKT) { pthread_attr_init(&t_attr); pthread_attr_setdetachstate(&t_attr, PTHREAD_CREATE_DETACHED); exec_pkt_argv.flags |= UDP_THREAD_FOR_EACH_PKT; } debug(DBG_SOFT, "Preparing the udp listening socket on port %d", udp_port); err = sockets_all_ifs(my_family, SOCK_DGRAM, udp_port, me.cur_ifs, me.cur_ifs_n, dev_sk, &max_sk_idx); if (!err) return NULL; else if (err < 0) fatal("Creation of the %s daemon aborted. " "Is there another ntkd running?", "udp"); debug(DBG_NORMAL, "Udp daemon on port %d up & running", udp_port); pthread_mutex_unlock(&udp_daemon_lock); pthread_mutex_init(&udp_exec_lock, 0); for (;;) { FD_ZERO(&fdset); if (!me.cur_ifs_n) { /* All the devices have been removed while ntkd was * running, sleep well */ sleep(1); continue; } for (i = 0; i < me.cur_ifs_n; i++) if (dev_sk[i]) FD_SET(dev_sk[i], &fdset); ret = select(dev_sk[max_sk_idx] + 1, &fdset, NULL, NULL, NULL); if (sigterm_timestamp) /* NetsukukuD has been closed */ break; if (ret < 0) { #ifdef DEBUG if (select_errors > 20) break; select_errors++; #endif error("daemon_udp: select error: %s", strerror(errno)); continue; } for (i = 0; i < me.cur_ifs_n; i++) { ifs = &me.cur_ifs[i]; if (!dev_sk[i]) continue; if (!FD_ISSET(dev_sk[i], &fdset)) continue; setzero(&rpkt, sizeof(PACKET)); pkt_addsk(&rpkt, my_family, dev_sk[i], SKT_UDP); pkt_add_dev(&rpkt, ifs, 0); rpkt.flags = MSG_WAITALL; pkt_addport(&rpkt, udp_port); if (pkt_recv(&rpkt) < 0) { pkt_free(&rpkt, 0); continue; } exec_pkt_argv.acpt_idx = accept_idx; exec_pkt_argv.acpt_sidx = accept_sidx; if (argv.flags & UDP_THREAD_FOR_EACH_PKT) { exec_pkt_argv.recv_pkt = &rpkt; pthread_mutex_lock(&udp_exec_lock); pthread_create(&thread, &t_attr, udp_exec_pkt, &exec_pkt_argv); pthread_mutex_lock(&udp_exec_lock); pthread_mutex_unlock(&udp_exec_lock); } else { exec_pkt_argv.recv_pkt = &rpkt; udp_exec_pkt(&exec_pkt_argv); } } } destroy_accept_tbl(); return NULL; }
/** Find devices on remote host. * Create new devices on local virtual bus. * \warning Function replaces global usb_busses variable from libusb. */ int usb_find_devices(void) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Create buffer pkt_init(pkt, UsbFindDevices); pkt_send(pkt, fd); // Get number of changes int res = 0; Iterator it; if(pkt_recv(fd, pkt) > 0) { pkt_begin(pkt, &it); // Get return value res = iter_getint(&it); // Allocate virtualbus struct usb_bus vbus; vbus.next = __remote_bus; struct usb_bus* rbus = &vbus; // Get busses while(!iter_end(&it)) { // Evaluate if(it.type == StructureType) { iter_enter(&it); // Allocate bus if(rbus->next == NULL) { // Allocate next item struct usb_bus* nbus = malloc(sizeof(struct usb_bus)); memset(nbus, 0, sizeof(struct usb_bus)); rbus->next = nbus; nbus->prev = rbus; rbus = nbus; } else rbus = rbus->next; // Read dirname strcpy(rbus->dirname, iter_getstr(&it)); // Read location rbus->location = iter_getuint(&it); // Read devices struct usb_device vdev; vdev.next = rbus->devices; struct usb_device* dev = &vdev; while(it.type == SequenceType) { iter_enter(&it); // Initialize if(dev->next == NULL) { dev->next = malloc(sizeof(struct usb_device)); memset(dev->next, 0, sizeof(struct usb_device)); dev->next->bus = rbus; if(dev != &vdev) dev->next->prev = dev; if(rbus->devices == NULL) rbus->devices = dev->next; } dev = dev->next; // Read filename strcpy(dev->filename, iter_getstr(&it)); // Read devnum dev->devnum = iter_getuint(&it); // Read descriptor // Apply byte-order conversion for 16/32bit integers memcpy(&dev->descriptor, it.val, it.len); dev->descriptor.bcdUSB = ntohs(dev->descriptor.bcdUSB); dev->descriptor.idVendor = ntohs(dev->descriptor.idVendor); dev->descriptor.idProduct = ntohs(dev->descriptor.idProduct); dev->descriptor.bcdDevice = ntohs(dev->descriptor.bcdDevice); iter_next(&it); // Alloc configurations unsigned cfgid = 0, cfgnum = dev->descriptor.bNumConfigurations; dev->config = NULL; if(cfgnum > 0) { dev->config = malloc(cfgnum * sizeof(struct usb_config_descriptor)); memset(dev->config, 0, cfgnum * sizeof(struct usb_config_descriptor)); } // Read config while(it.type == RawType && cfgid < cfgnum) { struct usb_config_descriptor* cfg = &dev->config[cfgid]; ++cfgid; // Ensure struct under/overlap int szlen = sizeof(struct usb_config_descriptor); if(szlen > it.len) szlen = it.len; // Read config and apply byte-order conversion memcpy(cfg, it.val, szlen); cfg->wTotalLength = ntohs(cfg->wTotalLength); // Allocate interfaces cfg->interface = NULL; if(cfg->bNumInterfaces > 0) { cfg->interface = malloc(cfg->bNumInterfaces * sizeof(struct usb_interface)); } //! \test Implement usb_device extra interfaces - are they needed? cfg->extralen = 0; cfg->extra = NULL; iter_next(&it); // Load interfaces unsigned i, j, k; for(i = 0; i < cfg->bNumInterfaces; ++i) { struct usb_interface* iface = &cfg->interface[i]; // Read altsettings count iface->num_altsetting = iter_getint(&it); // Allocate altsettings if(iface->num_altsetting > 0) { iface->altsetting = malloc(iface->num_altsetting * sizeof(struct usb_interface_descriptor)); } // Load altsettings for(j = 0; j < iface->num_altsetting; ++j) { // Ensure struct under/overlap struct usb_interface_descriptor* as = &iface->altsetting[j]; int szlen = sizeof(struct usb_interface_descriptor); if(szlen > it.len) szlen = it.len; // Read altsettings - no conversions apply memcpy(as, it.val, szlen); iter_next(&it); // Allocate endpoints as->endpoint = NULL; if(as->bNumEndpoints > 0) { size_t epsize = as->bNumEndpoints * sizeof(struct usb_endpoint_descriptor); as->endpoint = malloc(epsize); memset(as->endpoint, 0, epsize); } // Load endpoints for(k = 0; k < as->bNumEndpoints; ++k) { struct usb_endpoint_descriptor* endpoint = &as->endpoint[k]; int szlen = sizeof(struct usb_endpoint_descriptor); if(szlen > it.len) szlen = it.len; // Read endpoint and apply conversion memcpy(endpoint, it.val, szlen); endpoint->wMaxPacketSize = ntohs(endpoint->wMaxPacketSize); iter_next(&it); // Null extra descriptors. endpoint->extralen = 0; endpoint->extra = NULL; } // Read extra interface descriptors as->extralen = as_int(it.val, it.len); iter_next(&it); if(as->extralen > 0){ as->extra = malloc(as->extralen); int szlen = as->extralen; if(szlen > it.len) szlen = it.len; memcpy(as->extra, it.val, szlen); iter_next(&it); } else as->extra = NULL; } } } //log_msg("Bus %s Device %s: ID %04x:%04x", rbus->dirname, dev->filename, dev->descriptor.idVendor, dev->descriptor.idProduct); } // Free unused devices while(dev->next != NULL) { struct usb_device* ddev = dev->next; debug_msg("deleting device %03d", ddev->devnum); dev->next = ddev->next; free(ddev); } } else { debug_msg("unexpected item identifier 0x%02x", it.type); iter_next(&it); } } // Deallocate unnecessary busses while(rbus->next != NULL) { debug_msg("deleting bus %03d", rbus->next->location); struct usb_bus* bus = rbus->next; rbus->next = bus->next; } // Save busses if(__remote_bus == NULL) { __orig_bus = usb_busses; debug_msg("overriding global usb_busses from %p to %p", usb_busses, vbus.next); } __remote_bus = vbus.next; usb_busses = __remote_bus; } // Return remote result pkt_release(); debug_msg("returned %d", res); return res; }
int nmrp_do(struct nmrpd_args *args) { struct nmrp_pkt tx, rx; uint8_t *src, dest[6]; uint16_t len, region; char *filename; time_t beg; int i, status, ulreqs, expect, upload_ok, autoip; struct ethsock *sock; uint32_t intf_addr; void (*sigh_orig)(int); struct { struct in_addr addr; struct in_addr mask; } PACKED ipconf; if (args->op != NMRP_UPLOAD_FW) { fprintf(stderr, "Operation not implemented.\n"); return 1; } if (!mac_parse(args->mac, dest)) { fprintf(stderr, "Invalid MAC address '%s'.\n", args->mac); return 1; } if ((ipconf.mask.s_addr = inet_addr(args->ipmask)) == INADDR_NONE) { fprintf(stderr, "Invalid subnet mask '%s'.\n", args->ipmask); return 1; } if (!args->ipaddr) { autoip = true; /* The MAC of the device that was used to test this utility starts * with a4:2b:8c, hence 164 (0xa4) and 183 (0x2b + 0x8c) */ args->ipaddr = "10.164.183.252"; if (!args->ipaddr_intf) { args->ipaddr_intf = "10.164.183.253"; } } else if (args->ipaddr_intf) { autoip = true; } else { autoip = false; } if ((ipconf.addr.s_addr = inet_addr(args->ipaddr)) == INADDR_NONE) { fprintf(stderr, "Invalid IP address '%s'.\n", args->ipaddr); return 1; } if (args->ipaddr_intf && (intf_addr = inet_addr(args->ipaddr_intf)) == INADDR_NONE) { fprintf(stderr, "Invalid IP address '%s'.\n", args->ipaddr_intf); return 1; } if (args->file_local && strcmp(args->file_local, "-") && access(args->file_local, R_OK) == -1) { fprintf(stderr, "Error accessing file '%s'.\n", args->file_local); return 1; } if (args->file_remote) { if (!tftp_is_valid_filename(args->file_remote)) { fprintf(stderr, "Invalid remote filename '%s'.\n", args->file_remote); return 1; } } if (args->region) { region = htons(to_region_code(args->region)); if (!region) { fprintf(stderr, "Invalid region code '%s'.\n", args->region); return 1; } } else { region = 0; } status = 1; sock = ethsock_create(args->intf, ETH_P_NMRP); if (!sock) { return 1; } gsock = sock; garp = 0; sigh_orig = signal(SIGINT, sigh); if (!autoip) { status = is_valid_ip(sock, &ipconf.addr, &ipconf.mask); if (status <= 0) { if (!status) { fprintf(stderr, "Address %s/%s cannot be used on interface %s.\n", args->ipaddr, args->ipmask, args->intf); } goto out; } } else { if (verbosity) { printf("Adding %s to interface %s.\n", args->ipaddr_intf, args->intf); } if (ethsock_ip_add(sock, intf_addr, ipconf.mask.s_addr, &gundo) != 0) { goto out; } } if (ethsock_set_timeout(sock, args->rx_timeout)) { goto out; } src = ethsock_get_hwaddr(sock); if (!src) { goto out; } memcpy(tx.eh.ether_shost, src, 6); memcpy(tx.eh.ether_dhost, dest, 6); tx.eh.ether_type = htons(ETH_P_NMRP); msg_init(&tx.msg, NMRP_C_ADVERTISE); msg_opt_add(&tx.msg, NMRP_O_MAGIC_NO, "NTGR", 4); msg_hton(&tx.msg); i = 0; upload_ok = 0; beg = time(NULL); while (1) { printf("\rAdvertising NMRP server on %s ... %c", args->intf, spinner[i]); fflush(stdout); i = (i + 1) & 3; if (pkt_send(sock, &tx) < 0) { perror("sendto"); goto out; } status = pkt_recv(sock, &rx); if (status == 0 && memcmp(rx.eh.ether_dhost, src, 6) == 0) { break; } else if (status == 1) { goto out; } else { if ((time(NULL) - beg) >= 60) { printf("\nNo response after 60 seconds. Bailing out.\n"); goto out; } } } printf("\n"); expect = NMRP_C_CONF_REQ; ulreqs = 0; do { if (expect != NMRP_C_NONE && rx.msg.code != expect) { fprintf(stderr, "Received %s while waiting for %s!\n", msg_code_str(rx.msg.code), msg_code_str(expect)); } msg_init(&tx.msg, NMRP_C_NONE); status = 1; switch (rx.msg.code) { case NMRP_C_ADVERTISE: printf("Received NMRP advertisement from %s.\n", mac_to_str(rx.eh.ether_shost)); status = 1; goto out; case NMRP_C_CONF_REQ: tx.msg.code = NMRP_C_CONF_ACK; msg_opt_add(&tx.msg, NMRP_O_DEV_IP, &ipconf, 8); msg_opt_add(&tx.msg, NMRP_O_FW_UP, NULL, 0); #ifdef NMRPFLASH_SET_REGION if (region) { msg_opt_add(&tx.msg, NMRP_O_DEV_REGION, ®ion, 2); } #endif expect = NMRP_C_TFTP_UL_REQ; printf("Received configuration request from %s.\n", mac_to_str(rx.eh.ether_shost)); memcpy(tx.eh.ether_dhost, rx.eh.ether_shost, 6); printf("Sending configuration: ip %s, mask %s.\n", args->ipaddr, args->ipmask); memcpy(arpmac, rx.eh.ether_shost, 6); memcpy(&arpip, &ipconf.addr, sizeof(ipconf.addr)); if (ethsock_arp_add(sock, arpmac, &arpip) != 0) { goto out; } garp = 1; break; case NMRP_C_TFTP_UL_REQ: if (!upload_ok) { if (++ulreqs > 5) { printf("Bailing out after %d upload requests.\n", ulreqs); tx.msg.code = NMRP_C_CLOSE_REQ; break; } } else { if (verbosity) { printf("Ignoring extra upload request.\n"); } ethsock_set_timeout(sock, args->ul_timeout); tx.msg.code = NMRP_C_KEEP_ALIVE_REQ; break; } len = 0; filename = msg_opt_data(&rx.msg, NMRP_O_FILE_NAME, &len); if (filename) { if (!args->file_remote) { args->file_remote = filename; } printf("Received upload request: filename '%.*s'.\n", len, filename); } else if (!args->file_remote) { args->file_remote = args->file_local; printf("Received upload request with empty filename.\n"); } status = 0; if (args->tftpcmd) { printf("Executing '%s' ... \n", args->tftpcmd); setenv("IP", inet_ntoa(ipconf.addr), 1); setenv("MAC", mac_to_str(rx.eh.ether_shost), 1); setenv("NETMASK", inet_ntoa(ipconf.mask), 1); status = system(args->tftpcmd); } if (!status && args->file_local) { if (!autoip) { status = is_valid_ip(sock, &ipconf.addr, &ipconf.mask); if (status < 0) { goto out; } else if (!status) { printf("IP address of %s has changed. Please assign a " "static ip to the interface.\n", args->intf); tx.msg.code = NMRP_C_CLOSE_REQ; break; } } if (verbosity) { printf("Using remote filename '%s'.\n", args->file_remote); } if (!strcmp(args->file_local, "-")) { printf("Uploading from stdin ... "); } else { printf("Uploading %s ... ", leafname(args->file_local)); } fflush(stdout); status = tftp_put(args); } if (!status) { printf("OK\nWaiting for remote to respond.\n"); upload_ok = 1; ethsock_set_timeout(sock, args->ul_timeout); tx.msg.code = NMRP_C_KEEP_ALIVE_REQ; expect = NMRP_C_NONE; } else if (status == -2) { expect = NMRP_C_TFTP_UL_REQ; } else { goto out; } break; case NMRP_C_KEEP_ALIVE_REQ: tx.msg.code = NMRP_C_KEEP_ALIVE_ACK; ethsock_set_timeout(sock, args->ul_timeout); printf("Received keep-alive request.\n"); break; case NMRP_C_CLOSE_REQ: tx.msg.code = NMRP_C_CLOSE_ACK; break; case NMRP_C_CLOSE_ACK: status = 0; goto out; default: fprintf(stderr, "Unknown message code 0x%02x!\n", rx.msg.code); msg_dump(&rx.msg, 0); } if (tx.msg.code != NMRP_C_NONE) { msg_hton(&tx.msg); if (pkt_send(sock, &tx) < 0) { perror("sendto"); goto out; } if (tx.msg.code == NMRP_C_CLOSE_REQ) { goto out; } } if (rx.msg.code == NMRP_C_CLOSE_REQ) { printf("Remote finished. Closing connection.\n"); break; } status = pkt_recv(sock, &rx); if (status) { if (status == 2) { fprintf(stderr, "Timeout while waiting for %s.\n", msg_code_str(expect)); } goto out; } ethsock_set_timeout(sock, args->rx_timeout); } while (1); status = 0; if (ulreqs) { printf("Reboot your device now.\n"); } else { printf("No upload request received.\n"); } out: signal(SIGINT, sigh_orig); gsock = NULL; ethsock_arp_del(sock, arpmac, &arpip); ethsock_ip_del(sock, &gundo); ethsock_close(sock); return status; }