// forced == 1 static void socksserver_disconnect_client(socksserver* srv, int fd, int forced) { fdinfo* client = &srv->clients[fdindex(fd)]; int fdflag = 0; if(CONFIG_LOG && srv->log) { logstart(); printfd(fd); LOGPUT(1, VARISL(" disconnect, forced: "), VARII(forced), NULL); } if(forced) rocksockserver_disconnect_client(&srv->serva, fd); client->state = SS_DISCONNECTED; if(client->data) { client->data->state = BS_UNUSED; client->data->start = 0; client->data->used = 0; } if(client->target_fd != -1) fdflag = 1; fd = client->target_fd; client->target_fd = -1; if(fdflag) { srv->clients[fdindex(fd)].target_fd = -1; socksserver_disconnect_client(srv, fd, 1); } }
static int socksserver_on_clientconnect (void* userdata, struct sockaddr_storage* clientaddr, int fd) { socksserver* srv = (socksserver*) userdata; char buffer[256]; (void) buffer; if(CONFIG_LOG && srv->log && clientaddr) { logstart(); printfd(fd); LOGPUT(1, VARISL(" connect from: "), VARIC(get_client_ip(clientaddr, buffer, sizeof(buffer))), NULL); } if(fd < 3 || fd >= MAX_FD) { rocksockserver_disconnect_client(&srv->serva, fd); return -2; } fdinfo* client = &srv->clients[fdindex(fd)]; // put into nonblocking mode, so that writes will not block the server int flags = fcntl(fd, F_GETFL); if(flags == -1) return -1; if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) return -2; client->data = find_free_buffer(srv); if (!client->data) { if(CONFIG_LOG && srv->log) { logstart(); LOGPUTS(1, SPL("warning: couldnt find free buffer\n")); } rocksockserver_disconnect_client(&srv->serva, fd); return -2; } client->state = SS_CONNECTED; client->data->state = BS_IDLE; client->data->start = 0; client->target_fd = -1; return 0; }
void ttLogStart(int logID) { UserTask* usertask; if (logID < 1 || logID > NBRUSERLOGS) { MEX_ERROR("ttLogStart: Log ID out of bounds!"); return; } if (rtsys->running->isUserTask()) { usertask = (UserTask*) rtsys->running; logstart(usertask, logID+5); // 5 pre-defined log types } else { printf("ttLogStart: Call from interrupt handler ignored!\n"); return; } }
static int chanio(Ep *ep, Hostchan *hc, int dir, int pid, void *a, int len) { Ctlr *ctlr; int nleft, n, nt, i, maxpkt, npkt; uint hcdma, hctsiz; ctlr = ep->hp->aux; maxpkt = ep->maxpkt; npkt = HOWMANY(len, ep->maxpkt); if(npkt == 0) npkt = 1; hc->hcchar = (hc->hcchar & ~Epdir) | dir; if(dir == Epin) n = ROUND(len, ep->maxpkt); else n = len; hc->hctsiz = n | npkt<<OPktcnt | pid; hc->hcdma = dmaaddr(a); nleft = len; logstart(ep); for(;;){ hcdma = hc->hcdma; hctsiz = hc->hctsiz; hc->hctsiz = hctsiz & ~Dopng; if(hc->hcchar&Chen){ dprint("ep%d.%d before chanio hcchar=%8.8ux\n", ep->dev->nb, ep->nb, hc->hcchar); hc->hcchar |= Chen | Chdis; while(hc->hcchar&Chen) ; hc->hcint = Chhltd; } if((i = hc->hcint) != 0){ dprint("ep%d.%d before chanio hcint=%8.8ux\n", ep->dev->nb, ep->nb, i); hc->hcint = i; } if(hc->hcsplt & Spltena){ qlock(&ctlr->split); sofwait(ctlr, hc - ctlr->regs->hchan); if((dwc.regs->hfnum & 1) == 0) hc->hcchar &= ~Oddfrm; else hc->hcchar |= Oddfrm; } hc->hcchar = (hc->hcchar &~ Chdis) | Chen; clog(ep, hc); wait: if(ep->ttype == Tbulk && dir == Epin) i = chanwait(ep, ctlr, hc, Chhltd); else if(ep->ttype == Tintr && (hc->hcsplt & Spltena)) i = chanwait(ep, ctlr, hc, Chhltd); else i = chanwait(ep, ctlr, hc, Chhltd|Nak); clog(ep, hc); if(hc->hcint != i){ dprint("chanwait intr %ux->%ux\n", i, hc->hcint); if((i = hc->hcint) == 0) goto wait; } hc->hcint = i; if(hc->hcsplt & Spltena){ hc->hcsplt &= ~Compsplt; qunlock(&ctlr->split); } if((i & Xfercomp) == 0 && i != (Chhltd|Ack) && i != Chhltd){ if(i & Stall) error(Estalled); if(i & (Nyet|Frmovrun)) continue; if(i & Nak){ if(ep->ttype == Tintr) tsleep(&up->sleep, return0, 0, ep->pollival); else tsleep(&up->sleep, return0, 0, 1); continue; } logdump(ep); print("usbotg: ep%d.%d error intr %8.8ux\n", ep->dev->nb, ep->nb, i); if(i & ~(Chhltd|Ack)) error(Eio); if(hc->hcdma != hcdma) print("usbotg: weird hcdma %ux->%ux intr %ux->%ux\n", hcdma, hc->hcdma, i, hc->hcint); } n = hc->hcdma - hcdma; if(n == 0){ if((hc->hctsiz & Pktcnt) != (hctsiz & Pktcnt)) break; else continue; } if(dir == Epin && ep->ttype == Tbulk){ nt = (hctsiz & Xfersize) - (hc->hctsiz & Xfersize); if(nt != n){ if(n == ROUND(nt, 4)) n = nt; else print("usbotg: intr %8.8ux " "dma %8.8ux-%8.8ux " "hctsiz %8.8ux-%8.ux\n", i, hcdma, hc->hcdma, hctsiz, hc->hctsiz); } } if(n > nleft){ if(n != ROUND(nleft, 4)) dprint("too much: wanted %d got %d\n", len, len - nleft + n); n = nleft; } nleft -= n; if(nleft == 0 || (n % maxpkt) != 0) break; if((i & Xfercomp) && ep->ttype != Tctl) break; if(dir == Epout) dprint("too little: nleft %d hcdma %x->%x hctsiz %x->%x intr %x\n", nleft, hcdma, hc->hcdma, hctsiz, hc->hctsiz, i); } logdump(ep); return len - nleft; }
static int socksserver_connect_request(socksserver* srv, int fd) { fdinfo* client = &srv->clients[fdindex(fd)]; size_t i = 0; unsigned char dlen = 0; unsigned char* buf = client->data->buf; int flags, ret; host_info addr; struct addrinfo addrbuf; struct sockaddr sockbuf; memset(&addr, 0, sizeof(addr)); memset(&addrbuf, 0, sizeof(addrbuf)); memset(&sockbuf, 0, sizeof(sockbuf)); addrbuf.ai_addr = &sockbuf; addr.hostaddr = &addrbuf; if(!client->data->start) return -1; if(buf[i++] != 5) return EC_NOT_ALLOWED; // check first byte whenever the message length is > 0 to not waste resources on maldoers if(client->data->start < 1+1+1+1+4+2) return -1; if(buf[i++] != 1) return EC_COMMAND_NOT_SUPPORTED; // we support only the connect method. if(buf[i++] != 0) return EC_GENERAL_FAILURE; switch(buf[i++]) { case 1: //ipv4 memcpy(&((struct sockaddr_in*) addr.hostaddr->ai_addr)->sin_addr, buf + 4, 4); memcpy(&((struct sockaddr_in*) addr.hostaddr->ai_addr)->sin_port, buf + 8, 2); ((struct sockaddr_in*) addr.hostaddr->ai_addr)->sin_family = PF_INET; addr.hostaddr->ai_addr->sa_family = PF_INET; addr.hostaddr->ai_addrlen = sizeof(struct sockaddr_in); break; case 3: //dns if(CONFIG_DNS) { dlen = buf[i++]; if(client->data->start < 1U+1U+1U+1U+1U+dlen+2U) return -1; addr.port = my_ntohs(buf + i + dlen); buf[i + dlen] = 0; addr.host = (char*) (buf + i); if(CONFIG_IPV6) addr.hostaddr = NULL; if(!resolve_host(&addr)) { if(CONFIG_IPV6) { memcpy(&addrbuf, addr.hostaddr, sizeof(struct addrinfo)); freeaddrinfo(addr.hostaddr); addr.hostaddr = &addrbuf; } } else goto notsupported; break; } else goto notsupported; case 4: //ipv6 if(CONFIG_IPV6) { if(client->data->start < 1+1+1+1+16+2) return -1; memcpy(&((struct sockaddr_in6*) addr.hostaddr->ai_addr)->sin6_addr, buf + 4, 16); memcpy(&((struct sockaddr_in6*) addr.hostaddr->ai_addr)->sin6_port, buf + 20, 2); ((struct sockaddr_in6*) addr.hostaddr->ai_addr)->sin6_family = PF_INET6; addr.hostaddr->ai_addr->sa_family = PF_INET6; addr.hostaddr->ai_addrlen = sizeof(struct sockaddr_in6); break; } default: notsupported: return EC_ADDRESSTYPE_NOT_SUPPORTED; } client->target_fd = socket(addr.hostaddr->ai_addr->sa_family, SOCK_STREAM, 0); if(client->target_fd == -1) { neterror: switch(errno) { case ENETDOWN: case ENETUNREACH: case ENETRESET: return EC_NET_UNREACHABLE; case EHOSTUNREACH: case EHOSTDOWN: return EC_HOST_UNREACHABLE; case ECONNREFUSED: return EC_CONN_REFUSED; default: return EC_GENERAL_FAILURE; } } if(client->target_fd >= MAX_FD) { close(client->target_fd); return EC_GENERAL_FAILURE; } flags = fcntl(client->target_fd, F_GETFL); if(flags == -1) return EC_GENERAL_FAILURE; if(fcntl(client->target_fd, F_SETFL, flags | O_NONBLOCK) == -1) return EC_GENERAL_FAILURE; ret = connect(client->target_fd, addr.hostaddr->ai_addr, addr.hostaddr->ai_addrlen); if(ret == -1) { ret = errno; if (!(ret == EINPROGRESS || ret == EWOULDBLOCK)) goto neterror; } srv->clients[fdindex(client->target_fd)].state = SS_SOCKSTARGET; srv->clients[fdindex(client->target_fd)].data = client->data; srv->clients[fdindex(client->target_fd)].target_fd = fd; rocksockserver_watch_fd(&srv->serva, client->target_fd); if(CONFIG_LOG && srv->log) { if(get_client_ip((struct sockaddr_storage*) addr.hostaddr->ai_addr, (char*) buf, CLIENT_BUFSIZE)) { logstart(); printfd(fd); LOGPUTS(1, SPLITERAL(" -> ")); printfd(client->target_fd); LOGPUT(1, VARISL(" <"), VARIC((char*)buf), VARISL(">"), NULL); } } return EC_SUCCESS; }