VirtualBox

Changeset 56143 in vbox for trunk/src


Ignore:
Timestamp:
May 28, 2015 7:47:00 PM (10 years ago)
Author:
vboxsync
Message:

VBoxNetFlt/linux: Instead of fighting an uphill battle with ifdefs to
loop over all net devices, abuse/co-opt register_netdevice_notifier()
to do that for us.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c

    r56120 r56143  
    5555#include "../VBoxNetFltInternal.h"
    5656
     57typedef struct VBOXNETFLTNOTIFIER {
     58    struct notifier_block Notifier;
     59    PVBOXNETFLTINS pThis;
     60} VBOXNETFLTNOTIFIER;
     61typedef struct VBOXNETFLTNOTIFIER *PVBOXNETFLTNOTIFIER;
     62
     63
    5764#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 20, 0)
    5865# define vlan_tx_tag_get(skb)       skb_vlan_tag_get(skb)
     
    7077#endif
    7178
     79#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
     80# define VBOX_NETDEV_NOTIFIER_INFO_TO_DEV(ptr) netdev_notifier_info_to_dev(ptr)
     81#else
     82# define VBOX_NETDEV_NOTIFIER_INFO_TO_DEV(ptr) ((struct net_device *)ptr)
     83#endif
     84
    7285#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
    7386# define VBOX_NETDEV_NAME(dev)              netdev_name(dev)
    7487#else
    7588# define VBOX_NETDEV_NAME(dev)              ((dev)->reg_state != NETREG_REGISTERED ? "(unregistered net_device)" : (dev)->name)
    76 #endif
    77 
    78 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
    79 # define VBOX_DEV_NET(dev)                  dev_net(dev)
    80 #else
    81 # define VBOX_DEV_NET(dev)                  ((dev)->nd_net)
    8289#endif
    8390
     
    18261833    PVBOXNETFLTINS      pThis = VBOX_FLT_NB_TO_INST(self);
    18271834    struct net_device  *pMyDev = ASMAtomicUoReadPtrT(&pThis->u.s.pDev, struct net_device *);
    1828 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
    1829     struct net_device  *pDev  = netdev_notifier_info_to_dev(ptr);
    1830 #else
    1831     struct net_device  *pDev  = (struct net_device *)ptr;
    1832 #endif
     1835    struct net_device  *pDev  = VBOX_NETDEV_NOTIFIER_INFO_TO_DEV(ptr);
    18331836    int                 rc    = NOTIFY_OK;
    18341837
     
    18731876}
    18741877
    1875 #if 0 /* XXX: temporarily disable */
     1878static int vboxNetFltLinuxEnumeratorCallback(struct notifier_block *self, unsigned long ulEventType, void *ptr)
     1879{
     1880    PVBOXNETFLTINS pThis = ((PVBOXNETFLTNOTIFIER)self)->pThis;
     1881    struct net_device *dev  = VBOX_NETDEV_NOTIFIER_INFO_TO_DEV(ptr);
     1882    struct in_device *in_dev;
     1883    struct inet6_dev *in6_dev;
     1884
     1885    if (ulEventType != NETDEV_REGISTER)
     1886        return NOTIFY_OK;
     1887
     1888    if (RT_UNLIKELY(pThis->pSwitchPort->pfnNotifyHostAddress == NULL))
     1889        return NOTIFY_OK;
     1890
     1891    /*
     1892     * IPv4
     1893     */
     1894    in_dev = __in_dev_get_rcu(dev);
     1895    if (in_dev != NULL)
     1896    {
     1897        for_ifa(in_dev) {
     1898            if (IN_LOOPBACK(ntohl(ifa->ifa_address)))
     1899                return NOTIFY_OK;
     1900
     1901            Log(("%s: %s: IPv4 addr %RTnaipv4 mask %RTnaipv4\n",
     1902                 __FUNCTION__, VBOX_NETDEV_NAME(dev),
     1903                 ifa->ifa_address, ifa->ifa_mask));
     1904           
     1905            pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort,
     1906                /* :fAdded */ true, kIntNetAddrType_IPv4, &ifa->ifa_address);
     1907        } endfor_ifa(in_dev);
     1908    }
     1909
     1910    /*
     1911     * IPv6
     1912     */
     1913    in6_dev = __in6_dev_get(dev);
     1914    if (in6_dev != NULL)
     1915    {
     1916        struct inet6_ifaddr *ifa;
     1917
     1918        read_lock_bh(&in6_dev->lock);
     1919#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
     1920        list_for_each_entry(ifa, &in6_dev->addr_list, if_list)
     1921#else
     1922        for (ifa = in6_dev->addr_list; ifa != NULL; ifa = ifa->if_next)
     1923#endif
     1924        {
     1925            if (   dev != pThis->u.s.pDev
     1926                && ipv6_addr_src_scope(&ifa->addr) <= IPV6_ADDR_SCOPE_LINKLOCAL)
     1927                continue;
     1928
     1929            Log(("%s: %s: IPv6 addr %RTnaipv6/%u\n",
     1930                 __FUNCTION__, VBOX_NETDEV_NAME(dev),
     1931                 &ifa->addr, (unsigned)ifa->prefix_len));
     1932
     1933            pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort,
     1934                /* :fAdded */ true, kIntNetAddrType_IPv6, &ifa->addr);
     1935        }
     1936        read_unlock_bh(&in6_dev->lock);
     1937    }
     1938
     1939    return NOTIFY_OK;
     1940}
     1941
     1942
    18761943static int vboxNetFltLinuxNotifierIPv4Callback(struct notifier_block *self, unsigned long ulEventType, void *ptr)
    18771944{
     
    19402007    return rc;
    19412008}
    1942 #endif /* 0 */
    19432009
    19442010
     
    21702236        return VERR_INTNET_FLT_IF_FAILED;
    21712237
    2172 #if 0 /* XXX: temporarily disable */
    21732238    if (pThis->pSwitchPort->pfnNotifyHostAddress)
    21742239    {
    2175         struct net *net = VBOX_DEV_NET(pThis->u.s.pDev);
    2176         struct net_device *dev;
    2177 
    2178 #if !defined(for_each_netdev_rcu) /* introduced in 2.6.33 */
    2179         read_lock(&dev_base_lock);
    2180 #endif
    2181         rcu_read_lock();
    2182 
    2183 #if !defined(for_each_netdev_rcu)
    2184         for_each_netdev(net, dev)
    2185 #else
    2186         for_each_netdev_rcu(net, dev)
    2187 #endif
    2188         {
    2189             struct in_device *in_dev;
    2190             struct inet6_dev *in6_dev;
    2191 
    2192             /*
    2193              * IPv4
    2194              */
    2195             in_dev = __in_dev_get_rcu(dev);
    2196             if (in_dev != NULL)
    2197             {
    2198                 for_ifa(in_dev) {
    2199                     if (ifa->ifa_address == htonl(INADDR_LOOPBACK))
    2200                         goto continue_netdev;
    2201 
    2202                     Log(("%s: %s: IPv4: addr %RTnaipv4 mask %RTnaipv4\n",
    2203                          __FUNCTION__, VBOX_NETDEV_NAME(dev),
    2204                          ifa->ifa_address, ifa->ifa_mask));
    2205 
    2206                     pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort,
    2207                         /* :fAdded */ true, kIntNetAddrType_IPv4, &ifa->ifa_address);
    2208                 } endfor_ifa(in_dev);
    2209             }
    2210 
    2211             /*
    2212              * IPv6
    2213              */
    2214             in6_dev = __in6_dev_get(dev);
    2215             if (in6_dev != NULL)
    2216             {
    2217                 struct inet6_ifaddr *ifa;
    2218 
    2219                 read_lock_bh(&in6_dev->lock);
    2220 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
    2221                 list_for_each_entry(ifa, &in6_dev->addr_list, if_list)
    2222 #else
    2223                 for (ifa = in6_dev->addr_list; ifa != NULL; ifa = ifa->if_next)
    2224 #endif
    2225                 {
    2226                     Log(("%s: %s: IPv6: addr %RTnaipv6/%u\n",
    2227                          __FUNCTION__, VBOX_NETDEV_NAME(dev),
    2228                          &ifa->addr, (unsigned)ifa->prefix_len));
    2229 
    2230                     pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort,
    2231                         /* :fAdded */ true, kIntNetAddrType_IPv6, &ifa->addr);
    2232                 }
    2233                 read_unlock_bh(&in6_dev->lock);
    2234             }
    2235 
    2236           continue_netdev:
    2237             /* continue */;
    2238         }
    2239         rcu_read_unlock();
    2240 #if !defined(for_each_netdev_rcu)
    2241         read_unlock(&dev_base_lock);
    2242 #endif
    2243 
    2244         Log(("%s: pfnNotifyHostAddress is set, register notifiers\n", __FUNCTION__));
     2240        VBOXNETFLTNOTIFIER Enumerator;
     2241
     2242        /*
     2243         * register_inetaddr_notifier() and register_inet6addr_notifier()
     2244         * do not call the callback for existing devices.  Enumerating
     2245         * all network devices explicitly is a bit of an ifdef mess,
     2246         * so co-opt register_netdevice_notifier() to do that for us.
     2247         */
     2248        RT_ZERO(Enumerator);
     2249        Enumerator.Notifier.notifier_call = vboxNetFltLinuxEnumeratorCallback;
     2250        Enumerator.pThis = pThis;
     2251
     2252        err = register_netdevice_notifier(&Enumerator.Notifier);
     2253        if (err)
     2254        {
     2255            LogRel(("%s: failed to enumerate network devices: error %d\n",
     2256                    __FUNCTION__, err));
     2257            return VINF_SUCCESS;
     2258        }
     2259
     2260        unregister_netdevice_notifier(&Enumerator.Notifier);
    22452261
    22462262        pThis->u.s.NotifierIPv4.notifier_call = vboxNetFltLinuxNotifierIPv4Callback;
     
    22562272                    __FUNCTION__, err));
    22572273    }
    2258     else
    2259         Log(("%s: uwe: pfnNotifyHostAddress is NULL\n", __FUNCTION__));
    2260 #endif
    22612274
    22622275    return VINF_SUCCESS;
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