VirtualBox

Changeset 15035 in vbox for trunk/src


Ignore:
Timestamp:
Dec 5, 2008 12:36:46 PM (16 years ago)
Author:
vboxsync
Message:

ICMP: support storaging and searching of sent packet.

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

Legend:

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

    r14684 r15035  
    6767
    6868#ifdef VBOX_WITH_SLIRP_ICMP
     69int
     70icmp_init(PNATState pData)
     71{
     72        pData->icmp_socket.so_type = IPPROTO_ICMP;
     73        pData->icmp_socket.so_state = SS_ISFCONNECTED;
     74        pData->icmp_socket.s = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
     75        insque(pData, &pData->icmp_socket, &udb);
     76        LIST_INIT(&pData->icmp_msg_head);
     77        return (0);
     78}
     79
     80/*
     81 * ip here is ip header + 64bytes readed from ICMP packet
     82 */
     83struct icmp_msg *
     84icmp_find_original_mbuf(PNATState pData, struct ip *ip)
     85{
     86    struct mbuf *m0;
     87    struct ip *ip0;
     88    struct icmp *icp, *icp0;
     89    struct icmp_msg *icm;
     90    int found = 0;
     91    struct socket *head_socket;
     92    struct in_addr laddr, faddr;
     93    u_int lport, fport;
     94
     95    switch (ip->ip_p) {
     96    case IPPROTO_ICMP:
     97        icp = (struct icmp *)((char *)ip + (ip->ip_hl << 2));
     98        LIST_FOREACH(icm, &pData->icmp_msg_head, im_list)
     99        {
     100            m0 = icm->im_m;
     101            ip0 = mtod(m0, struct ip *);
     102            AssertRelease(ip0->ip_p == IPPROTO_ICMP);
     103            icp0 = (struct icmp *)((char *)ip0 + (ip0->ip_hl << 2));
     104            LogRel(("ip(src:%R[IP4], dst:%R[IP4],id:%x) ip0(src:%R[IP4],dst:%R[IP4],id:%x)\n",
     105                    ip->ip_src.s_addr,
     106                    ip->ip_dst.s_addr,
     107                    ip->ip_id,
     108                    ip0->ip_src.s_addr,
     109                    ip0->ip_dst.s_addr,
     110                    ip0->ip_id));
     111            LogRel(("icp(id:%x, seq:%x, type=%d) icp0(id:%x, seq:%x)\n",icp->icmp_id, icp->icmp_seq, icp->icmp_type, icp0->icmp_id, icp0->icmp_seq));
     112            if (
     113                ((icp->icmp_type != ICMP_ECHO && ip->ip_src.s_addr == ip0->ip_dst.s_addr)
     114                ||(icp->icmp_type == ICMP_ECHO && ip->ip_dst.s_addr == ip0->ip_dst.s_addr))
     115                && icp->icmp_id == icp0->icmp_id
     116                && icp->icmp_seq == icp->icmp_seq) {
     117                found = 1;
     118                break;
     119            }
     120        }
     121    case IPPROTO_UDP:
     122        head_socket = &udb;
     123    case IPPROTO_TCP:
     124        head_socket = (head_socket != NULL ? head_socket : &tcb); /* head_socket could be initialized with udb*/
     125    }
     126    if (found == 1) {
     127        return (icm);
     128    }
     129    return (NULL);
     130}
     131
    69132static int
    70 icmp_attach(PNATState pData, struct socket *so) {
    71     AssertRelease(so != NULL);
    72     so->s = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
    73     insque(pData, so, &udb); /*adding it udb queue*/
    74     return (so->s);
     133icmp_attach(PNATState pData, struct mbuf *m) {
     134    struct icmp_msg *icm;
     135    struct ip *ip;
     136    ip = mtod(m, struct ip *);
     137    Assert(ip->ip_p == IPPROTO_ICMP);
     138    icm = malloc(sizeof(struct icmp_msg));
     139    icm->im_m = m;
     140    LIST_INSERT_HEAD(&pData->icmp_msg_head, icm, im_list);
     141    return (0);
    75142}
    76143#endif /* VBOX_WITH_SLIRP_ICMP */
     
    85152  register struct ip *ip=mtod(m, struct ip *);
    86153  int icmplen=ip->ip_len;
     154  int status;
    87155  /* int code; */
    88156
     
    123191    icp->icmp_type = ICMP_ECHOREPLY;
    124192#endif /* !VBOX_WITH_SLIRP_ICMP */
     193
    125194    ip->ip_len += hlen;              /* since ip_input subtracts this */
    126     if (ip->ip_dst.s_addr == alias_addr.s_addr) {
     195    if (ip->ip_dst.s_addr == alias_addr.s_addr
     196    ) {
    127197#ifdef VBOX_WITH_SLIRP_ICMP
    128198      icp->icmp_type = ICMP_ECHOREPLY;
     
    132202      struct socket *so;
    133203      struct sockaddr_in addr;
     204#ifndef VBOX_WITH_SLIRP_ICMP
    134205      if ((so = socreate()) == NULL) goto freeit;
    135 #ifndef VBOX_WITH_SLIRP_ICMP
    136206      if(udp_attach(pData, so) == -1)
    137 #else
    138       if(icmp_attach(pData, so) == -1)
    139 #endif
    140207      {
    141208        DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n",
     
    154221      so->so_state = SS_ISFCONNECTED;
    155222
    156       /* Send the packet */
    157223      addr.sin_family = AF_INET;
    158224      if ((so->so_faddr.s_addr & htonl(pData->netmask)) == special_addr.s_addr) {
     
    171237      }
    172238      addr.sin_port = so->so_fport;
    173 #ifndef VBOX_WITH_SLIRP_ICMP
    174239      if(sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), 0,
    175240                (struct sockaddr *)&addr, sizeof(addr)) == -1) {
     
    180245      }
    181246#else /* !VBOX_WITH_SLIRP_ICMP */
    182       if(sendto(so->s, icp, icmplen, 0,
     247      addr.sin_family = AF_INET;
     248      if ((ip->ip_dst.s_addr & htonl(pData->netmask)) == special_addr.s_addr) {
     249        /* It's an alias */
     250        switch(ntohl(ip->ip_dst.s_addr) & ~pData->netmask) {
     251        case CTL_DNS:
     252          addr.sin_addr = dns_addr;
     253          break;
     254        case CTL_ALIAS:
     255        default:
     256          addr.sin_addr = loopback_addr;
     257          break;
     258        }
     259      } else {
     260            addr.sin_addr.s_addr = ip->ip_dst.s_addr;
     261      }
     262      icmp_attach(pData, m);
     263      /* Send the packet */
     264      status = setsockopt(pData->icmp_socket.s, IPPROTO_IP, IP_TTL, (void *)&ip->ip_ttl, sizeof(ip->ip_ttl));
     265      if (status < 0) {
     266            LogRel(("error(%s) occured while setting TTL attribute of IP packet\n", strerror(errno)));
     267      }
     268      if(sendto(pData->icmp_socket.s, icp, icmplen, 0,
    183269                (struct sockaddr *)&addr, sizeof(addr)) == -1) {
    184270        DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n",
    185271                    errno,strerror(errno)));
    186272        icmp_error(pData, m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
    187         udp_detach(pData, so);
     273        m_free(pData, m);
    188274      }
    189275
     
    382468    m->m_len -= optlen;
    383469  }
    384 
     470  LogRel(("%s, ttl %d msg_type=%d code=%d\n", __FUNCTION__, ip->ip_ttl, icp->icmp_type, icp->icmp_code ));
     471#ifndef VBOX_WITH_SLIRP_ICMP
    385472  ip->ip_ttl = MAXTTL;
    386 #ifndef VBOX_WITH_SLIRP_ICMP
    387473  { /* swap */
    388474    struct in_addr icmp_dst;
  • trunk/src/VBox/Devices/Network/slirp/ip_icmp.h

    r1076 r15035  
    3737#ifndef _NETINET_IP_ICMP_H_
    3838#define _NETINET_IP_ICMP_H_
     39#ifdef VBOX_WITH_SLIRP_ICMP
     40#include <queue.h>
     41#endif
    3942
    4043/*
     
    162165void icmp_reflect _P((PNATState, struct mbuf *));
    163166
     167#ifdef VBOX_WITH_SLIRP_ICMP
     168struct icmp_msg{
     169    LIST_ENTRY(icmp_msg) im_list;
     170    struct mbuf *im_m;
     171};
     172
     173LIST_HEAD(icmp_storage, icmp_msg);
     174
     175int icmp_init _P((PNATState ));
     176struct icmp_msg * icmp_find_original_mbuf _P((PNATState , struct ip *));
     177#endif /* VBOX_WITH_SLIRP_ICMP */
     178
    164179#endif
  • trunk/src/VBox/Devices/Network/slirp/ip_input.c

    r14795 r15035  
    138138
    139139        /* check ip_ttl for a correct ICMP reply */
    140         if(ip->ip_ttl==0 || ip->ip_ttl==1) {
     140        if(ip->ip_ttl==0 || ip->ip_ttl == 1) {
    141141          icmp_error(pData, m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl");
    142142          goto bad;
    143143        }
    144144
     145#ifdef VBOX_WITH_SLIRP_ICMP
     146        ip->ip_ttl--;
     147#endif
    145148        /*
    146149         * Process options and, if not destined for us,
  • trunk/src/VBox/Devices/Network/slirp/slirp.c

    r14964 r15035  
    246246    if_init(pData);
    247247    ip_init(pData);
     248#ifdef VBOX_WITH_SLIRP_ICMP
     249    icmp_init(pData);
     250#endif /* VBOX_WITH_SLIRP_ICMP */
    248251
    249252    /* Initialise mbufs *after* setting the MTU */
     
    555558             * the session could have more queued if the packets needed
    556559             * to be fragmented.
    557              * 
     560             *
    558561             * (XXX <= 4 ?)
    559562             */
  • trunk/src/VBox/Devices/Network/slirp/slirp_state.h

    r14684 r15035  
    2121#ifndef _slirp_state_h_
    2222#define _slirp_state_h_
     23#ifdef VBOX_WITH_SLIRP_ICMP
     24#include "ip_icmp.h"
     25#endif
    2326
    2427/** Number of DHCP clients supported by NAT. */
     
    129132    struct socket udb;
    130133    struct socket *udp_last_so;
     134#ifdef VBOX_WITH_SLIRP_ICMP
     135    struct socket icmp_socket;
     136    struct icmp_storage icmp_msg_head;
     137#endif
    131138#if defined(VBOX_WITH_SIMPLIFIED_SLIRP_SYNC) && defined(RT_OS_WINDOWS)
    132139# define VBOX_SOCKET_EVENT (pData->phEvents[VBOX_SOCKET_EVENT_INDEX])
  • trunk/src/VBox/Devices/Network/slirp/socket.c

    r14964 r15035  
    423423    DEBUG_ARG("so = %lx", (long)so);
    424424
    425     if (so->so_type == IPPROTO_ICMP)
    426     {
    427         /* This is a "ping" reply */
    428         char buff[256];
    429         int len;
    430 
    431         len = recvfrom(so->s, buff, sizeof(buff), 0,
    432                        (struct sockaddr *)&addr, &addrlen);
    433         /* XXX Check if reply is "correct"? */
     425        if (so->so_type == IPPROTO_ICMP) {   /* This is a "ping" reply */
     426          char buff[1500];
     427          int len;
     428          len = recvfrom(so->s, buff, 1500, 0,
     429                         (struct sockaddr *)&addr, &addrlen);
     430          /* XXX Check if reply is "correct"? */
    434431
    435432        if(len == -1 || len == 0)
     
    441438            else if(errno == ENETUNREACH)
    442439                code=ICMP_UNREACH_NET;
     440
    443441
    444442            DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
     
    450448#ifdef VBOX_WITH_SLIRP_ICMP
    451449            struct ip *ip;
    452             uint32_t dst;
    453             ip = mtod(so->so_m, struct ip *);
    454             dst = ip->ip_src.s_addr;
    455             memcpy(so->so_m->m_data, buff, len); /* ovveride ther tail of old packet */
     450            uint32_t dst,src;
     451            char ip_copy[256];
     452            struct icmp *icp;
     453            int old_ip_len;
     454            struct mbuf *orig_m;
     455            struct icmp_msg *icm;
     456
     457            ip = (struct ip *)buff;
     458            icp = (struct icmp *)((char *)ip + (ip->ip_hl << 2));
     459            Assert(icp->icmp_type != ICMP_ECHO);
     460            if (icp->icmp_type >= ICMP_UNREACH ) {
     461                ip = &icp->icmp_ip;
     462            }
     463            icm = icmp_find_original_mbuf(pData, ip);
     464            if (icm == NULL) {
     465                LogRel(("Can't find the corresponding packet for the received ICMP\n"));
     466                return;
     467            }
     468            orig_m = icm->im_m;
     469            Assert(orig_m != NULL);
     470
     471            LogRel(("ICMP message arrived on socket %d\n", so->s));
     472            src = addr.sin_addr.s_addr;
     473
     474            ip = mtod(orig_m, struct ip *); /* Now ip is old header */
     475            old_ip_len = (ip->ip_hl << 2) + 64;
     476            memcpy(ip_copy, ip, old_ip_len);
     477
     478            dst = ip->ip_src.s_addr; /* source address from original IP packet*/
     479
     480            memcpy(orig_m->m_data, buff, len); /* overide ther tail of old packet */
     481            orig_m->m_len = len;
     482            ip = mtod(orig_m, struct ip *); /* ip is from mbuf we've overrided */
     483
     484            icp = (struct icmp *)((char *)ip + (ip->ip_hl << 2));
     485            NTOHS(ip->ip_len);
     486            if (icp->icmp_type >= ICMP_UNREACH && icp->icmp_type != ICMP_ECHO) {
     487                memcpy(&icp->icmp_ip, ip_copy, old_ip_len); /* according RFC 793 error messages required copy of initial IP header + 64 bit */
     488                ip->ip_tos=((ip->ip_tos & 0x1E) | 0xC0);  /* high priority for errors */
     489            }
    456490            /* the low level expects fields to be in host format so let's convert them*/
    457             ip = mtod(so->so_m, struct ip *);
    458             NTOHS(ip->ip_len);
    459491            NTOHS(ip->ip_off);
    460492            NTOHS(ip->ip_id);
     493            ip->ip_src.s_addr = src;
    461494            ip->ip_dst.s_addr = dst;
    462 #endif
     495            icmp_reflect(pData, orig_m);
     496            LIST_REMOVE(icm, im_list);
     497            /* Don't call m_free here*/
     498            free(icm);
     499#else
    463500            icmp_reflect(pData, so->so_m);
    464501            so->so_m = 0; /* Don't m_free() it again! */
    465         }
    466         /* No need for this socket anymore, udp_detach it */
    467         udp_detach(pData, so);
    468     }
    469     else
    470     {
    471         /* A "normal" UDP packet */
    472         struct mbuf *m;
    473         int len, n;
     502#endif
     503          }
     504          /* No need for this socket anymore, udp_detach it */
     505          udp_detach(pData, so);
     506        } else {                                /* A "normal" UDP packet */
     507          struct mbuf *m;
     508          int len, n;
    474509
    475510        if (!(m = m_get(pData)))
     
    533568                m->m_len = 0;
    534569            }
    535 #endif           
     570#endif
    536571
    537572            /*
     
    753788    so->so_state &= ~(SS_ISFCONNECTING);
    754789    if (so->so_state & SS_FCANTSENDMORE)
    755         so->so_state = SS_NOFDREF; /* Don't select it */ 
     790        so->so_state = SS_NOFDREF; /* Don't select it */
    756791                                   /* XXX close() here as well? */
    757792    else
  • trunk/src/VBox/Devices/Network/slirp/udp.c

    r14951 r15035  
    367367        /* Correctly update list if detaching last socket in list. */
    368368        if (so == udp_last_so) udp_last_so = &udb;
     369#ifndef VBOX_WITH_SLIRP_ICMP
    369370        closesocket(so->s);
    370371        /* if (so->so_m) m_free(so->so_m);    done by sofree */
    371372
    372373        sofree(pData, so);
     374#else /*! VBOX_WITH_SLIRP_ICMP */
     375        if (so != &pData->icmp_socket) {
     376            closesocket(so->s);
     377            sofree(pData, so);
     378        }
     379#endif /* VBOX_WITH_SLIRP_ICMP */
    373380}
    374381
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