VirtualBox

Changeset 52798 in vbox


Ignore:
Timestamp:
Sep 21, 2014 9:19:38 PM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
96193
Message:

NAT: when outgoing connect(2) fails decide what to do based on the
errno. The code to call icmp_error() is a bit icky because
tcp_input() vivisects incoming datagram and original mbuf can't be
used.

Location:
trunk/src/VBox/Devices/Network/slirp
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/slirp/slirp.c

    r52792 r52798  
    10111011            if (sockerr != 0)
    10121012            {
    1013                 /* "continue" tcp_input() to reject connection from guest */
    1014                 so->so_state = SS_NOFDREF;
    1015                 TCP_INPUT(pData, NULL, 0, so);
     1013                tcp_fconnect_failed(pData, so, sockerr);
    10161014                ret = slirpVerifyAndFreeSocket(pData, so);
    10171015                Assert(ret == 1); /* freed */
  • trunk/src/VBox/Devices/Network/slirp/slirp.h

    r51137 r52798  
    321321int tcp_reass (PNATState, struct tcpcb *, struct tcphdr *, int *, struct mbuf *);
    322322void tcp_input (PNATState, register struct mbuf *, int, struct socket *);
     323void tcp_fconnect_failed(PNATState, struct socket *, int);
    323324void tcp_dooptions (PNATState, struct tcpcb *, u_char *, int, struct tcpiphdr *);
    324325void tcp_xmit_timer (PNATState, register struct tcpcb *, int);
  • trunk/src/VBox/Devices/Network/slirp/socket.c

    r52712 r52798  
    214214        m_freem(pData, so->so_m);
    215215        so->so_m = NULL;
     216    }
     217
     218    if (so->so_ohdr != NULL)
     219    {
     220        RTMemFree(so->so_ohdr);
     221        so->so_ohdr = NULL;
    216222    }
    217223
  • trunk/src/VBox/Devices/Network/slirp/socket.h

    r52755 r52798  
    5959    struct tcpiphdr *so_ti;      /* Pointer to the original ti within
    6060                                  * so_mconn, for non-blocking connections */
     61    uint8_t         *so_ohdr;    /* unmolested IP header of the datagram in so_m */
    6162    int             so_urgc;
    6263    struct in_addr  so_faddr;    /* foreign host table entry */
  • trunk/src/VBox/Devices/Network/slirp/tcp_input.c

    r51727 r52798  
    290290tcp_input(PNATState pData, register struct mbuf *m, int iphlen, struct socket *inso)
    291291{
    292     struct ip save_ip, *ip;
     292    struct ip *ip, *save_ip;
    293293    register struct tcpiphdr *ti;
    294294    caddr_t optp = NULL;
     
    303303    u_long tiwin;
    304304/*  int ts_present = 0; */
     305    size_t ohdrlen;
     306    uint8_t ohdr[60 + 8]; /* max IP header plus 8 bytes of payload for icmp */
     307
    305308    STAM_PROFILE_START(&pData->StatTCP_input, counter_input);
    306309
     
    324327        tp = sototcpcb(so);
    325328        m = so->so_m;
    326 
    327329        so->so_m = 0;
     330
     331        if (RT_LIKELY(so->so_ohdr != NULL))
     332        {
     333            RTMemFree(so->so_ohdr);
     334            so->so_ohdr = NULL;
     335        }
     336
    328337        ti = so->so_ti;
    329338
     
    347356
    348357    tcpstat.tcps_rcvtotal++;
     358
     359    ip = mtod(m, struct ip *);
     360
     361    /* ip_input() subtracts iphlen from ip::ip_len */
     362    AssertStmt((ip->ip_len + iphlen == m_length(m, NULL)), goto drop);
     363    if (RT_UNLIKELY(ip->ip_len < sizeof(struct tcphdr)))
     364    {
     365        /* tcps_rcvshort++; */
     366        goto drop;
     367    }
     368
     369    /*
     370     * Save a copy of the IP header in case we want to restore it for
     371     * sending an ICMP error message in response.
     372     *
     373     * XXX: This function should really be fixed to not strip IP
     374     * options, to not overwrite IP header and to use "tlen" local
     375     * variable (instead of ti->ti_len), then "m" could be passed to
     376     * icmp_error() directly.
     377     */
     378    ohdrlen = iphlen + 8;
     379    m_copydata(m, 0, ohdrlen, (caddr_t)ohdr);
     380    save_ip = (struct ip *)ohdr;
     381    save_ip->ip_len += iphlen;  /* undo change by ip_input() */
     382
     383
    349384    /*
    350385     * Get IP and TCP header together in first mbuf.
     
    357392        iphlen = sizeof(struct ip);
    358393    }
    359     /* XXX Check if too short */
    360 
    361 
    362     /*
    363      * Save a copy of the IP header in case we want restore it
    364      * for sending an ICMP error message in response.
    365      */
    366     ip = mtod(m, struct ip *);
    367     /*
    368      * (vvl) ip_input substracts IP header length from ip->ip_len value.
    369      * here we do the test the same as input method of UDP protocol.
    370      */
    371     Assert((ip->ip_len + iphlen == m_length(m, NULL)));
    372     save_ip = *ip;
    373     save_ip.ip_len+= iphlen;
    374394
    375395    /*
     
    802822                    m->m_data -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
    803823                    m->m_len  += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
    804                     *ip = save_ip;
     824                    *ip = *save_ip;
    805825                    icmp_error(pData, m, ICMP_UNREACH, code, 0, strerror(errno));
    806826                    tp->t_socket->so_m = NULL;
     
    818838                so->so_m = m;
    819839                so->so_ti = ti;
     840                so->so_ohdr = RTMemDup(ohdr, ohdrlen);
    820841                tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
    821842                TCP_STATE_SWITCH_TO(tp, TCPS_SYN_RECEIVED);
     
    17431764}
    17441765
     1766
     1767void
     1768tcp_fconnect_failed(PNATState pData, struct socket *so, int sockerr)
     1769{
     1770    struct tcpcb *tp;
     1771    int code;
     1772
     1773    Log2(("NAT: connect error %d %R[natsock]\n", sockerr, so));
     1774
     1775    Assert(so->so_state & SS_ISFCONNECTING);
     1776    so->so_state = SS_NOFDREF;
     1777
     1778    if (sockerr == ECONNREFUSED || sockerr == ECONNRESET)
     1779    {
     1780        /* hand off to tcp_input():cont_conn to send RST */
     1781        TCP_INPUT(pData, NULL, 0, so);
     1782        return;
     1783    }
     1784
     1785    tp = sototcpcb(so);
     1786    if (RT_UNLIKELY(tp == NULL)) /* should never happen */
     1787    {
     1788        LogRel(("NAT: tp == NULL %R[natsock]\n", so));
     1789        sofree(pData, so);
     1790        return;
     1791    }
     1792
     1793    if (sockerr == ENETUNREACH || sockerr == ENETDOWN)
     1794        code = ICMP_UNREACH_NET;
     1795    else if (sockerr == EHOSTUNREACH || sockerr == EHOSTDOWN)
     1796        code = ICMP_UNREACH_HOST;
     1797    else
     1798        code = -1;
     1799
     1800    if (code >= 0)
     1801    {
     1802        struct ip *oip;
     1803        size_t ohdrlen;
     1804        struct mbuf *m;
     1805
     1806        if (RT_UNLIKELY(so->so_ohdr == NULL))
     1807            goto out;
     1808
     1809        oip = (struct ip *)so->so_ohdr;
     1810        ohdrlen = oip->ip_hl * 4 + 8;
     1811
     1812        m = m_gethdr(pData, M_NOWAIT, MT_HEADER);
     1813        if (RT_UNLIKELY(m == NULL))
     1814            goto out;
     1815
     1816        m_copyback(pData, m, 0, ohdrlen, (caddr_t)so->so_ohdr);
     1817        m->m_pkthdr.header = mtod(m, void *);
     1818
     1819        icmp_error(pData, m, ICMP_UNREACH, code, 0, NULL);
     1820    }
     1821
     1822  out:
     1823    tcp_close(pData, tp);
     1824}
     1825
     1826
    17451827void
    17461828tcp_dooptions(PNATState pData, struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti)
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette