VirtualBox

Changeset 15442 in vbox for trunk/src/VBox/Main/solaris


Ignore:
Timestamp:
Dec 13, 2008 1:40:42 PM (16 years ago)
Author:
vboxsync
Message:

#3282 HostNetIf API: updated common part, added draft implementation for Solaris.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/solaris/NetIfList-solaris.cpp

    r15372 r15442  
    4040#include "netif.h"
    4141
    42 
    43 PNETIFINFO NetIfList()
    44 {
    45     return NULL;
    46 }
    47 
     42#include <list>
     43#include <map>
     44
     45#ifdef VBOX_WITH_HOSTNETIF_API
     46
     47#include <fcntl.h>
     48#include <unistd.h>
     49#include <stropts.h>
     50#include <errno.h>
     51#include <limits.h>
     52#include <stdio.h>
     53#ifdef VBOX_SOLARIS_NSL_RESOLVED
     54# include <libdevinfo.h>
     55#endif
     56#include <net/if.h>
     57#include <sys/socket.h>
     58#include <sys/sockio.h>
     59#include <net/if_arp.h>
     60#include <net/if.h>
     61#include <sys/types.h>
     62
     63static void vboxSolarisAddHostIface(char *pszIface, int Instance, PCRTMAC pMac, void *pvHostNetworkInterfaceList)
     64{
     65    std::list<ComObjPtr <HostNetworkInterface> > *pList = (std::list<ComObjPtr <HostNetworkInterface> > *)pvHostNetworkInterfaceList;
     66    Assert(pList);
     67
     68    typedef std::map <std::string, std::string> NICMap;
     69    typedef std::pair <std::string, std::string> NICPair;
     70    static NICMap SolarisNICMap;
     71    if (SolarisNICMap.empty())
     72    {
     73        SolarisNICMap.insert(NICPair("afe", "ADMtek Centaur/Comet Fast Ethernet"));
     74        SolarisNICMap.insert(NICPair("aggr", "Link Aggregation Interface"));
     75        SolarisNICMap.insert(NICPair("bge", "Broadcom BCM57xx Gigabit Ethernet"));
     76        SolarisNICMap.insert(NICPair("ce", "Cassini Gigabit Ethernet"));
     77        SolarisNICMap.insert(NICPair("chxge", "Chelsio Ethernet"));
     78        SolarisNICMap.insert(NICPair("dmfe", "Davicom Fast Ethernet"));
     79        SolarisNICMap.insert(NICPair("dnet", "DEC 21040/41 21140 Ethernet"));
     80        SolarisNICMap.insert(NICPair("e1000", "Intel PRO/1000 Gigabit Ethernet"));
     81        SolarisNICMap.insert(NICPair("e1000g", "Intel PRO/1000 Gigabit Ethernet"));
     82        SolarisNICMap.insert(NICPair("elx", "3COM EtherLink III Ethernet"));
     83        SolarisNICMap.insert(NICPair("elxl", "3COM Ethernet"));
     84        SolarisNICMap.insert(NICPair("eri", "eri Fast Ethernet"));
     85        SolarisNICMap.insert(NICPair("ge", "GEM Gigabit Ethernet"));
     86        SolarisNICMap.insert(NICPair("hme", "SUNW,hme Fast-Ethernet"));
     87        SolarisNICMap.insert(NICPair("ipge", "PCI-E Gigabit Ethernet"));
     88        SolarisNICMap.insert(NICPair("iprb", "Intel 82557/58/59 Ethernet"));
     89        SolarisNICMap.insert(NICPair("mxfe", "Macronix 98715 Fast Ethernet"));
     90        SolarisNICMap.insert(NICPair("nge", "Nvidia Gigabit Ethernet"));
     91        SolarisNICMap.insert(NICPair("pcelx", "3COM EtherLink III PCMCIA Ethernet"));
     92        SolarisNICMap.insert(NICPair("pcn", "AMD PCnet Ethernet"));
     93        SolarisNICMap.insert(NICPair("qfe", "SUNW,qfe Quad Fast-Ethernet"));
     94        SolarisNICMap.insert(NICPair("rge", "Realtek Gigabit Ethernet"));
     95        SolarisNICMap.insert(NICPair("rtls", "Realtek 8139 Fast Ethernet"));
     96        SolarisNICMap.insert(NICPair("skge", "SksKonnect Gigabit Ethernet"));
     97        SolarisNICMap.insert(NICPair("spwr", "SMC EtherPower II 10/100 (9432) Ethernet"));
     98        SolarisNICMap.insert(NICPair("vnic", "Virtual Network Interface Ethernet"));
     99        SolarisNICMap.insert(NICPair("xge", "Neterior Xframe Gigabit Ethernet"));
     100        SolarisNICMap.insert(NICPair("xge", "Neterior Xframe 10Gigabit Ethernet"));
     101    }
     102
     103    /*
     104     * Try picking up description from our NIC map.
     105     */
     106    char szNICInstance[128];
     107    RTStrPrintf(szNICInstance, sizeof(szNICInstance), "%s%d", pszIface, Instance);
     108    char szNICDesc[256];
     109    std::string Description = SolarisNICMap[pszIface];
     110    if (Description != "")
     111        RTStrPrintf(szNICDesc, sizeof(szNICDesc), "%s - %s", szNICInstance, Description.c_str());
     112    else
     113        RTStrPrintf(szNICDesc, sizeof(szNICDesc), "%s - Ethernet", szNICInstance);
     114
     115    /*
     116     * Construct UUID with interface name and the MAC address if available.
     117     */
     118    RTUUID Uuid;
     119    RTUuidClear(&Uuid);
     120    memcpy(&Uuid, szNICInstance, RT_MIN(strlen(szNICInstance), sizeof(Uuid)));
     121    Uuid.Gen.u8ClockSeqHiAndReserved = (Uuid.Gen.u8ClockSeqHiAndReserved & 0x3f) | 0x80;
     122    Uuid.Gen.u16TimeHiAndVersion = (Uuid.Gen.u16TimeHiAndVersion & 0x0fff) | 0x4000;
     123    if (pMac)
     124    {
     125        Uuid.Gen.au8Node[0] = pMac->au8[0];
     126        Uuid.Gen.au8Node[1] = pMac->au8[1];
     127        Uuid.Gen.au8Node[2] = pMac->au8[2];
     128        Uuid.Gen.au8Node[3] = pMac->au8[3];
     129        Uuid.Gen.au8Node[4] = pMac->au8[4];
     130        Uuid.Gen.au8Node[5] = pMac->au8[5];
     131    }
     132
     133    ComObjPtr<HostNetworkInterface> IfObj;
     134    IfObj.createObject();
     135    if (SUCCEEDED(IfObj->init(Bstr(szNICDesc), Guid(Uuid))))
     136        pList->push_back(IfObj);
     137}
     138
     139static boolean_t vboxSolarisAddLinkHostIface(const char *pszIface, void *pvHostNetworkInterfaceList)
     140{
     141    /*
     142     * Clip off the zone instance number from the interface name (if any).
     143     */
     144    char szIfaceName[128];
     145    strcpy(szIfaceName, pszIface);
     146    char *pszColon = (char *)memchr(szIfaceName, ':', sizeof(szIfaceName));
     147    if (pszColon)
     148        *pszColon = '\0';
     149
     150    /*
     151     * Get the instance number from the interface name, then clip it off.
     152     */
     153    int cbInstance = 0;
     154    int cbIface = strlen(szIfaceName);
     155    const char *pszEnd = pszIface + cbIface - 1;
     156    for (int i = 0; i < cbIface - 1; i++)
     157    {
     158        if (!RT_C_IS_DIGIT(*pszEnd))
     159            break;
     160        cbInstance++;
     161        pszEnd--;
     162    }
     163
     164    int Instance = atoi(pszEnd + 1);
     165    strncpy(szIfaceName, pszIface, cbIface - cbInstance);
     166    szIfaceName[cbIface - cbInstance] = '\0';
     167
     168    /*
     169     * Add the interface.
     170     */
     171    vboxSolarisAddHostIface(szIfaceName, Instance, NULL, pvHostNetworkInterfaceList);
     172
     173    /*
     174     * Continue walking...
     175     */
     176    return _B_FALSE;
     177}
     178
     179static bool vboxSolarisSortNICList(const ComObjPtr <HostNetworkInterface> Iface1, const ComObjPtr <HostNetworkInterface> Iface2)
     180{
     181    Bstr Iface1Str;
     182    (*Iface1).COMGETTER(Name) (Iface1Str.asOutParam());
     183
     184    Bstr Iface2Str;
     185    (*Iface2).COMGETTER(Name) (Iface2Str.asOutParam());
     186
     187    return Iface1Str < Iface2Str;
     188}
     189
     190static bool vboxSolarisSameNIC(const ComObjPtr <HostNetworkInterface> Iface1, const ComObjPtr <HostNetworkInterface> Iface2)
     191{
     192    Bstr Iface1Str;
     193    (*Iface1).COMGETTER(Name) (Iface1Str.asOutParam());
     194
     195    Bstr Iface2Str;
     196    (*Iface2).COMGETTER(Name) (Iface2Str.asOutParam());
     197
     198    return (Iface1Str == Iface2Str);
     199}
     200
     201# ifdef VBOX_SOLARIS_NSL_RESOLVED
     202static int vboxSolarisAddPhysHostIface(di_node_t Node, di_minor_t Minor, void *pvHostNetworkInterfaceList)
     203{
     204    /*
     205     * Skip aggregations.
     206     */
     207    if (!strcmp(di_driver_name(Node), "aggr"))
     208        return DI_WALK_CONTINUE;
     209
     210    /*
     211     * Skip softmacs.
     212     */
     213    if (!strcmp(di_driver_name(Node), "softmac"))
     214        return DI_WALK_CONTINUE;
     215
     216    vboxSolarisAddHostIface(di_driver_name(Node), di_instance(Node), NULL, pvHostNetworkInterfaceList);
     217    return DI_WALK_CONTINUE;
     218}
     219# endif /* VBOX_SOLARIS_NSL_RESOLVED */
     220
     221int NetIfList(std::list <ComObjPtr <HostNetworkInterface> > &list)
     222{
     223
     224#  ifdef VBOX_SOLARIS_NSL_RESOLVED
     225
     226    /*
     227     * Use libdevinfo for determining all physical interfaces.
     228     */
     229    di_node_t Root;
     230    Root = di_init("/", DINFOCACHE);
     231    if (Root != DI_NODE_NIL)
     232    {
     233        di_walk_minor(Root, DDI_NT_NET, 0, &list, vboxSolarisAddPhysHostIface);
     234        di_fini(Root);
     235    }
     236
     237    /*
     238     * Use libdlpi for determining all DLPI interfaces.
     239     */
     240    if (VBoxSolarisLibDlpiFound())
     241        g_pfnLibDlpiWalk(vboxSolarisAddLinkHostIface, &list, 0);
     242
     243#  endif    /* VBOX_SOLARIS_NSL_RESOLVED */
     244
     245    /*
     246     * This gets only the list of all plumbed logical interfaces.
     247     * This is needed for zones which cannot access the device tree
     248     * and in this case we just let them use the list of plumbed interfaces
     249     * on the zone.
     250     */
     251    int Sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
     252    if (Sock > 0)
     253    {
     254        struct lifnum IfNum;
     255        memset(&IfNum, 0, sizeof(IfNum));
     256        IfNum.lifn_family = AF_INET;
     257        int rc = ioctl(Sock, SIOCGLIFNUM, &IfNum);
     258        if (!rc)
     259        {
     260            struct lifreq Ifaces[24];
     261            struct lifconf IfConfig;
     262            memset(&IfConfig, 0, sizeof(IfConfig));
     263            IfConfig.lifc_family = AF_INET;
     264            IfConfig.lifc_len = sizeof(Ifaces);
     265            IfConfig.lifc_buf = (caddr_t)&(Ifaces[0]);
     266            rc = ioctl(Sock, SIOCGLIFCONF, &IfConfig);
     267            if (!rc)
     268            {
     269                for (int i = 0; i < IfNum.lifn_count; i++)
     270                {
     271                    /*
     272                     * Skip loopback interfaces.
     273                     */
     274                    if (!strncmp(Ifaces[i].lifr_name, "lo", 2))
     275                        continue;
     276
     277                    NETIFINFO Info;
     278                    memset(&Info, 0, sizeof(Info));
     279                    rc = ioctl(Sock, SIOCGLIFADDR, &(Ifaces[i]));
     280                    if (rc >= 0)
     281                    {
     282                        memcpy(Info.IPAddress.au8, &Ifaces[i].lifr_addr.sa_data, Info.IPAddress.au8);
     283                        // SIOCGLIFNETMASK
     284                        struct arpreq ArpReq;
     285                        memcpy(&ArpReq.arp_pa, &Ifaces[i].lifr_addr, sizeof(struct sockaddr_in));
     286
     287                        /*
     288                         * We might fail if the interface has not been assigned an IP address.
     289                         * That doesn't matter; as long as it's plumbed we can pick it up.
     290                         * But, if it has not acquired an IP address we cannot obtain it's MAC
     291                         * address this way, so we just use all zeros there.
     292                         */
     293                        rc = ioctl(Sock, SIOCGARP, &ArpReq);
     294                        if (rc >= 0)
     295                            memcpy(&Info.MACAddress, ArpReq.arp_ha.sa_data, sizeof(Info.MACAddress));
     296
     297#if 0
     298                        char szNICDesc[LIFNAMSIZ + 256];
     299                        char *pszIface = Ifaces[i].lifr_name;
     300                        strcpy(szNICDesc, pszIface);
     301
     302                        vboxSolarisAddLinkHostIface(pszIface, &list);
     303#endif
     304                    }
     305
     306                    rc = ioctl(Sock, SIOCGLIFNETMASK, &(Ifaces[i]));
     307                    if (rc >= 0)
     308                    {
     309                        memcpy(Info.IPNetMask.au8, &Ifaces[i].lifr_addr.sa_data, Info.IPNetMask.au8);
     310                    }
     311                    rc = ioctl(Sock, SIOCGLIFFLAGS, &(Ifaces[i]));
     312                    if (rc >= 0)
     313                    {
     314                        Info.enmStatus = Ifaces[i].lifr_flags & IFF_UP ? NETIF_S_UP : NETIF_S_DOWN;
     315                    }
     316                    char *pszIface = Ifaces[i].lifr_name;
     317                    vboxSolarisAddLinkHostIface(pszIface, &list);
     318                }
     319            }
     320        }
     321        close(Sock);
     322    }
     323
     324    /*
     325     * Weed out duplicates caused by dlpi_walk inconsistencies across Nevadas.
     326     */
     327    list.sort(vboxSolarisSortNICList);
     328    list.unique(vboxSolarisSameNIC);
     329
     330    return VINF_SUCCESS;
     331}
     332#else
     333int NetIfList(std::list <ComObjPtr <HostNetworkInterface> > &list)
     334{
     335    return VERR_NOT_IMPLEMENTED;
     336}
     337#endif
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