VirtualBox

儲存庫 vbox 的更動 12089


忽略:
時間撮記:
2008-9-4 下午12:45:59 (16 年 以前)
作者:
vboxsync
訊息:

Solaris/vboxnetflt: Implemented flow control, re-worked some of the parts. Implemented checksumming (disabled).

檔案:
修改 1 筆資料

圖例:

未更動
新增
刪除
  • trunk/src/VBox/HostDrivers/VBoxNetFlt/solaris/VBoxNetFlt-solaris.c

    r12035 r12089  
    328328static unsigned vboxNetFltSolarisMBlkCalcSGSegs(PVBOXNETFLTINS pThis, mblk_t *pMsg);
    329329static int vboxNetFltSolarisMBlkToSG(PVBOXNETFLTINS pThis, mblk_t *pMsg, PINTNETSG pSG, unsigned cSegs, uint32_t fSrc);
    330 static int vboxNetFltSolarisIOWorker(PVBOXNETFLTINS pThis, queue_t *pQueue, vboxnetflt_stream_t *pStream, mblk_t *pMsg, uint32_t fSrc);
     330static int vboxNetFltSolarisRecv(PVBOXNETFLTINS pThis, vboxnetflt_stream_t *pStream, queue_t *pQueue, mblk_t *pMsg);
    331331static PVBOXNETFLTINS vboxNetFltSolarisFindInstance(vboxnetflt_stream_t *pStream);
    332 static void vboxNetFltSolarisFinalizeMBlk(mblk_t *pMsg);
     332static mblk_t *vboxNetFltSolarisFixChecksums(mblk_t *pMsg);
    333333static void vboxNetFltSolarisAnalyzeMBlk(mblk_t *pMsg);
    334334
     
    750750    bool fSendUpstream = true;
    751751    vboxnetflt_stream_t *pStream = pQueue->q_ptr;
    752     PVBOXNETFLTINS pThis = vboxNetFltSolarisFindInstance(pStream);
    753 
    754     if (pStream->Type == kIpStream)
    755     {
    756         switch (DB_TYPE(pMsg))
    757         {
    758             case M_DATA:
     752
     753    /*
     754     * In the unlikely case where VirtualBox crashed and this filter
     755     * is somehow still in the host stream we must try not to panic the host.
     756     */
     757    if (   pStream
     758        && pStream->Type == kIpStream
     759        && pMsg)
     760    {
     761        PVBOXNETFLTINS pThis = vboxNetFltSolarisFindInstance(pStream);
     762        if (RT_LIKELY(pThis))
     763        {
     764            switch (DB_TYPE(pMsg))
    759765            {
    760                 LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut M_DATA\n"));
    761 
    762                 vboxNetFltSolarisIOWorker(pThis, pStream->pReadQueue, pStream, pMsg, INTNETTRUNKDIR_WIRE);
    763                 fSendUpstream = false;          /* vboxNetFltSolarisIOWorker would send it if required, do nothing more here. */
    764                 break;
     766                case M_DATA:
     767                {
     768                    LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut M_DATA\n"));
     769
     770                    vboxNetFltSolarisRecv(pThis, pStream, pQueue, pMsg);
     771                    fSendUpstream = false;          /* vboxNetFltSolarisRecv would send it if required, do nothing more here. */
     772                    break;
     773                }
     774
     775                case M_PROTO:
     776                case M_PCPROTO:
     777                {
     778                    union DL_primitives *pPrim = (union DL_primitives *)pMsg->b_rptr;
     779                    t_uscalar_t Prim = pPrim->dl_primitive;
     780
     781                    LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: M_PCPROTO %d\n", Prim));
     782                    switch (Prim)
     783                    {
     784                        case DL_UNITDATA_IND:
     785                        {
     786                            /*
     787                             * I do not think control would come here... We convert all outgoing fast mode requests
     788                             * to raw mode; so I don't think we should really receive any fast mode replies.
     789                             */
     790                            LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: DL_UNITDATA_IND\n"));
     791
     792                            vboxNetFltSolarisRecv(pThis, pStream, pQueue, pMsg);
     793                            fSendUpstream = false;      /* vboxNetFltSolarisRecv would send it if required, do nothing more here. */
     794                            break;
     795                        }
     796
     797                        case DL_PHYS_ADDR_ACK:
     798                        {
     799                            vboxNetFltSolarisCachePhysAddr(pThis, pMsg);
     800
     801                            /*
     802                             * Swallow our fake physical address request acknowledgement.
     803                             */
     804                            if (pStream->UnAckPrim == DL_PHYS_ADDR_REQ)
     805                            {
     806                                freemsg(pMsg);
     807                                fSendUpstream = false;
     808                            }
     809                            break;
     810                        }
     811
     812                        case DL_OK_ACK:
     813                        {
     814                            dl_ok_ack_t *pOkAck = (dl_ok_ack_t *)pMsg->b_rptr;
     815                            if (pOkAck->dl_correct_primitive == DL_PROMISCON_REQ)
     816                            {
     817                                LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: M_PCPROTO: DL_OK_ACK: fPromisc is ON.\n"));
     818                                pStream->fPromisc = true;
     819                            }
     820                            else if (pOkAck->dl_correct_primitive == DL_PROMISCOFF_REQ)
     821                            {
     822                                LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: M_PCPROTO: DL_OK_ACK: fPromisc is OFF.\n"));
     823                                pStream->fPromisc = false;
     824                            }
     825
     826                            /*
     827                             * Swallow our fake promiscous request acknowledgement.
     828                             */
     829                            if (pStream->UnAckPrim == pOkAck->dl_correct_primitive)
     830                            {
     831                                freemsg(pMsg);
     832                                fSendUpstream = false;
     833                            }
     834                            break;
     835                        }
     836                    }
     837                    break;
     838                }
     839
     840                case M_IOCACK:
     841                {
     842                    /*
     843                     * Swallow our fake raw/fast path mode request acknowledgement.
     844                     */
     845                    struct iocblk *pIOC = (struct iocblk *)pMsg->b_rptr;
     846                    if (pIOC->ioc_id == pStream->ModeReqId)
     847                    {
     848                        pStream->ModeReqId = VBOXNETFLT_MODE_REQ_MAGIC;
     849                        pStream->fRawMode = !pStream->fRawMode;
     850
     851                        /*
     852                         * Somehow raw mode is turned off?? This should never really happen...
     853                         */
     854                        if (pStream->fRawMode == false)
     855                        {
     856                            LogFlow((DEVICE_NAME ":re-requesting raw mode!\n"));
     857                            vboxNetFltSolarisSetRawMode(pQueue);
     858                        }
     859
     860                        freemsg(pMsg);
     861                        fSendUpstream = false;
     862                    }
     863                    break;
     864                }
     865
     866                case M_FLUSH:
     867                {
     868                    /*
     869                     * We must support flushing queues.
     870                     */
     871                    LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: M_FLUSH\n"));
     872                    if (*pMsg->b_rptr & FLUSHR)
     873                        flushq(pQueue, FLUSHALL);
     874                    break;
     875                }
    765876            }
    766 
    767             case M_PROTO:
    768             case M_PCPROTO:
    769             {
    770                 union DL_primitives *pPrim = (union DL_primitives *)pMsg->b_rptr;
    771                 t_uscalar_t Prim = pPrim->dl_primitive;
    772 
    773                 LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: M_PCPROTO %d\n", Prim));
    774                 switch (Prim)
    775                 {
    776                     case DL_UNITDATA_IND:
    777                     {
    778                         /*
    779                          * I do not think control would come here... We convert all outgoing fast mode requests
    780                          * to raw mode; so I don't think we should really receive any fast mode replies.
    781                          */
    782                         LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: DL_UNITDATA_IND\n"));
    783 
    784                         vboxNetFltSolarisIOWorker(pThis, pStream->pReadQueue, pStream, pMsg, INTNETTRUNKDIR_WIRE);
    785                         fSendUpstream = false;      /* vboxNetFltSolarisIOWorker would send it if required, do nothing more here. */
    786                         break;
    787                     }
    788 
    789                     case DL_PHYS_ADDR_ACK:
    790                     {
    791                         vboxNetFltSolarisCachePhysAddr(pThis, pMsg);
    792 
    793                         /*
    794                          * Swallow our fake physical address request acknowledgement.
    795                          */
    796                         if (pStream->UnAckPrim == DL_PHYS_ADDR_REQ)
    797                         {
    798                             freemsg(pMsg);
    799                             fSendUpstream = false;
    800                         }
    801                         break;
    802                     }
    803 
    804                     case DL_OK_ACK:
    805                     {
    806                         dl_ok_ack_t *pOkAck = (dl_ok_ack_t *)pMsg->b_rptr;
    807                         if (pOkAck->dl_correct_primitive == DL_PROMISCON_REQ)
    808                         {
    809                             LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: M_PCPROTO: DL_OK_ACK: fPromisc is ON.\n"));
    810                             pStream->fPromisc = true;
    811                         }
    812                         else if (pOkAck->dl_correct_primitive == DL_PROMISCOFF_REQ)
    813                         {
    814                             LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: M_PCPROTO: DL_OK_ACK: fPromisc is OFF.\n"));
    815                             pStream->fPromisc = false;
    816                         }
    817 
    818                         /*
    819                          * Swallow our fake promiscous request acknowledgement.
    820                          */
    821                         if (pStream->UnAckPrim == pOkAck->dl_correct_primitive)
    822                         {
    823                             freemsg(pMsg);
    824                             fSendUpstream = false;
    825                         }
    826                         break;
    827                     }
    828                 }
    829                 break;
    830             }
    831 
    832             case M_IOCACK:
    833             {
    834                 /*
    835                  * Swallow our fake raw/fast path mode request acknowledgement.
    836                  */
    837                 struct iocblk *pIOC = (struct iocblk *)pMsg->b_rptr;
    838                 if (pIOC->ioc_id == pStream->ModeReqId)
    839                 {
    840                     pStream->ModeReqId = VBOXNETFLT_MODE_REQ_MAGIC;
    841                     pStream->fRawMode = !pStream->fRawMode;
    842 
    843                     /*
    844                      * Somehow raw mode is turned off??
    845                      */
    846                     if (pStream->fRawMode == false)
    847                     {
    848                         LogFlow((DEVICE_NAME ":re-requesting raw mode!!!!!!!!!!!!!!!!!!!!!!!!!!\n"));
    849                         vboxNetFltSolarisSetRawMode(pQueue);
    850                     }
    851 
    852                     freemsg(pMsg);
    853                     fSendUpstream = false;
    854                 }
    855                 break;
    856             }
    857 
    858             case M_FLUSH:
    859             {
    860                 /*
    861                  * We must support flushing queues.
    862                  */
    863                 LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: M_FLUSH\n"));
    864                 if (*pMsg->b_rptr & FLUSHR)
    865                     flushq(pQueue, FLUSHALL);
    866                 break;
    867             }
    868         }
     877        }
     878        else
     879            LogRel((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: Could not find VirtualBox instance!!\n"));
    869880    }
    870881
     
    906917    bool fSendDownstream = true;
    907918    vboxnetflt_stream_t *pStream = pQueue->q_ptr;
    908     PVBOXNETFLTINS pThis = vboxNetFltSolarisFindInstance(pStream);
    909     int rc;
    910     if (pStream->Type == kIpStream)
    911     {
    912         switch (DB_TYPE(pMsg))
    913         {
    914             case M_DATA:
     919
     920    /*
     921     * In the unlikely case where VirtualBox crashed and this filter
     922     * is somehow still in the host stream we must try not to panic the host.
     923     */
     924    if (   pStream
     925        && pStream->Type == kIpStream
     926        && pMsg)
     927    {
     928        PVBOXNETFLTINS pThis = vboxNetFltSolarisFindInstance(pStream);
     929        if (RT_LIKELY(pThis))
     930        {
     931            switch (DB_TYPE(pMsg))
    915932            {
    916                 LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModWritePut M_DATA\n"));
    917                 break;
    918             }
    919 
    920             case M_PROTO:
    921             case M_PCPROTO:
    922             {
    923                 /*
    924                  * Queue up other primitives to the service routine.
    925                  */
    926                 LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModWritePut M_PROTO/M_PCPROTO\n"));
    927 
    928                 union DL_primitives *pPrim = (union DL_primitives *)pMsg->b_rptr;
    929                 t_uscalar_t Prim = pPrim->dl_primitive;
    930                 switch (Prim)
     933                case M_DATA:
    931934                {
    932                     case DL_UNITDATA_REQ:
     935                    LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModWritePut M_DATA\n"));
     936                    break;
     937                }
     938
     939                case M_PROTO:
     940                case M_PCPROTO:
     941                {
     942                    /*
     943                     * Queue up other primitives to the service routine.
     944                     */
     945                    LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModWritePut M_PROTO/M_PCPROTO\n"));
     946
     947                    union DL_primitives *pPrim = (union DL_primitives *)pMsg->b_rptr;
     948                    t_uscalar_t Prim = pPrim->dl_primitive;
     949                    switch (Prim)
    933950                    {
    934                         LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModWritePut DL_UNITDATA_REQ\n"));
    935                         mblk_t *pRawMsg;
    936                         rc = vboxNetFltSolarisUnitDataToRaw(pThis, pMsg, &pRawMsg);
    937                         if (VBOX_SUCCESS(rc))
    938                             pMsg = pRawMsg;
    939                         else
     951                        case DL_UNITDATA_REQ:
     952                        {
     953                            LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModWritePut DL_UNITDATA_REQ\n"));
     954                            mblk_t *pRawMsg;
     955                            int rc = vboxNetFltSolarisUnitDataToRaw(pThis, pMsg, &pRawMsg);
     956                            if (VBOX_SUCCESS(rc))
     957                                pMsg = pRawMsg;
     958                            else
     959                                fSendDownstream = false;
     960                            break;
     961                        }
     962
     963                        default:
     964                        {
     965                            /*
     966                             * Enqueue other DLPI primitives and service them later.
     967                             */
    940968                            fSendDownstream = false;
    941                         break;
     969                            putq(pQueue, pMsg);
     970                            break;
     971                        }
    942972                    }
    943 
    944                     default:
     973                    break;
     974                }
     975
     976                case M_IOCTL:
     977                {
     978                    struct iocblk *pIOC = (struct iocblk *)pMsg->b_rptr;
     979                    if (pIOC->ioc_cmd == DL_IOC_HDR_INFO)
     980                    {
     981                        if (pThis->fActive)
     982                        {
     983                            /*
     984                             * Somebody is wanting fast path when we need raw mode.
     985                             * Since we are evil, let's acknowledge the request ourselves!
     986                             */
     987                            miocnak(pQueue, pMsg, 0, EINVAL);
     988                            fSendDownstream = false;
     989                            LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModWritePut: Fast path request when we need raw mode!\n"));
     990                        }
     991                    }
     992                    break;
     993                }
     994
     995                case M_FLUSH:
     996                {
     997                    /*
     998                     * Canonical flush courtesy man qreply(9F) while we have a service routine.
     999                     */
     1000                    LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModWritePut M_FLUSH\n"));
     1001                    if (*pMsg->b_rptr & FLUSHW)
    9451002                    {
    9461003                        /*
    947                          * Enqueue other DLPI primitives and service them later.
     1004                         * Flush and mark as serviced.
    9481005                         */
    949                         fSendDownstream = false;
    950                         putq(pQueue, pMsg);
    951                         break;
     1006                        flushq(pQueue, FLUSHALL);
     1007                        *pMsg->b_rptr &= ~FLUSHW;
    9521008                    }
    953                 }
    954                 break;
    955             }
    956 
    957             case M_IOCTL:
    958             {
    959                 struct iocblk *pIOC = (struct iocblk *)pMsg->b_rptr;
    960                 if (pIOC->ioc_cmd == DL_IOC_HDR_INFO)
    961                 {
    962                     if (pThis->fActive)
     1009
     1010                    if (*pMsg->b_rptr & FLUSHR)
    9631011                    {
    9641012                        /*
    965                          * Somebody is wanting fast path when we need raw mode.
    966                          * Since we are evil, let's acknowledge the request ourselves!
     1013                         * Send the request upstream.
    9671014                         */
    968                         miocnak(pQueue, pMsg, 0, EINVAL);
    969                         fSendDownstream = false;
    970                         LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModWritePut: Fast path request when we need raw mode!\n"));
     1015                        flushq(RD(pQueue), FLUSHALL);
     1016                        qreply(pQueue, pMsg);
    9711017                    }
     1018                    else
     1019                        freemsg(pMsg);
     1020
     1021                    break;
    9721022                }
    973                 break;
    9741023            }
    975 
    976             case M_FLUSH:
    977             {
    978                 /*
    979                  * Canonical flush courtesy man qreply(9F) while we have a service routine.
    980                  */
    981                 LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModWritePut M_FLUSH\n"));
    982                 if (*pMsg->b_rptr & FLUSHW)
    983                 {
    984                     /*
    985                      * Flush and mark as serviced.
    986                      */
    987                     flushq(pQueue, FLUSHALL);
    988                     *pMsg->b_rptr &= ~FLUSHW;
    989                 }
    990 
    991                 if (*pMsg->b_rptr & FLUSHR)
    992                 {
    993                     /*
    994                      * Send the request upstream.
    995                      */
    996                     flushq(RD(pQueue), FLUSHALL);
    997                     qreply(pQueue, pMsg);
    998                 }
    999                 else
    1000                     freemsg(pMsg);
    1001 
    1002                 break;
    1003             }
    1004         }
     1024        }
     1025        else
     1026            LogRel((DEVICE_NAME ":VBoxNetFltSolarisModWritePut: Could not find VirtualBox instance!!\n"));
    10051027    }
    10061028
     
    10371059
    10381060    /*
    1039      * Drain the queue as we service the messages.
     1061     * Implment just the flow controlled service draining of the queue.
     1062     * Nothing else to do here, we handle all the important stuff in the Put procedure.
    10401063     */
    10411064    mblk_t *pMsg;
    10421065    while (pMsg = getq(pQueue))
    10431066    {
    1044         switch (DB_TYPE(pMsg))
    1045         {
    1046             case M_DATA:
    1047             case M_PROTO:
    1048             case M_PCPROTO:
    1049             {
    1050                 LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModWriteService M_DATA/M_PROTO/M_PCPROTO forwarding downstream\n"));
    1051                 putnext(pQueue, pMsg);
    1052                 break;
    1053             }
    1054 
    1055             case M_IOCTL:
    1056             case M_IOCDATA:
    1057             {
    1058                 LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModWritePut M_IOCTL/M_IOCDATA\n"));
    1059                 putnext(pQueue, pMsg);
    1060                 break;
    1061             }
    1062 
    1063             default:
    1064             {
    1065                 LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModWriteService (Unknown)!\n"));
    1066                 if (canputnext(pQueue))
    1067                     putnext(pQueue, pMsg);
    1068                 else
    1069                     putq(pQueue, pMsg);
    1070                 break;
    1071             }
     1067        if (canputnext(pQueue))
     1068            putnext(pQueue, pMsg);
     1069        else
     1070        {
     1071            putbq(pQueue, pMsg);
     1072            break;
    10721073        }
    10731074    }
     
    15221523    int rc;
    15231524    int rc2;
    1524     int rc3;
    15251525    int ret;
    1526     ldi_ident_t DevId = ldi_ident_from_anon();
     1526    ldi_ident_t IPDevId = ldi_ident_from_anon();
     1527    ldi_ident_t ARPDevId = ldi_ident_from_anon();
    15271528    ldi_handle_t IPDevHandle;
    15281529    ldi_handle_t UDPDevHandle;
     
    15301531
    15311532    /*
    1532      * @todo Do opening of each stream separately with error checking.
    1533      */
    1534     /*
    1535      * Open the IP stream as a layered device.
    1536      */
    1537     rc = ldi_open_by_name(IP_DEV_NAME, FREAD | FWRITE, kcred, &IPDevHandle, DevId);
    1538     rc2 = ldi_open_by_name("/dev/arp", FREAD | FWRITE, kcred, &ARPDevHandle, DevId);
    1539     if (   !rc
    1540         && !rc2)
     1533     * Open the IP and ARP streams as layered devices.
     1534     */
     1535    rc = ldi_open_by_name(IP_DEV_NAME, FREAD | FWRITE, kcred, &IPDevHandle, IPDevId);
     1536    ldi_ident_release(IPDevId);
     1537    if (rc)
     1538    {
     1539        LogRel((DEVICE_NAME ":failed to open the IP stream on '%s'.\n", pThis->szName));
     1540        return VERR_INTNET_FLT_IF_FAILED;
     1541    }
     1542
     1543    rc = ldi_open_by_name("/dev/arp", FREAD | FWRITE, kcred, &ARPDevHandle, ARPDevId);
     1544    ldi_ident_release(ARPDevId);
     1545    if (rc)
     1546    {
     1547        LogRel((DEVICE_NAME ":failed to open the ARP stream on '%s'.\n", pThis->szName));
     1548        ldi_close(IPDevHandle, FREAD | FWRITE, kcred);
     1549        return VERR_INTNET_FLT_IF_FAILED;
     1550    }
     1551
     1552    /*
     1553     * Obtain the interface flags from IP.
     1554     */
     1555    rc = vboxNetFltSolarisGetIfFlags(IPDevHandle, &Interface);
     1556    if (VBOX_SUCCESS(rc))
    15411557    {
    15421558        /*
    1543          * Obtain the interface flags from IP.
     1559         * Open the UDP stream. We sort of cheat here and obtain the vnode so that we can perform
     1560         * things that are not possible from the layered interface.
    15441561         */
    1545         rc = vboxNetFltSolarisGetIfFlags(IPDevHandle, &Interface);
     1562        vnode_t *pVNodeUDP = NULL;
     1563        vnode_t *pVNodeUDPHeld = NULL;
     1564        TIUSER *pUserUDP = NULL;
     1565        rc = vboxNetFltSolarisOpenDev(UDP_DEV_NAME, &pVNodeUDP, &pVNodeUDPHeld, &pUserUDP);
    15461566        if (VBOX_SUCCESS(rc))
    15471567        {
    15481568            /*
    1549              * Open the UDP stream. We sort of cheat here and obtain the vnode so that we can perform
    1550              * things that are not possible from the layered interface.
     1569             * Get the multiplexor IDs.
    15511570             */
    1552             vnode_t *pVNodeUDP = NULL;
    1553             vnode_t *pVNodeUDPHeld = NULL;
    1554             TIUSER *pUserUDP = NULL;
    1555             rc = vboxNetFltSolarisOpenDev(UDP_DEV_NAME, &pVNodeUDP, &pVNodeUDPHeld, &pUserUDP);
    1556             if (VBOX_SUCCESS(rc))
     1571            rc = ldi_ioctl(IPDevHandle, SIOCGLIFMUXID, (intptr_t)&Interface, FKIOCTL, kcred, &ret);
     1572            if (!rc)
    15571573            {
    15581574                /*
    1559                  * Get the multiplexor IDs.
     1575                 * Get the multiplex file descriptor to the lower streams. Generally this is lost
     1576                 * once a module is I_PLINK, we need to reobtain it for inserting/removing ourselves from the stack.
    15601577                 */
    1561                 rc = ldi_ioctl(IPDevHandle, SIOCGLIFMUXID, (intptr_t)&Interface, FKIOCTL, kcred, &ret);
    1562                 if (!rc)
     1578                int IpMuxFd;
     1579                int ArpMuxFd;
     1580                rc = vboxNetFltSolarisMuxIdToFd(pVNodeUDP, Interface.lifr_ip_muxid, &IpMuxFd);
     1581                rc2 = vboxNetFltSolarisMuxIdToFd(pVNodeUDP, Interface.lifr_arp_muxid, &ArpMuxFd);
     1582                if (   VBOX_SUCCESS(rc)
     1583                    && VBOX_SUCCESS(rc2))
    15631584                {
    15641585                    /*
    1565                      * Get the multiplex file descriptor to the lower streams. Generally this is lost
    1566                      * once a module is I_PLINK, we need to reobtain it for inserting/removing ourselves from the stack.
     1586                     * We need to I_PUNLINK on these multiplexor IDs before we can start
     1587                     * operating on the lower stream as insertions are direct operations on the lower stream.
    15671588                     */
    1568                     int IpMuxFd;
    1569                     int ArpMuxFd;
    1570                     rc = vboxNetFltSolarisMuxIdToFd(pVNodeUDP, Interface.lifr_ip_muxid, &IpMuxFd);
    1571                     rc2 = vboxNetFltSolarisMuxIdToFd(pVNodeUDP, Interface.lifr_arp_muxid, &ArpMuxFd);
    1572                     if (   VBOX_SUCCESS(rc)
    1573                         && VBOX_SUCCESS(rc2))
     1589                    int ret;
     1590                    rc = strioctl(pVNodeUDP, I_PUNLINK, (intptr_t)Interface.lifr_ip_muxid, 0, K_TO_K, kcred, &ret);
     1591                    rc2 = strioctl(pVNodeUDP, I_PUNLINK, (intptr_t)Interface.lifr_arp_muxid, 0, K_TO_K, kcred, &ret);
     1592                    if (   !rc
     1593                        && !rc2)
    15741594                    {
    15751595                        /*
    1576                          * We need to I_PUNLINK on these multiplexor IDs before we can start
    1577                          * operating on the lower stream as insertions are direct operations on the lower stream.
     1596                         * Obtain the vnode from the useless userland file descriptor.
    15781597                         */
    1579                         int ret;
    1580                         rc = strioctl(pVNodeUDP, I_PUNLINK, (intptr_t)Interface.lifr_ip_muxid, 0, K_TO_K, kcred, &ret);
    1581                         rc2 = strioctl(pVNodeUDP, I_PUNLINK, (intptr_t)Interface.lifr_arp_muxid, 0, K_TO_K, kcred, &ret);
    1582                         if (   !rc
    1583                             && !rc2)
     1598                        file_t *pIpFile = getf(IpMuxFd);
     1599                        file_t *pArpFile = getf(ArpMuxFd);
     1600                        if (   pIpFile
     1601                            && pArpFile
     1602                            && pArpFile->f_vnode
     1603                            && pIpFile->f_vnode)
    15841604                        {
     1605                            vnode_t *pVNodeIp = pIpFile->f_vnode;
     1606                            vnode_t *pVNodeArp = pArpFile->f_vnode;
     1607
    15851608                            /*
    1586                              * Obtain the vnode from the useless userland file descriptor.
     1609                             * Find the position on the host stack for attaching/detaching ourselves.
    15871610                             */
    1588                             file_t *pIpFile = getf(IpMuxFd);
    1589                             file_t *pArpFile = getf(ArpMuxFd);
    1590                             if (   pIpFile
    1591                                 && pArpFile
    1592                                 && pArpFile->f_vnode
    1593                                 && pIpFile->f_vnode)
     1611                            rc = vboxNetFltSolarisDetermineModPos(fAttach, pVNodeIp, &StrMod.pos);
     1612                            rc2 = vboxNetFltSolarisDetermineModPos(fAttach, pVNodeArp, &ArpStrMod.pos);
     1613                            if (   VBOX_SUCCESS(rc)
     1614                                && VBOX_SUCCESS(rc2))
    15941615                            {
    1595                                 vnode_t *pVNodeIp = pIpFile->f_vnode;
    1596                                 vnode_t *pVNodeArp = pArpFile->f_vnode;
    1597 
    15981616                                /*
    1599                                  * Find the position on the host stack for attaching/detaching ourselves.
     1617                                 * Set global data which will be grabbed by ModOpen.
    16001618                                 */
    1601                                 rc = vboxNetFltSolarisDetermineModPos(fAttach, pVNodeIp, &StrMod.pos);
    1602                                 rc2 = vboxNetFltSolarisDetermineModPos(fAttach, pVNodeArp, &ArpStrMod.pos);
    1603                                 if (   VBOX_SUCCESS(rc)
    1604                                     && VBOX_SUCCESS(rc2))
     1619                                g_VBoxNetFltSolarisState.pCurInstance = pThis;
     1620                                g_VBoxNetFltSolarisState.CurType = kIpStream;
     1621
     1622                                /*
     1623                                 * Inject/Eject from the host IP stack.
     1624                                 */
     1625                                rc = strioctl(pVNodeIp, fAttach ? _I_INSERT : _I_REMOVE, (intptr_t)&StrMod, 0, K_TO_K, kcred, &ret);
     1626                                if (!rc)
    16051627                                {
    1606                                     /** @todo -XXX- Do each step here with full error checking. I know the if-levels are
    1607                                       * getting ridiculous but it has to be done as failure here is still possible
    1608                                       * (though unlikely) given a terribly ackward user configuration or messed up stack.
    1609                                       */
    1610                                     /*
    1611                                      * Set global data which will be grabbed by ModOpen.
    1612                                      */
    1613                                     g_VBoxNetFltSolarisState.pCurInstance = pThis;
    1614                                     g_VBoxNetFltSolarisState.CurType = kIpStream;
    1615 
    1616                                     /*
    1617                                      * Inject/Eject from the host IP stack.
    1618                                      */
    1619                                     rc = strioctl(pVNodeIp, fAttach ? _I_INSERT : _I_REMOVE, (intptr_t)&StrMod, 0, K_TO_K, kcred, &ret);
    1620 
    16211628                                    /*
    16221629                                     * Inject/Eject from the host ARP stack.
    16231630                                     */
    16241631                                    g_VBoxNetFltSolarisState.CurType = kArpStream;
    1625                                     rc2 = strioctl(pVNodeArp, fAttach ? _I_INSERT : _I_REMOVE, (intptr_t)&ArpStrMod, 0, K_TO_K, kcred, &ret);
    1626 
    1627                                     g_VBoxNetFltSolarisState.pCurInstance = NULL;
    1628                                     g_VBoxNetFltSolarisState.CurType = kUndefined;
    1629 
    1630                                     /*
    1631                                      * Our job's not yet over; we need to relink the upper and lower streams
    1632                                      * otherwise we've pretty much screwed up the host interface.
    1633                                      */
    1634                                     rc3 = vboxNetFltSolarisRelink(pVNodeUDP, &Interface, IpMuxFd, ArpMuxFd);
    1635                                     if (   !rc
    1636                                         && !rc2
    1637                                         && VBOX_SUCCESS(rc3))
     1632                                    rc = strioctl(pVNodeArp, fAttach ? _I_INSERT : _I_REMOVE, (intptr_t)&ArpStrMod, 0, K_TO_K, kcred, &ret);
     1633                                    if (!rc)
    16381634                                    {
    1639                                         bool fRawModeOk = !fAttach;         /* Raw mode check is always ok during the detach case */
    1640                                         if (fAttach)
     1635                                        g_VBoxNetFltSolarisState.pCurInstance = NULL;
     1636                                        g_VBoxNetFltSolarisState.CurType = kUndefined;
     1637
     1638                                        /*
     1639                                         * Our job's not yet over; we need to relink the upper and lower streams
     1640                                         * otherwise we've pretty much screwed up the host interface.
     1641                                         */
     1642                                        rc = vboxNetFltSolarisRelink(pVNodeUDP, &Interface, IpMuxFd, ArpMuxFd);
     1643                                        if (VBOX_SUCCESS(rc))
    16411644                                        {
    1642                                             /*
    1643                                              * Check if our raw mode request was successful (only in the IP stream).
    1644                                              */
    1645                                             vboxnetflt_stream_t *pStream = pThis->u.s.pvStream;
    1646                                             AssertRelease(pStream);
    1647                                             if (   pStream->fRawMode == true
    1648                                                 && pStream->ModeReqId == VBOXNETFLT_MODE_REQ_MAGIC)
     1645                                            bool fRawModeOk = !fAttach;         /* Raw mode check is always ok during the detach case */
     1646                                            if (fAttach)
    16491647                                            {
    1650                                                 pStream->ModeReqId = 0;
    1651                                                 fRawModeOk = true;
     1648                                                /*
     1649                                                 * Check if our raw mode request was successful (only in the IP stream).
     1650                                                 */
     1651                                                vboxnetflt_stream_t *pStream = pThis->u.s.pvStream;
     1652                                                if (RT_LIKELY(pStream))
     1653                                                {
     1654                                                    if (   pStream->fRawMode == true
     1655                                                        && pStream->ModeReqId == VBOXNETFLT_MODE_REQ_MAGIC)
     1656                                                    {
     1657                                                        pStream->ModeReqId = 0;
     1658                                                        fRawModeOk = true;
     1659                                                    }
     1660                                                }
     1661                                            }
     1662
     1663                                            if (fRawModeOk)
     1664                                            {
     1665                                                /*
     1666                                                 * Close the devices ONLY during the return from function case; otherwise
     1667                                                 * we end up close twice which is an instant kernel panic.
     1668                                                 */
     1669                                                vboxNetFltSolarisCloseDev(pVNodeUDPHeld, pUserUDP);
     1670                                                ldi_close(ARPDevHandle, FREAD | FWRITE, kcred);
     1671                                                ldi_close(IPDevHandle, FREAD | FWRITE, kcred);
     1672
     1673                                                LogFlow((DEVICE_NAME ":vboxNetFltSolarisModSetup: Success! %s %s@(Ip:%d Arp:%d) %s interface %s\n",
     1674                                                        fAttach ? "Injected" : "Ejected", StrMod.mod_name, StrMod.pos, ArpStrMod.pos,
     1675                                                        fAttach ? "to" : "from", pThis->szName));
     1676                                                return VINF_SUCCESS;
    16521677                                            }
    16531678                                            else
    1654                                                 fRawModeOk = false;
    1655                                         }
    1656 
    1657                                         if (fRawModeOk)
    1658                                         {
    1659                                             /*
    1660                                              * Close the devices ONLY during the return from function case; otherwise
    1661                                              * we end up close twice which is an instant kernel panic.
    1662                                              */
    1663                                             vboxNetFltSolarisCloseDev(pVNodeUDPHeld, pUserUDP);
    1664                                             ldi_close(IPDevHandle, FREAD | FWRITE, kcred);
    1665                                             ldi_close(ARPDevHandle, FREAD | FWRITE, kcred);
    1666                                             ldi_ident_release(DevId);
    1667 
    1668                                             LogFlow((DEVICE_NAME ":vboxNetFltSolarisModSetup: Success! %s %s@(Ip:%d Arp:%d) %s %s\n",
    1669                                                     fAttach ? "Attached" : "Detached", StrMod.mod_name, StrMod.pos, ArpStrMod.pos,
    1670                                                     fAttach ? "to" : "from", pThis->szName));
    1671                                             return VINF_SUCCESS;
     1679                                                LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: Raw mode request failed.\n"));
    16721680                                        }
    16731681                                        else
    1674                                             LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: Raw mode request failed.\n"));
     1682                                        {
     1683                                            LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: module relinking failed. Mode=%s rc=%d.\n",
     1684                                                    fAttach ? "inject" : "eject", rc));
     1685                                        }
     1686
     1687                                        /*
     1688                                         * Try failing gracefully during attach.
     1689                                         */
     1690                                        if (fAttach)
     1691                                            strioctl(pVNodeIp, _I_REMOVE, (intptr_t)&StrMod, 0, K_TO_K, kcred, &ret);
    16751692                                    }
    16761693                                    else
    16771694                                    {
    1678                                         LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: module %s or relinking failed. rc=%d rc2=%d rc3=%d.\n",
    1679                                                 fAttach ? "insert" : "remove", rc, rc2, rc3));
    1680 
    1681                                         /*
    1682                                          * Try failing gracefully during attach.
    1683                                          */
    1684                                         /** @todo -XXX- see todo above, and remove later accordingly. */
    1685                                         if (fAttach)
    1686                                         {
    1687                                             strioctl(pVNodeIp, _I_REMOVE, (intptr_t)&StrMod, 0, K_TO_K, kcred, &ret);
    1688                                             strioctl(pVNodeArp, _I_REMOVE, (intptr_t)&ArpStrMod, 0, K_TO_K, kcred, &ret);
    1689                                             vboxNetFltSolarisRelink(pVNodeUDP, &Interface, IpMuxFd, ArpMuxFd);
    1690                                         }
     1695                                        LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: failed to %s the ARP stack. rc=%d\n",
     1696                                                fAttach ? "inject into" : "eject from", rc));
    16911697                                    }
     1698
     1699                                    if (fAttach)
     1700                                        strioctl(pVNodeIp, _I_REMOVE, (intptr_t)&StrMod, 0, K_TO_K, kcred, &ret);
     1701
     1702                                    vboxNetFltSolarisRelink(pVNodeUDP, &Interface, IpMuxFd, ArpMuxFd);
    16921703                                }
    16931704                                else
    1694                                     LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: vboxNetFltSolarisDetermineModPos failed. rc=%d rc2=%d\n", rc, rc2));
     1705                                {
     1706                                    LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: failed to %s the IP stack. rc=%d\n",
     1707                                            fAttach ? "inject into" : "eject from", rc));
     1708                                }
    16951709                            }
    16961710                            else
    1697                                 LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: failed to get vnode from MuxFd.\n"));
     1711                                LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: vboxNetFltSolarisDetermineModPos failed. rc=%d rc2=%d\n", rc, rc2));
    16981712                        }
    16991713                        else
    1700                             LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: failed to unlink upper stream rc=%d rc2=%d.\n", rc, rc2));
     1714                            LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: failed to get vnode from MuxFd.\n"));
    17011715                    }
    17021716                    else
    1703                         LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: failed to get MuxFd from MuxId. rc=%d rc2=%d\n"));
     1717                        LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: failed to unlink upper stream rc=%d rc2=%d.\n", rc, rc2));
    17041718                }
    17051719                else
    1706                     LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: failed to get Mux Ids.\n"));
    1707                 vboxNetFltSolarisCloseDev(pVNodeUDPHeld, pUserUDP);
     1720                    LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: failed to get MuxFd from MuxId. rc=%d rc2=%d\n"));
    17081721            }
    17091722            else
    1710                 LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: failed to open UDP.\n"));
     1723                LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: failed to get Mux Ids.\n"));
     1724            vboxNetFltSolarisCloseDev(pVNodeUDPHeld, pUserUDP);
    17111725        }
    17121726        else
    1713             LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: invalid interface '%s'.\n", pThis->szName));
    1714 
    1715         ldi_close(IPDevHandle, FREAD | FWRITE, kcred);
    1716         ldi_close(ARPDevHandle, FREAD | FWRITE, kcred);
    1717         ldi_ident_release(DevId);
     1727            LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: failed to open UDP.\n"));
    17181728    }
    17191729    else
    1720         LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: failed to open IP and/or ARP!\n"));
     1730        LogRel((DEVICE_NAME ":vboxNetFltSolarisModSetup: invalid interface '%s'.\n", pThis->szName));
     1731
     1732    ldi_close(ARPDevHandle, FREAD | FWRITE, kcred);
     1733    ldi_close(IPDevHandle, FREAD | FWRITE, kcred);
    17211734
    17221735    return VERR_INTNET_FLT_IF_FAILED;
     
    20212034
    20222035    pEtherMsg->b_cont = pMsg->b_cont;
     2036
     2037    /*
     2038     * Change the chained blocks to type M_DATA.
     2039     */
     2040    for (mblk_t *pTmp = pEtherMsg->b_cont; pTmp; pTmp = pTmp->b_cont)
     2041        DB_TYPE(pTmp) = M_DATA;
     2042
    20232043    pMsg->b_cont = NULL;
    20242044    freemsg(pMsg);
     
    20332053 *
    20342054 * @returns VBox status code.
    2035  * @param   pThis   The instance.
    2036  * @param   pQueue  Pointer to the queue.
    2037  * @param   pMsg    Pointer to the message.
    2038  * @param   fSrc    The source of the frame.
    2039  */
    2040 static int vboxNetFltSolarisIOWorker(PVBOXNETFLTINS pThis, queue_t *pQueue, vboxnetflt_stream_t *pStream, mblk_t *pMsg, uint32_t fSrc)
    2041 {
    2042     LogFlow((DEVICE_NAME ":vboxNetFltSolarisIOWorker pThis=%p pQueue=%p pMsg=%p fSrc=%d\n", pThis, pQueue, pMsg, fSrc));
     2055 * @param   pThis       The instance.
     2056 * @param   pStream     Pointer to the stream.
     2057 * @param   pQueue      Pointer to the queue.
     2058 * @param   pOrigMsg    Pointer to the message.
     2059 */
     2060static int vboxNetFltSolarisRecv(PVBOXNETFLTINS pThis, vboxnetflt_stream_t *pStream, queue_t *pQueue, mblk_t *pOrigMsg)
     2061{
     2062    LogFlow((DEVICE_NAME ":vboxNetFltSolarisRecv pThis=%p pOrigMsg=%p\n", pThis, pOrigMsg));
    20432063
    20442064    AssertCompile(sizeof(struct ether_header) == sizeof(RTNETETHERHDR));
     2065    Assert(pStream->Type == kIpStream);
    20452066
    20462067    /*
    20472068     * Make a copy as we will alter pMsg.
    20482069     */
    2049     mblk_t *pOrigMsg = copymsg(pMsg);
     2070    mblk_t *pMsg = copymsg(pOrigMsg);
    20502071
    20512072    /*
     
    20632084        {
    20642085            freemsg(pMsg);
    2065             LogRel((DEVICE_NAME ":vboxNetFltSolarisIOWorker invalid message!\n"));
     2086            LogRel((DEVICE_NAME ":vboxNetFltSolarisRecv invalid message!\n"));
    20662087            return VERR_GENERAL_FAILURE;
    20672088        }
     
    20692090
    20702091    /*
    2071      * Figure out the source of the frame based on the source Mac address.
    2072      */
     2092     * Figure out the source of the packet based on the source Mac address.
     2093     */
     2094    /** @todo Is there a more fool-proof way to determine if the packet was indeed sent from the host?? */
     2095    uint32_t fSrc = INTNETTRUNKDIR_WIRE;
    20732096    PRTNETETHERHDR pEthHdr = (PRTNETETHERHDR)pMsg->b_rptr;
    20742097    if (vboxNetFltPortOsIsHostMac(pThis, &pEthHdr->SrcMac))
    20752098        fSrc = INTNETTRUNKDIR_HOST;
    20762099
     2100    bool fChecksumAdjusted = false;
    20772101#if 0
    2078     vboxNetFltSolarisAnalyzeMBlk(pMsg);
     2102    if (fSrc & INTNETTRUNKDIR_HOST)
     2103    {
     2104        mblk_t *pCorrectedMsg = vboxNetFltSolarisFixChecksums(pMsg);
     2105        if (pCorrectedMsg)
     2106        {
     2107            fChecksumAdjusted = true;
     2108            pMsg = pCorrectedMsg;
     2109        }
     2110    }
    20792111#endif
    20802112
    20812113    /*
    2082      * Don't route ARP stream packets from the wire up the internal network,
    2083      * because we already get them on the IP stream under full promiscous mode.
    2084      * This avoids sending 2 copies of packets into the internal network.
    2085      */
    2086     bool fDropIt = false;
    2087     if (    pStream->Type == kIpStream
    2088          || (pStream->Type == kArpStream && (fSrc & INTNETTRUNKDIR_HOST)))      /** Do we really need these?? */
    2089     {
    2090         unsigned cSegs = vboxNetFltSolarisMBlkCalcSGSegs(pThis, pMsg);
    2091         PINTNETSG pSG = (PINTNETSG)alloca(RT_OFFSETOF(INTNETSG, aSegs[cSegs]));
    2092         int rc = vboxNetFltSolarisMBlkToSG(pThis, pMsg, pSG, cSegs, fSrc);
    2093         if (VBOX_FAILURE(rc))
    2094         {
    2095             LogRel((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG failed. rc=%d\n", rc));
    2096             return rc;
    2097         }
    2098 
    2099         fDropIt = pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, fSrc);
    2100     }
    2101 
     2114     * Route all received packets into the internal network.
     2115     */
     2116    unsigned cSegs = vboxNetFltSolarisMBlkCalcSGSegs(pThis, pMsg);
     2117    PINTNETSG pSG = (PINTNETSG)alloca(RT_OFFSETOF(INTNETSG, aSegs[cSegs]));
     2118    int rc = vboxNetFltSolarisMBlkToSG(pThis, pMsg, pSG, cSegs, fSrc);
     2119    if (VBOX_FAILURE(rc))
     2120    {
     2121        LogRel((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG failed. rc=%d\n", rc));
     2122        return rc;
     2123    }
     2124
     2125    bool fDropIt = pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, fSrc);
     2126
     2127    /*
     2128     * Drop messages consumed by the internal network.
     2129     */
    21022130    if (fDropIt)
    21032131    {
    2104         LogFlow((DEVICE_NAME ":Packet consumed by internal network.\n"));
     2132        LogFlow((DEVICE_NAME ":vboxNetFltSolarisRecv Packet consumed by internal network.\n"));
    21052133        freemsg(pOrigMsg);
    21062134        freemsg(pMsg);
     
    21092137    {
    21102138        /*
    2111          * Packets from the host must be send down as raw mode packets.
    2112          * Packets from the wire, we don't care; just push the original
    2113          * upstream in whatever way we go it.
     2139         * Packets from the host, push them up in raw mode.
     2140         * Packets from the wire, we must push them in their original form
     2141         * as upstream consumers expect this format.
    21142142         */
    21152143        if (pStream->fRawMode)
     
    21172145            if (fSrc & INTNETTRUNKDIR_HOST)
    21182146            {
    2119                 if (fOriginalIsRaw)
     2147                /* Raw packets with correct checksums, pass-through the original */
     2148                if (    fOriginalIsRaw
     2149                    && !fChecksumAdjusted)
     2150                {
    21202151                    putnext(pQueue, pOrigMsg);
    2121                 else
     2152                }
     2153                else    /* For M_PROTO packets or checksum corrected raw packets, pass-through the raw */
    21222154                {
    21232155                    putnext(pQueue, pMsg);
    2124                     pMsg = pOrigMsg;    /* for freeing the M_PROTO message */
     2156                    pMsg = pOrigMsg;        /* for the freemsg that follows */
    21252157                }
    21262158            }
     
    21622194/**
    21632195 * Finalize the message to be fed into the internal network.
    2164  *
     2196 * Verifies and tries to fix checksums for TCP, UDP and IP.
     2197 *
     2198 * @returns Corrected message or NULL if no change was required.
    21652199 * @param   pMsg    Pointer to the message block.
    21662200 *                  This must not be DLPI linked messages, must be M_DATA.
    21672201 *
    2168  * @remarks We don't compute ethernet CRC here.
    2169  */
    2170 static void vboxNetFltSolarisFinalizeMBlk(mblk_t *pMsg)
    2171 {
    2172     LogFlow((DEVICE_NAME ":vboxNetFltSolarisFinalizeMBlk pMsg=%p\n"));
     2202 * @remarks This function expects raw mblk_t (chained is acceptible) and if it
     2203 *          returns a corrected message, the passed in input message has been
     2204 *          freed and should not be referenced anymore.
     2205 */
     2206static mblk_t *vboxNetFltSolarisFixChecksums(mblk_t *pMsg)
     2207{
     2208    LogFlow((DEVICE_NAME ":vboxNetFltSolarisFixChecksums pMsg=%p\n"));
    21732209
    21742210    Assert(DB_TYPE(pMsg) == M_DATA);
    21752211
    2176     /*
    2177      * Concatenate chained mblks.
    2178      */
    2179     if (pMsg->b_cont)
    2180     {
    2181         mblk_t *pFullMsg = allocb(msgdsize(pMsg), BPRI_MED);
    2182         if (!pFullMsg)
    2183         {
    2184             LogRel((DEVICE_NAME ":vboxNetFltSolarisFinalizeMBlk failed to alloc new message.\n"));
    2185             return;
    2186         }
    2187 
    2188         for (mblk_t *pTmp = pMsg; pTmp; pTmp = pTmp->b_cont)
    2189         {
    2190             if (DB_TYPE(pTmp) == M_DATA)
     2212    if (MBLKL(pMsg) < sizeof(RTNETETHERHDR))
     2213    {
     2214        LogRel((DEVICE_NAME ":vboxNetFltSolarisFixChecksums Packet shorter than ethernet header size!\n"));
     2215        return NULL;
     2216    }
     2217
     2218    PRTNETETHERHDR pEthHdr = (PRTNETETHERHDR)pMsg->b_rptr;
     2219    if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPV4))
     2220    {
     2221        /*
     2222         * Check if we have a complete packet or being fed a chain.
     2223         */
     2224        size_t cbIpPacket = 0;
     2225        if (pMsg->b_cont)
     2226        {
     2227            LogFlow((DEVICE_NAME ":Chained mblk_t.\n"));
     2228
     2229            /*
     2230             * Handle chain by making a packet copy to verify if the IP checksum is correct.
     2231             * Contributions to calculating IP checksums from a chained message block with
     2232             * odd/non-pulled up sizes are welcome.
     2233             */
     2234            size_t cbFullMsg = msgdsize(pMsg);
     2235            mblk_t *pFullMsg = allocb(cbFullMsg, BPRI_MED);
     2236            LogFlow((DEVICE_NAME ":msgdsize returns %d\n", cbFullMsg));
     2237            if (RT_UNLIKELY(!pFullMsg))
    21912238            {
    2192                 bcopy(pTmp->b_rptr, pFullMsg->b_wptr, MBLKL(pTmp));
    2193                 pFullMsg->b_wptr += MBLKL(pTmp);
     2239                LogRel((DEVICE_NAME ":vboxNetFltSolarisFixChecksums failed to alloc new message of %d bytes.\n", cbFullMsg));
     2240                return false;
     2241            }
     2242
     2243            for (mblk_t *pTmp = pMsg; pTmp; pTmp = pTmp->b_cont)
     2244            {
     2245                if (DB_TYPE(pTmp) == M_DATA)
     2246                {
     2247                    bcopy(pTmp->b_rptr, pFullMsg->b_wptr, MBLKL(pTmp));
     2248                    pFullMsg->b_wptr += MBLKL(pTmp);
     2249                }
     2250                else
     2251                    LogFlow((DEVICE_NAME ":Not M_DATA.. this is really bad.\n"));
     2252            }
     2253
     2254            freemsg(pMsg);
     2255            pMsg = pFullMsg;
     2256            DB_TYPE(pMsg) = M_DATA;
     2257            pEthHdr = (PRTNETETHERHDR)pMsg->b_rptr;
     2258        }
     2259
     2260        cbIpPacket = MBLKL(pMsg) - sizeof(RTNETETHERHDR);
     2261
     2262        /*
     2263         * Check if the IP checksum is valid.
     2264         */
     2265        PRTNETIPV4 pIpHdr = (PRTNETIPV4)(pEthHdr + 1);
     2266        if (!RTNetIPv4IsHdrValid(pIpHdr, cbIpPacket, cbIpPacket))
     2267        {
     2268            LogFlow((DEVICE_NAME ":Invalid IP checksum detected. Trying to fix...\n"));
     2269
     2270            /*
     2271             * Fix up TCP/UDP and IP checksums if they're incomplete/invalid.
     2272             */
     2273            if (pIpHdr->ip_p == RTNETIPV4_PROT_TCP)
     2274            {
     2275                size_t cbTcpPacket = cbIpPacket - (pIpHdr->ip_hl << 2);
     2276
     2277                PRTNETTCP pTcpHdr = (PRTNETTCP)(pIpHdr + 1);
     2278                if (!RTNetIPv4IsTCPValid(pIpHdr, pTcpHdr, cbTcpPacket, NULL, cbTcpPacket))
     2279                {
     2280                    RTNetIPv4TCPChecksum(pIpHdr, pTcpHdr, NULL);
     2281                    LogFlow((DEVICE_NAME ":fixed TCP checkum.\n"));
     2282                }
     2283                else
     2284                    LogFlow((DEVICE_NAME ":valid TCP checksum invalid IP checksum...\n"));
     2285            }
     2286            else if (pIpHdr->ip_p == RTNETIPV4_PROT_UDP)
     2287            {
     2288                size_t cbUdpPacket = cbIpPacket - (pIpHdr->ip_hl << 2);
     2289
     2290                PRTNETUDP pUdpHdr = (PRTNETUDP)(pIpHdr + 1);
     2291                RTNetIPv4UDPChecksum(pIpHdr, pUdpHdr, pUdpHdr + 1);
     2292
     2293                LogFlow((DEVICE_NAME ":fixed UDP checksum.\n"));
    21942294            }
    21952295            else
    21962296            {
    2197                 LogRel((DEVICE_NAME ":vboxNetFltSolarisFinalizeMBlk non-M_DATA chained message!\n"));
    2198                 freemsg(pFullMsg);
    2199                 return;
     2297                LogFlow((DEVICE_NAME ":Non TCP/UDP protocol with invalid IP header!\n"));
    22002298            }
    2201         }
    2202 
    2203         freemsg(pMsg);
    2204         pMsg = pFullMsg;
    2205         DB_TYPE(pMsg) = M_DATA;
    2206     }
    2207 
    2208     size_t cbMsg = MBLKL(pMsg);
    2209     if (cbMsg > sizeof(RTNETETHERHDR))
    2210     {
    2211         PRTNETETHERHDR pEthHdr = (PRTNETETHERHDR)pMsg->b_rptr;
    2212         if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPV4))
    2213         {
    2214             cbMsg -= sizeof(RTNETETHERHDR);
    2215 
    2216             PRTNETIPV4 pIpHdr = NULL;
    2217             if (cbMsg > sizeof(RTNETIPV4))
    2218                 pIpHdr = (PRTNETIPV4)(pEthHdr + 1);
    2219             else
    2220             {
    2221                 LogRel((DEVICE_NAME ":IP packet too short.\n"));
    2222                 return;
    2223             }
    2224 
    2225             if (RTNetIPv4IsHdrValid(pIpHdr, cbMsg, cbMsg))
    2226             {
    2227 #if 0
    2228                 /*
    2229                  * Fix up TCP checksum.
    2230                  */
    2231                 if (pIpHdr->ip_p == RTNETIPV4_PROT_TCP)
    2232                 {
    2233                     PRTNETTCP pTcpHdr = (PRTNETTCP)(pIpHdr + 1);
    2234                     cbLen -= pIpHdr->ip_hl * 4;
    2235                     if (!RTNetIPv4IsTCPValid(pIpHdr, pTcpHdr, cbLen, NULL, cbLen))
    2236                     {
    2237                         /*
    2238                          * @todo -XXX- this will horribly fail for an mblk_t chain! Fix this later by allocating, copying temp buffer.
    2239                          */
    2240                         RTNetIPv4TCPChecksum(pIpHdr, pTcpHdr, NULL);
    2241                         LogFlow((DEVICE_NAME ":computed TCP checksum.\n"));
    2242                     }
    2243                 }
    2244 
    2245                 /*
    2246                  * Fix up UDP checksum.
    2247                  */
    2248                 if (pIpHdr->ip_p == RTNETIPV4_PROT_UDP)
    2249                 {
    2250                     PRTNETUDP pUdpHdr = (PRTNETUDP)(pIpHdr + 1);
    2251                     cbLen -= pIpHdr->ip_hl * 4;
    2252                     RTNetIPv4UDPChecksum(pIpHdr, pUdpHdr, pUdpHdr + 1);
    2253                     LogFlow((DEVICE_NAME ":computed UDP checksum.\n"));
    2254                 }
    2255                 RTNetIPv4HdrChecksum(pIpHdr);
    2256                 LogFlow((DEVICE_NAME ":computed IP checksum.\n"));
    2257 #endif
    2258             }
    2259             else
    2260             {
    2261                 RTNetIPv4HdrChecksum(pIpHdr);
    2262                 LogFlow((DEVICE_NAME ":Re-Computed IP Header.\n"));
    2263             }
    2264         }
    2265         else
    2266             LogFlow((DEVICE_NAME ":EtherType=%x D=%.6Rhxs S=%.6Rhxs\n", RT_H2BE_U16(pEthHdr->EtherType), &pEthHdr->DstMac, &pEthHdr->SrcMac));
    2267     }
    2268     else
    2269         LogRel((DEVICE_NAME ":Packet shorter than ethernet header size!\n"));
     2299
     2300            RTNetIPv4HdrChecksum(pIpHdr);
     2301            LogFlow((DEVICE_NAME ":fixed IP checkum.\n"));
     2302
     2303            return pMsg;
     2304        }
     2305    }
     2306
     2307    return NULL;
    22702308}
    22712309
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

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