Ejemplo n.º 1
0
// 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);
    }
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
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;
  }
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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;
}