Beispiel #1
0
void
fwtcp_del(struct fwspec *fwspec)
{
    struct fwtcp *fwtcp;
    struct fwtcp **pprev;

    for (pprev = &fwtcp_list; (fwtcp = *pprev) != NULL; pprev = &fwtcp->next) {
        if (fwspec_equal(&fwtcp->fwspec, fwspec)) {
            *pprev = fwtcp->next;
            fwtcp->next = NULL;
            break;
        }
    }

    if (fwtcp == NULL) {
        DPRINTF0(("%s: not found\n", __func__));
        return;
    }

    DPRINTF0(("%s\n", __func__));

    pollmgr_del_slot(fwtcp->pmhdl.slot);
    fwtcp->pmhdl.slot = -1;

    closesocket(fwtcp->sock);
    fwtcp->sock = -1;

    /* let pending msg_connect be processed before we delete fwtcp */
    proxy_lwip_post(&fwtcp->msg_delete);
}
Beispiel #2
0
/**
 * Poll manager callback should use this convenience wrapper to
 * schedule pxudp deletion on the lwip thread and to deregister from
 * the poll manager.
 */
static int
pxudp_schedule_delete(struct pxudp *pxudp)
{
    /*
     * If pollmgr_refptr_get() is called by any channel before
     * scheduled deletion happens, let them know we are gone.
     */
    pxudp->pmhdl.slot = -1;

    /*
     * Schedule deletion.  Since poll manager thread may be pre-empted
     * right after we send the message, the deletion may actually
     * happen on the lwip thread before we return from this function,
     * so it's not safe to refer to pxudp after this call.
     */
    proxy_lwip_post(&pxudp->msg_delete);

    /* tell poll manager to deregister us */
    return -1;
}
Beispiel #3
0
static int
pxudp_pmgr_pump(struct pollmgr_handler *handler, SOCKET fd, int revents)
{
    struct pxudp *pxudp;
    struct pbuf *p;
    ssize_t nread;
    err_t error;

    pxudp = (struct pxudp *)handler->data;
    LWIP_ASSERT1(handler == &pxudp->pmhdl);
    LWIP_ASSERT1(fd == pxudp->sock);
    LWIP_UNUSED_ARG(fd);


    if (revents & ~(POLLIN|POLLERR)) {
        DPRINTF(("%s: unexpected revents 0x%x\n", __func__, revents));
        return pxudp_schedule_delete(pxudp);
    }

    /*
     * XXX: AFAICS, there's no way to match the error with the
     * outgoing datagram that triggered it, since we do non-blocking
     * sends from lwip thread.
     */
    if (revents & POLLERR) {
        int sockerr = -1;
        socklen_t optlen = (socklen_t)sizeof(sockerr);
        int status;

        status = getsockopt(pxudp->sock, SOL_SOCKET,
                            SO_ERROR, (char *)&sockerr, &optlen);
        if (status < 0) {
            DPRINTF(("%s: sock %d: SO_ERROR failed:%R[sockerr]\n",
                     __func__, pxudp->sock, SOCKERRNO()));
        }
        else {
            DPRINTF(("%s: sock %d: %R[sockerr]\n",
                     __func__, pxudp->sock, sockerr));
        }
    }

    if ((revents & POLLIN) == 0) {
        return POLLIN;
    }

    nread = recv(pxudp->sock, pollmgr_udpbuf, sizeof(pollmgr_udpbuf), 0);
    if (nread == SOCKET_ERROR) {
        DPRINTF(("%s: %R[sockerr]\n", __func__, SOCKERRNO()));
        return POLLIN;
    }

    p = pbuf_alloc(PBUF_RAW, (u16_t)nread, PBUF_RAM);
    if (p == NULL) {
        DPRINTF(("%s: pbuf_alloc(%d) failed\n", __func__, (int)nread));
        return POLLIN;
    }

    error = pbuf_take(p, pollmgr_udpbuf, (u16_t)nread);
    if (error != ERR_OK) {
        DPRINTF(("%s: pbuf_take(%d) failed\n", __func__, (int)nread));
        pbuf_free(p);
        return POLLIN;
    }

    error = sys_mbox_trypost(&pxudp->inmbox, p);
    if (error != ERR_OK) {
        pbuf_free(p);
        return POLLIN;
    }

    proxy_lwip_post(&pxudp->msg_inbound);

    return POLLIN;
}
Beispiel #4
0
int
fwtcp_pmgr_listen(struct pollmgr_handler *handler, SOCKET fd, int revents)
{
    struct fwtcp *fwtcp;
    struct sockaddr_storage ss;
    socklen_t sslen;
    void *peer_addr;
    uint16_t peer_port;
    struct pxtcp *pxtcp;
    SOCKET newsock;
    int status;
    err_t error;

    fwtcp = (struct fwtcp *)handler->data;
    pxtcp = NULL;

    LWIP_ASSERT1(fwtcp != NULL);
    LWIP_ASSERT1(fd == fwtcp->sock);
    LWIP_ASSERT1(revents == POLLIN);
    LWIP_UNUSED_ARG(fd);
    LWIP_UNUSED_ARG(revents);

    LWIP_ASSERT1(sys_mbox_valid(&fwtcp->connmbox));

    sslen = sizeof(ss);
    newsock = accept(fwtcp->sock, (struct sockaddr *)&ss, &sslen);
    if (newsock == INVALID_SOCKET) {
        return POLLIN;
    }


    if (ss.ss_family == PF_INET) {
        struct sockaddr_in *peer4 = (struct sockaddr_in *)&ss;
        peer_addr = &peer4->sin_addr;
        peer_port = peer4->sin_port;
    }
    else { /* PF_INET6 */
        struct sockaddr_in6 *peer6 = (struct sockaddr_in6 *)&ss;
        peer_addr = &peer6->sin6_addr;
        peer_port = peer6->sin6_port;
    }
    peer_port = ntohs(peer_port);

#if PLEASE_ABSTAIN_FROM_DPRINFING > 1 /* DPRINTF */ && !defined(RT_OS_WINDOWS)
    {
        char addrbuf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
        const char *addrstr;

        addrstr = inet_ntop(ss.ss_family, peer_addr, addrbuf, sizeof(addrbuf));
        DPRINTF(("<--- TCP %s%s%s:%d\n",
                 ss.ss_family == AF_INET6 ? "[" : "",
                 addrstr,
                 ss.ss_family == AF_INET6 ? "]" : "",
                 peer_port));
    }
#endif  /* DPRINTF */


    pxtcp = pxtcp_create_forwarded(newsock);
    if (pxtcp == NULL) {
        proxy_reset_socket(newsock);
        return POLLIN;
    }

    status = pxtcp_pmgr_add(pxtcp);
    if (status < 0) {
        pxtcp_cancel_forwarded(pxtcp);
        return POLLIN;
    }

    error = sys_mbox_trypost(&fwtcp->connmbox, (void *)pxtcp);
    if (error != ERR_OK) {
        pxtcp_pmgr_del(pxtcp);
        pxtcp_cancel_forwarded(pxtcp);
        return POLLIN;
    }

    proxy_lwip_post(&fwtcp->msg_connect);
    return POLLIN;
}
Beispiel #5
0
/**
 * Poll manager callaback for fwudp::sock
 */
int
fwudp_pmgr_pump(struct pollmgr_handler *handler, SOCKET fd, int revents)
{
    struct fwudp *fwudp;
    struct sockaddr_storage ss;
    socklen_t sslen = sizeof(ss);
    size_t beg, lim;
    struct fwudp_dgram *dgram;
    struct pbuf *p;
    ssize_t nread;
    int status;
    err_t error;

    fwudp = (struct fwudp *)handler->data;

    LWIP_ASSERT1(fwudp != NULL);
    LWIP_ASSERT1(fd == fwudp->sock);
    LWIP_ASSERT1(revents == POLLIN);
    LWIP_UNUSED_ARG(fd);
    LWIP_UNUSED_ARG(revents);

    nread = recvfrom(fwudp->sock, pollmgr_udpbuf, sizeof(pollmgr_udpbuf), 0,
                     (struct sockaddr *)&ss, &sslen);
    if (nread < 0) {
        perror(__func__);
        return POLLIN;
    }

    /* Check that ring buffer is not full */
    lim = fwudp->inbuf.unsent;
    if (lim == 0) {
        lim = fwudp->inbuf.bufsize - 1; /* guard slot at the end */
    }
    else {
        --lim;
    }

    beg = fwudp->inbuf.vacant;
    if (beg == lim) { /* no vacant slot */
        return POLLIN;
    }


    dgram = &fwudp->inbuf.buf[beg];


    status = fwany_ipX_addr_set_src(&dgram->src_addr, (struct sockaddr *)&ss);
    if (status == PXREMAP_FAILED) {
        return POLLIN;
    }

    if (ss.ss_family == AF_INET) {
        const struct sockaddr_in *peer4 = (const struct sockaddr_in *)&ss;
        dgram->src_port = htons(peer4->sin_port);
    }
    else { /* PF_INET6 */
        const struct sockaddr_in6 *peer6 = (const struct sockaddr_in6 *)&ss;
        dgram->src_port = htons(peer6->sin6_port);
    }

    p = pbuf_alloc(PBUF_RAW, nread, PBUF_RAM);
    if (p == NULL) {
        DPRINTF(("%s: pbuf_alloc(%d) failed\n", __func__, (int)nread));
        return POLLIN;
    }

    error = pbuf_take(p, pollmgr_udpbuf, nread);
    if (error != ERR_OK) {
        DPRINTF(("%s: pbuf_take(%d) failed\n", __func__, (int)nread));
        pbuf_free(p);
        return POLLIN;
    }

    dgram->p = p;

    ++beg;
    if (beg == fwudp->inbuf.bufsize) {
        beg = 0;
    }
    fwudp->inbuf.vacant = beg;

    proxy_lwip_post(&fwudp->msg_send);

    return POLLIN;
}
Beispiel #6
0
static int
pxdns_pmgr_pump(struct pollmgr_handler *handler, SOCKET fd, int revents)
{
    struct pxdns *pxdns;
    struct request *req;
    ssize_t nread;
    err_t error;
    u16_t id;

    pxdns = (struct pxdns *)handler->data;
    LWIP_ASSERT1(handler == &pxdns->pmhdl4 || handler == &pxdns->pmhdl6);
    LWIP_ASSERT1(fd == (handler == &pxdns->pmhdl4 ? pxdns->sock4 : pxdns->sock6));

    if (revents & ~(POLLIN|POLLERR)) {
        DPRINTF0(("%s: unexpected revents 0x%x\n", __func__, revents));
        return POLLIN;
    }

    if (revents & POLLERR) {
        int sockerr = -1;
        socklen_t optlen = (socklen_t)sizeof(sockerr);
        int status;

        status = getsockopt(fd, SOL_SOCKET,
                            SO_ERROR, (char *)&sockerr, &optlen);
        if (status < 0) {
            DPRINTF(("%s: sock %d: SO_ERROR failed: %R[sockerr]\n",
                     __func__, fd, SOCKERRNO()));
        }
        else {
            DPRINTF(("%s: sock %d: %R[sockerr]\n",
                     __func__, fd, sockerr));
        }
    }

    if ((revents & POLLIN) == 0) {
        return POLLIN;
    }


    nread = recv(fd, pollmgr_udpbuf, sizeof(pollmgr_udpbuf), 0);
    if (nread < 0) {
        DPRINTF(("%s: %R[sockerr]\n", __func__, SOCKERRNO()));
        return POLLIN;
    }

    /* check for minimum dns packet length */
    if (nread < 12) {
        DPRINTF2(("%s: short reply %lu bytes\n",
                  __func__, (unsigned long)nread));
        return POLLIN;
    }

    /* XXX: shall we proxy back RCODE=Refused responses? */

    memcpy(&id, pollmgr_udpbuf, sizeof(id));
    req = pxdns_request_find(pxdns, id);
    if (req == NULL) {
        DPRINTF2(("%s: orphaned reply for %d\n", __func__, id));
        ++pxdns->late_answers;
        return POLLIN;
    }

    DPRINTF2(("%s: reply for req=%p: id %d -> client id %d\n",
              __func__, (void *)req, req->id, req->client_id));

    req->reply = pbuf_alloc(PBUF_RAW, nread, PBUF_RAM);
    if (req->reply == NULL) {
        DPRINTF(("%s: pbuf_alloc(%d) failed\n", __func__, (int)nread));
        pxdns_request_free(req);
        return POLLIN;
    }

    memcpy(pollmgr_udpbuf, &req->client_id, sizeof(req->client_id));
    error = pbuf_take(req->reply, pollmgr_udpbuf, nread);
    if (error != ERR_OK) {
        DPRINTF(("%s: pbuf_take(%d) failed\n", __func__, (int)nread));
        pxdns_request_free(req);
        return POLLIN;
    }

    proxy_lwip_post(&req->msg_reply);
    return POLLIN;
}