~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/Devices/Network/slirp/tcp_subr.c

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2009-12-18 16:44:29 UTC
  • mfrom: (0.3.3 upstream) (0.4.6 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091218164429-jd34ccexpv5na11a
Tags: 3.1.2-dfsg-1ubuntu1
* Merge from Debian unstable (LP: #498219), remaining changes:
  - Disable update action
    - debian/patches/u01-disable-update-action.dpatch
  - VirtualBox should go in Accessories, not in System tools (LP: #288590)
    - debian/virtualbox-ose-qt.files/virtualbox-ose.desktop
  - Add Apport hook
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Add Launchpad integration
    - debian/control
    - debian/lpi-bug.xpm
    - debian/patches/u02-lp-integration.dpatch
* Fixes the following bugs:
  - Kernel module fails to build with Linux >= 2.6.32 (LP: #474625)
  - X.Org drivers need to be rebuilt against X-Server 1.7 (LP: #495935)
  - The *-source packages try to build the kernel modules even though the
    kernel headers aren't available (LP: #473334)
* Replace *-source packages with transitional packages for *-dkms.
* Adapt u01-disable-update-action.dpatch and u02-lp-integration.dpatch for
  new upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
121
121
        win = sbspace(&tp->t_socket->so_rcv);
122
122
    if (m == 0)
123
123
    {
 
124
#ifndef VBOX_WITH_SLIRP_BSD_MBUF
124
125
        if ((m = m_get(pData)) == NULL)
 
126
#else
 
127
        if ((m = m_gethdr(pData, M_DONTWAIT, MT_HEADER)) == NULL)
 
128
#endif
125
129
            return;
126
 
#ifdef VBOX_WITH_NAT_SERVICE
127
 
        {
128
 
            struct ethhdr *eh0, *eh;
129
 
            Assert(tp->t_socket->so_m);
130
 
            eh0 = (struct ethhdr *)tp->t_socket->so_m->m_dat;
131
 
            eh = (struct ethhdr *)m->m_dat;
132
 
            memcpy(eh->h_source, eh0->h_source, ETH_ALEN);
133
 
        }
134
 
#endif
135
130
#ifdef TCP_COMPAT_42
136
131
        tlen = 1;
137
132
#else
138
133
        tlen = 0;
139
134
#endif
140
135
        m->m_data += if_maxlinkhdr;
 
136
#ifdef VBOX_WITH_SLIRP_BSD_MBUF
 
137
        m->m_pkthdr.header = mtod(m, void *);
 
138
#endif
141
139
        *mtod(m, struct tcpiphdr *) = *ti;
142
140
        ti = mtod(m, struct tcpiphdr *);
143
141
        flags = TH_ACK;
176
174
    ti->ti_sum = cksum(m, tlen);
177
175
    ((struct ip *)ti)->ip_len = tlen;
178
176
 
179
 
    if (flags & TH_RST)
 
177
    if(flags & TH_RST)
180
178
        ((struct ip *)ti)->ip_ttl = MAXTTL;
181
179
    else
182
180
        ((struct ip *)ti)->ip_ttl = ip_defttl;
397
395
        setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(opt));
398
396
 
399
397
        addr.sin_family = AF_INET;
400
 
        if ((so->so_faddr.s_addr & htonl(pData->netmask)) == special_addr.s_addr)
 
398
        if ((so->so_faddr.s_addr & htonl(pData->netmask)) == pData->special_addr.s_addr)
401
399
        {
402
400
            /* It's an alias */
403
401
            switch(ntohl(so->so_faddr.s_addr) & ~pData->netmask)
480
478
        }
481
479
        so->so_laddr = inso->so_laddr;
482
480
        so->so_lport = inso->so_lport;
483
 
#ifdef VBOX_WITH_SLIRP_ALIAS
484
481
        so->so_la = inso->so_la;
485
 
#endif
486
482
    }
487
483
 
488
484
    (void) tcp_mss(pData, sototcpcb(so), 0);
620
616
u_int8_t
621
617
tcp_tos(struct socket *so)
622
618
{
623
 
#ifndef VBOX_WITH_SLIRP_ALIAS
624
 
    int i = 0;
625
 
 
626
 
    while(tcptos[i].tos)
627
 
    {
628
 
        if (   (tcptos[i].fport && (ntohs(so->so_fport) == tcptos[i].fport))
629
 
            || (tcptos[i].lport && (ntohs(so->so_lport) == tcptos[i].lport)))
630
 
        {
631
 
            so->so_emu = tcptos[i].emu;
632
 
            return tcptos[i].tos;
633
 
        }
634
 
        i++;
635
 
    }
636
 
#endif
637
619
    return 0;
638
620
}
639
621
 
659
641
int
660
642
tcp_emu(PNATState pData, struct socket *so, struct mbuf *m)
661
643
{
662
 
#ifndef VBOX_WITH_SLIRP_ALIAS
663
 
    u_int n1, n2, n3, n4, n5, n6;
664
 
    char buff[256];
665
 
    u_int32_t laddr;
666
 
    u_int lport;
667
 
    char *bptr;
668
 
 
669
 
    DEBUG_CALL("tcp_emu");
670
 
    DEBUG_ARG("so = %lx", (long)so);
671
 
    DEBUG_ARG("m = %lx", (long)m);
672
 
 
673
 
    switch(so->so_emu)
674
 
    {
675
 
        int x, i;
676
 
 
677
 
        case EMU_IDENT:
678
 
        /*
679
 
         * Identification protocol as per rfc-1413
680
 
         */
681
 
        {
682
 
            struct socket *tmpso;
683
 
            struct sockaddr_in addr;
684
 
            socklen_t addrlen = sizeof(struct sockaddr_in);
685
 
            struct sbuf *so_rcv = &so->so_rcv;
686
 
 
687
 
            memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
688
 
            so_rcv->sb_wptr += m->m_len;
689
 
            so_rcv->sb_rptr += m->m_len;
690
 
            m->m_data[m->m_len] = 0; /* NULL terminate */
691
 
            if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n'))
692
 
            {
693
 
                if (sscanf(so_rcv->sb_data, "%u%*[ ,]%u", &n1, &n2) == 2)
694
 
                {
695
 
                    HTONS(n1);
696
 
                    HTONS(n2);
697
 
                    /* n2 is the one on our host */
698
 
                    for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next)
699
 
                    {
700
 
                        if (   tmpso->so_laddr.s_addr == so->so_laddr.s_addr
701
 
                            && tmpso->so_lport == n2
702
 
                            && tmpso->so_faddr.s_addr == so->so_faddr.s_addr
703
 
                            && tmpso->so_fport == n1)
704
 
                        {
705
 
                            if (getsockname(tmpso->s,
706
 
                                            (struct sockaddr *)&addr, &addrlen) == 0)
707
 
                                n2 = ntohs(addr.sin_port);
708
 
                            break;
709
 
                        }
710
 
                    }
711
 
                }
712
 
                so_rcv->sb_cc = sprintf(so_rcv->sb_data, "%d,%d\r\n", n1, n2);
713
 
                so_rcv->sb_rptr = so_rcv->sb_data;
714
 
                so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc;
715
 
            }
716
 
            m_free(pData, m);
717
 
            return 0;
718
 
        }
719
 
 
720
 
        case EMU_FTP:
721
 
            *(m->m_data+m->m_len) = 0; /* NULL terminate for strstr */
722
 
            if ((bptr = (char *)strstr(m->m_data, "ORT")) != NULL)
723
 
            {
724
 
                /*
725
 
                 * Need to emulate the PORT command
726
 
                 */
727
 
                struct sockaddr_in addr;
728
 
                socklen_t addrlen = sizeof addr;
729
 
 
730
 
                if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen))
731
 
                    return 1;
732
 
 
733
 
                x = sscanf(bptr, "ORT %u,%u,%u,%u,%u,%u\r\n%256[^\177]",
734
 
                           &n1, &n2, &n3, &n4, &n5, &n6, buff);
735
 
                if (x < 6)
736
 
                    return 1;
737
 
 
738
 
                laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
739
 
                lport = htons((n5 << 8) | (n6));
740
 
 
741
 
                if ((so = solisten(pData, 0, laddr, lport, SS_FACCEPTONCE)) == NULL)
742
 
                    return 1;
743
 
 
744
 
                n6 = ntohs(so->so_fport);
745
 
 
746
 
                n5 = (n6 >> 8) & 0xff;
747
 
                n6 &= 0xff;
748
 
 
749
 
                laddr = ntohl(addr.sin_addr.s_addr);
750
 
 
751
 
                n1 = ((laddr >> 24) & 0xff);
752
 
                n2 = ((laddr >> 16) & 0xff);
753
 
                n3 = ((laddr >> 8)  & 0xff);
754
 
                n4 = ( laddr        & 0xff);
755
 
 
756
 
                m->m_len = bptr - m->m_data; /* Adjust length */
757
 
                m->m_len += sprintf(bptr, "ORT %d,%d,%d,%d,%d,%d\r\n%s",
758
 
                                    n1, n2, n3, n4, n5, n6, x==7?buff:"");
759
 
                return 1;
760
 
            }
761
 
            else if ((bptr = (char *)strstr(m->m_data, "27 Entering")) != NULL)
762
 
            {
763
 
                /*
764
 
                 * Need to emulate the PASV response
765
 
                 */
766
 
                struct sockaddr_in addr;
767
 
                socklen_t addrlen = sizeof addr;
768
 
 
769
 
                if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen))
770
 
                    return 1;
771
 
 
772
 
                x = sscanf(bptr, "27 Entering Passive Mode (%u,%u,%u,%u,%u,%u)\r\n%256[^\177]",
773
 
                           &n1, &n2, &n3, &n4, &n5, &n6, buff);
774
 
                if (x < 6)
775
 
                    return 1;
776
 
 
777
 
                laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
778
 
                lport = htons((n5 << 8) | (n6));
779
 
 
780
 
                if ((so = solisten(pData, 0, laddr, lport, SS_FACCEPTONCE)) == NULL)
781
 
                    return 1;
782
 
 
783
 
                n6 = ntohs(so->so_fport);
784
 
 
785
 
                n5 = (n6 >> 8) & 0xff;
786
 
                n6 &= 0xff;
787
 
 
788
 
                laddr = ntohl(addr.sin_addr.s_addr);
789
 
 
790
 
                n1 = ((laddr >> 24) & 0xff);
791
 
                n2 = ((laddr >> 16) & 0xff);
792
 
                n3 = ((laddr >> 8)  & 0xff);
793
 
                n4 =  (laddr & 0xff);
794
 
 
795
 
                m->m_len = bptr - m->m_data; /* Adjust length */
796
 
                m->m_len += sprintf(bptr, "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s",
797
 
                                    n1, n2, n3, n4, n5, n6, x==7?buff:"");
798
 
 
799
 
                return 1;
800
 
            }
801
 
            return 1;
802
 
 
803
 
        case EMU_KSH:
804
 
            /*
805
 
             * The kshell (Kerberos rsh) and shell services both pass
806
 
             * a local port port number to carry signals to the server
807
 
             * and stderr to the client.  It is passed at the beginning
808
 
             * of the connection as a NUL-terminated decimal ASCII string.
809
 
             */
810
 
            so->so_emu = 0;
811
 
            for (lport = 0, i = 0; i < m->m_len-1; ++i)
812
 
            {
813
 
                if (m->m_data[i] < '0' || m->m_data[i] > '9')
814
 
                    return 1;       /* invalid number */
815
 
                lport *= 10;
816
 
                lport += m->m_data[i] - '0';
817
 
            }
818
 
            if (   m->m_data[m->m_len-1] == '\0'
819
 
                && lport != 0
820
 
                && (so = solisten(pData, 0, so->so_laddr.s_addr,
821
 
                                  htons(lport), SS_FACCEPTONCE)) != NULL)
822
 
                m->m_len = sprintf(m->m_data, "%d", ntohs(so->so_fport))+1;
823
 
            return 1;
824
 
 
825
 
        case EMU_IRC:
826
 
            /*
827
 
             * Need to emulate DCC CHAT, DCC SEND and DCC MOVE
828
 
             */
829
 
            *(m->m_data+m->m_len) = 0; /* NULL terminate the string for strstr */
830
 
            if ((bptr = (char *)strstr(m->m_data, "DCC")) == NULL)
831
 
                return 1;
832
 
 
833
 
            /* The %256s is for the broken mIRC */
834
 
            if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3)
835
 
            {
836
 
                if ((so = solisten(pData, 0, htonl(laddr),
837
 
                                   htons(lport), SS_FACCEPTONCE)) == NULL)
838
 
                    return 1;
839
 
 
840
 
                m->m_len = bptr - m->m_data; /* Adjust length */
841
 
                m->m_len += sprintf(bptr, "DCC CHAT chat %lu %u%c\n",
842
 
                                    (unsigned long)ntohl(so->so_faddr.s_addr),
843
 
                                    ntohs(so->so_fport), 1);
844
 
            }
845
 
            else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4)
846
 
            {
847
 
                if ((so = solisten(pData, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
848
 
                    return 1;
849
 
 
850
 
                m->m_len = bptr - m->m_data; /* Adjust length */
851
 
                m->m_len += sprintf(bptr, "DCC SEND %s %lu %u %u%c\n",
852
 
                                    buff, (unsigned long)ntohl(so->so_faddr.s_addr),
853
 
                                    ntohs(so->so_fport), n1, 1);
854
 
            }
855
 
            else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4)
856
 
            {
857
 
                if ((so = solisten(pData, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
858
 
                    return 1;
859
 
 
860
 
                m->m_len = bptr - m->m_data; /* Adjust length */
861
 
                m->m_len += sprintf(bptr, "DCC MOVE %s %lu %u %u%c\n",
862
 
                                    buff, (unsigned long)ntohl(so->so_faddr.s_addr),
863
 
                                    ntohs(so->so_fport), n1, 1);
864
 
            }
865
 
            return 1;
866
 
 
867
 
#ifdef VBOX
868
 
            /** @todo Disabled EMU_REALAUDIO, because it uses a static variable.
869
 
             * This is not legal when more than one slirp instance is active. */
870
 
#else /* !VBOX */
871
 
        case EMU_REALAUDIO:
872
 
            /*
873
 
             * RealAudio emulation - JP. We must try to parse the incoming
874
 
             * data and try to find the two characters that contain the
875
 
             * port number. Then we redirect an udp port and replace the
876
 
             * number with the real port we got.
877
 
             *
878
 
             * The 1.0 beta versions of the player are not supported
879
 
             * any more.
880
 
             *
881
 
             * A typical packet for player version 1.0 (release version):
882
 
             *
883
 
             * 0000:50 4E 41 00 05
884
 
             * 0000:00 01 00 02 1B D7 00 00 67 E6 6C DC 63 00 12 50 .....�..g�l�c..P
885
 
             * 0010:4E 43 4C 49 45 4E 54 20 31 30 31 20 41 4C 50 48 NCLIENT 101 ALPH
886
 
             * 0020:41 6C 00 00 52 00 17 72 61 66 69 6C 65 73 2F 76 Al..R..rafiles/v
887
 
             * 0030:6F 61 2F 65 6E 67 6C 69 73 68 5F 2E 72 61 79 42 oa/english_.rayB
888
 
             *
889
 
             * Now the port number 0x1BD7 is found at offset 0x04 of the
890
 
             * Now the port number 0x1BD7 is found at offset 0x04 of the
891
 
             * second packet. This time we received five bytes first and
892
 
             * then the rest. You never know how many bytes you get.
893
 
             *
894
 
             * A typical packet for player version 2.0 (beta):
895
 
             *
896
 
             * 0000:50 4E 41 00 06 00 02 00 00 00 01 00 02 1B C1 00 PNA...........�.
897
 
             * 0010:00 67 75 78 F5 63 00 0A 57 69 6E 32 2E 30 2E 30 .gux�c..Win2.0.0
898
 
             * 0020:2E 35 6C 00 00 52 00 1C 72 61 66 69 6C 65 73 2F .5l..R..rafiles/
899
 
             * 0030:77 65 62 73 69 74 65 2F 32 30 72 65 6C 65 61 73 website/20releas
900
 
             * 0040:65 2E 72 61 79 53 00 00 06 36 42                e.rayS...6B
901
 
             *
902
 
             * Port number 0x1BC1 is found at offset 0x0d.
903
 
             *
904
 
             * This is just a horrible switch statement. Variable ra tells
905
 
             * us where we're going.
906
 
             */
907
 
 
908
 
            bptr = m->m_data;
909
 
            while (bptr < m->m_data + m->m_len)
910
 
            {
911
 
                u_short p;
912
 
                static int ra = 0;
913
 
                char ra_tbl[4];
914
 
 
915
 
                ra_tbl[0] = 0x50;
916
 
                ra_tbl[1] = 0x4e;
917
 
                ra_tbl[2] = 0x41;
918
 
                ra_tbl[3] = 0;
919
 
 
920
 
                switch (ra)
921
 
                {
922
 
                    case 0:
923
 
                    case 2:
924
 
                    case 3:
925
 
                        if (*bptr++ != ra_tbl[ra])
926
 
                        {
927
 
                            ra = 0;
928
 
                            continue;
929
 
                        }
930
 
                        break;
931
 
 
932
 
                    case 1:
933
 
                        /*
934
 
                         * We may get 0x50 several times, ignore them
935
 
                         */
936
 
                        if (*bptr == 0x50)
937
 
                        {
938
 
                            ra = 1;
939
 
                            bptr++;
940
 
                            continue;
941
 
                        }
942
 
                        else if (*bptr++ != ra_tbl[ra])
943
 
                        {
944
 
                            ra = 0;
945
 
                            continue;
946
 
                        }
947
 
                        break;
948
 
 
949
 
                    case 4:
950
 
                        /*
951
 
                         * skip version number
952
 
                         */
953
 
                        bptr++;
954
 
                        break;
955
 
 
956
 
                    case 5:
957
 
                        /*
958
 
                         * The difference between versions 1.0 and
959
 
                         * 2.0 is here. For future versions of
960
 
                         * the player this may need to be modified.
961
 
                         */
962
 
                        if (*(bptr + 1) == 0x02)
963
 
                            bptr += 8;
964
 
                        else
965
 
                            bptr += 4;
966
 
                        break;
967
 
 
968
 
                    case 6:
969
 
                        /* This is the field containing the port
970
 
                         * number that RA-player is listening to.
971
 
                         */
972
 
                        lport = (((u_char*)bptr)[0] << 8)
973
 
                              + ((u_char *)bptr)[1];
974
 
                        if (lport < 6970)
975
 
                            lport += 256;   /* don't know why */
976
 
                        if (lport < 6970 || lport > 7170)
977
 
                            return 1;       /* failed */
978
 
 
979
 
                        /* try to get udp port between 6970 - 7170 */
980
 
                        for (p = 6970; p < 7071; p++)
981
 
                        {
982
 
                            if (udp_listen(htons(p),
983
 
                                           so->so_laddr.s_addr,
984
 
                                           htons(lport),
985
 
                                           SS_FACCEPTONCE))
986
 
                            {
987
 
                                break;
988
 
                            }
989
 
                        }
990
 
                        if (p == 7071)
991
 
                            p = 0;
992
 
                        *(u_char *)bptr++ = (p >> 8) & 0xff;
993
 
                        *(u_char *)bptr++ = p & 0xff;
994
 
                        ra = 0;
995
 
                        return 1;   /* port redirected, we're done */
996
 
                        break;
997
 
 
998
 
                    default:
999
 
                        ra = 0;
1000
 
                }
1001
 
                ra++;
1002
 
            }
1003
 
            return 1;
1004
 
#endif /* !VBOX */
1005
 
 
1006
 
        default:
1007
 
            /* Ooops, not emulated, won't call tcp_emu again */
1008
 
            so->so_emu = 0;
1009
 
            return 1;
1010
 
    }
1011
 
#else /* !VBOX_WITH_SLIRP_ALIAS */
1012
644
    /*XXX: libalias should care about it */
1013
645
    so->so_emu = 0;
1014
646
    return 1;
1015
 
#endif
1016
647
}