Méthode fiable pour obtenir l'adresse MAC de la machine en C #


132

J'ai besoin d'un moyen d'obtenir l'adresse MAC d'une machine quel que soit le système d'exploitation qu'elle exécute en utilisant C #. L'application devra fonctionner sur XP / Vista / Win7 32 et 64 bits ainsi que sur ces systèmes d'exploitation mais avec une langue étrangère par défaut. De nombreuses commandes C # et requêtes de système d'exploitation ne fonctionnent pas sur tous les systèmes d'exploitation. Des idées? J'ai gratté la sortie de "ipconfig / all" mais c'est terriblement peu fiable car le format de sortie diffère sur chaque machine.

Merci


7
Quand vous dites à travers OS, vous voulez dire à travers différents OS Microsoft?
John Weldon

Réponses:


137

Solution plus propre

var macAddr = 
    (
        from nic in NetworkInterface.GetAllNetworkInterfaces()
        where nic.OperationalStatus == OperationalStatus.Up
        select nic.GetPhysicalAddress().ToString()
    ).FirstOrDefault();

Ou:

String firstMacAddress = NetworkInterface
    .GetAllNetworkInterfaces()
    .Where( nic => nic.OperationalStatus == OperationalStatus.Up && nic.NetworkInterfaceType != NetworkInterfaceType.Loopback )
    .Select( nic => nic.GetPhysicalAddress().ToString() )
    .FirstOrDefault();

44
Ou lambda, si c'est votre truc! return NetworkInterface.GetAllNetworkInterfaces().Where(nic => nic.OperationalStatus == OperationalStatus.Up).Select(nic => nic.GetPhysicalAddress().ToString()).FirstOrDefault();(Si ce n'est pas votre truc, ça devrait être votre truc.)
GONeale

7
Moyen concis pour obtenir le plus rapide: var networks = NetworkInterface.GetAllNetworkInterfaces(); var activeNetworks = networks.Where(ni => ni.OperationalStatus == OperationalStatus.Up && ni.NetworkInterfaceType != NetworkInterfaceType.Loopback); var sortedNetworks = activeNetworks.OrderByDescending(ni => ni.Speed); return sortedNetworks.First().GetPhysicalAddress().ToString();
Graham Laight

1
La sélection en premier n'est pas toujours la meilleure option. Sélection de la connexion la plus utilisée: stackoverflow.com/a/51821927/3667
Ramunas

Note d'optimisation: vous pouvez appeler FirstOrDefaultavant la finale Select. De cette façon, il n'obtiendrait que l'adresse physique et la sérialiserait pour ce NetworkInterfaceque vous obtenez. N'oubliez pas d'ajouter le contrôle nul (?) Après le FirstOrDefault.
GregaMohorko

Un moyen de calcul plus rapide pour l'obtenir, vous n'avez pas besoin d'évaluer tous les réseaux qui correspondent à la condition donnée, vous n'avez besoin que du premier d'entre eux: NetworkInterface .GetAllNetworkInterfaces() .FirstOrDefault(nic => nic.OperationalStatus == OperationalStatus.Up && nic.NetworkInterfaceType != NetworkInterfaceType.Loopback)? .GetPhysicalAddress().ToString();
Alessandro Muzzi

80

Voici un code C # qui renvoie l'adresse MAC de la première interface réseau opérationnelle. En supposant que l' NetworkInterfaceassembly est implémenté dans le runtime (c'est-à-dire Mono) utilisé sur d'autres systèmes d'exploitation, cela fonctionnerait sur d'autres systèmes d'exploitation.

Nouvelle version: renvoie le NIC avec la vitesse la plus rapide qui a également une adresse MAC valide.

/// <summary>
/// Finds the MAC address of the NIC with maximum speed.
/// </summary>
/// <returns>The MAC address.</returns>
private string GetMacAddress()
{
    const int MIN_MAC_ADDR_LENGTH = 12;
    string macAddress = string.Empty;
    long maxSpeed = -1;

    foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
    {
        log.Debug(
            "Found MAC Address: " + nic.GetPhysicalAddress() +
            " Type: " + nic.NetworkInterfaceType);

        string tempMac = nic.GetPhysicalAddress().ToString();
        if (nic.Speed > maxSpeed &&
            !string.IsNullOrEmpty(tempMac) &&
            tempMac.Length >= MIN_MAC_ADDR_LENGTH)
        {
            log.Debug("New Max Speed = " + nic.Speed + ", MAC: " + tempMac);
            maxSpeed = nic.Speed;
            macAddress = tempMac;
        }
    }

    return macAddress;
}

Version originale: renvoie simplement le premier.

/// <summary>
/// Finds the MAC address of the first operation NIC found.
/// </summary>
/// <returns>The MAC address.</returns>
private string GetMacAddress()
{
    string macAddresses = string.Empty;

    foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
    {
        if (nic.OperationalStatus == OperationalStatus.Up)
        {
            macAddresses += nic.GetPhysicalAddress().ToString();
            break;
        }
    }

    return macAddresses;
}

La seule chose que je n'aime pas dans cette approche, c'est que si vous avez comme un Nortel Packet Miniport ou un type de connexion VPN, il a le potentiel d'être choisi. Pour autant que je sache, il n'y a aucun moyen de distinguer le MAC d'un périphérique physique réel d'un certain type d'interface réseau virtuelle.


6
Ne choisissez pas seulement la première interface opérationnelle. Cela pourrait renvoyer des interfaces de bouclage, des cartes 3G parfois connectées, etc., qui ne sont probablement pas ce que vous voulez. Le NetworkInterfaceType ( msdn.microsoft.com/en-us/library/… ) vous donnera plus d'informations sur la connexion NetworkInterface afin que vous puissiez faire un choix plus éclairé. Gardez également à l'esprit qu'il peut y avoir de nombreuses connexions actives sur une machine et que leur ordre peut ne pas être prévisible.
Dave R.

@DaveR. J'ai regardé NetworkInterfaceType, il renvoie presque toujours Ethernet même s'il s'agissait d'un adaptateur virtuel dans mon expérience, donc je l'ai trouvé assez inutile.
blak3r

1
Vous devez choisir l'interface avec le GatewayMetric le plus bas. Il doit s'agir de la connexion qui a "l'itinéraire le plus rapide, le plus fiable ou le moins gourmand en ressources". Fondamentalement, cela vous donnera l'interface que Windows préfère utiliser. Cependant, je pense que vous avez besoin de WMI pour l'obtenir. Je vais voir si je peux faire fonctionner ça ...
AVee

6
Pour être complet, la classe NetworkInterface est accessible avecusing System.Net.NetworkInformation;
iancoleman

1
FWIW, si vous avez un NIC gigabit et Hyper-V installé, vous aurez également un NIC virtuel 10gigabit. :) Problème difficile à résoudre ...
Christopher Painter

10

La propriété MACAddress de la classe WMI Win32_NetworkAdapterConfiguration peut vous fournir l'adresse MAC d'un adaptateur. (Espace de noms System.Management)

MACAddress

    Data type: string
    Access type: Read-only

    Media Access Control (MAC) address of the network adapter. A MAC address is assigned by the manufacturer to uniquely identify the network adapter.

    Example: "00:80:C7:8F:6C:96"

Si vous n'êtes pas familier avec l'API WMI (Windows Management Instrumentation), vous trouverez ici un bon aperçu des applications .NET.

WMI est disponible dans toutes les versions de Windows avec le runtime .Net.

Voici un exemple de code:

System.Management.ManagementClass mc = default(System.Management.ManagementClass);
ManagementObject mo = default(ManagementObject);
mc = new ManagementClass("Win32_NetworkAdapterConfiguration");

ManagementObjectCollection moc = mc.GetInstances();
    foreach (var mo in moc) {
        if (mo.Item("IPEnabled") == true) {
              Adapter.Items.Add("MAC " + mo.Item("MacAddress").ToString());
         }
     }

9

WMI est la meilleure solution si la machine à laquelle vous vous connectez est une machine Windows, mais si vous recherchez un linux, un mac ou un autre type d'adaptateur réseau, vous devrez utiliser autre chose. Voici quelques options:

  1. Utilisez la commande DOS nbtstat -a. Créez un processus, appelez cette commande, analysez la sortie.
  2. Envoyez d'abord un ping à l'adresse IP pour vous assurer que votre carte réseau met en cache la commande dans sa table ARP, puis utilisez la commande DOS arp -a. Analysez la sortie du processus comme dans l'option 1.
  3. Utilisez un appel non géré redouté à sendarp dans le fichier iphlpapi.dll

Voici un échantillon de l'article n ° 3. Cela semble être la meilleure option si WMI n'est pas une solution viable:

using System.Runtime.InteropServices;
...
[DllImport("iphlpapi.dll", ExactSpelling = true)]
        public static extern int SendARP(int DestIP, int SrcIP, byte[] pMacAddr, ref uint PhyAddrLen);
...
private string GetMacUsingARP(string IPAddr)
{
    IPAddress IP = IPAddress.Parse(IPAddr);
    byte[] macAddr = new byte[6];
    uint macAddrLen = (uint)macAddr.Length;

    if (SendARP((int)IP.Address, 0, macAddr, ref macAddrLen) != 0)
        throw new Exception("ARP command failed");

    string[] str = new string[(int)macAddrLen];
    for (int i = 0; i < macAddrLen; i++)
        str[i] = macAddr[i].ToString("x2");

    return string.Join(":", str);
}

Pour donner du crédit là où il est dû, voici la base de ce code: http://www.pinvoke.net/default.aspx/iphlpapi.sendarp#


Je cherchais la même chose que l'OP et c'est exactement ce dont j'avais besoin!
QueueHammer

Dans les options 1 et 2, vous voulez dire des commandes DOS si vous êtes sur une machine Windows et la commande équivalente sur Linux ou Mac, non?
Raikol Amaro

8

Nous utilisons WMI pour obtenir l'adresse mac de l'interface avec la métrique la plus basse, par exemple les fenêtres d'interface préféreront utiliser, comme ceci:

public static string GetMACAddress()
{
    ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration where IPEnabled=true");
    IEnumerable<ManagementObject> objects = searcher.Get().Cast<ManagementObject>();
    string mac = (from o in objects orderby o["IPConnectionMetric"] select o["MACAddress"].ToString()).FirstOrDefault();
    return mac;
}

Ou dans Silverlight (nécessite une confiance accrue):

public static string GetMACAddress()
{
    string mac = null;
    if ((Application.Current.IsRunningOutOfBrowser) && (Application.Current.HasElevatedPermissions) && (AutomationFactory.IsAvailable))
    {
        dynamic sWbemLocator = AutomationFactory.CreateObject("WbemScripting.SWBemLocator");
        dynamic sWbemServices = sWbemLocator.ConnectServer(".");
        sWbemServices.Security_.ImpersonationLevel = 3; //impersonate

        string query = "SELECT * FROM Win32_NetworkAdapterConfiguration where IPEnabled=true";
        dynamic results = sWbemServices.ExecQuery(query);

        int mtu = int.MaxValue;
        foreach (dynamic result in results)
        {
            if (result.IPConnectionMetric < mtu)
            {
                mtu = result.IPConnectionMetric;
                mac = result.MACAddress;
            }
        }
    }
    return mac;
}

7
public static PhysicalAddress GetMacAddress()
{
    var myInterfaceAddress = NetworkInterface.GetAllNetworkInterfaces()
        .Where(n => n.OperationalStatus == OperationalStatus.Up && n.NetworkInterfaceType != NetworkInterfaceType.Loopback)
        .OrderByDescending(n => n.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
        .Select(n => n.GetPhysicalAddress())
        .FirstOrDefault();

    return myInterfaceAddress;
}

Si j'exécute ce code, obtiendra-t-il l'adresse de la personne exécutant l'application? Cela signifie qu'il n'obtiendra pas l'adresse IP du serveur où il est hébergé, n'est-ce pas?
Nate Pet

Il obtient l'adresse MAC de la machine hôte, le serveur.
Tony

6

IMHO renvoyer la première adresse mac n'est pas une bonne idée, en particulier lorsque les machines virtuelles sont hébergées. Par conséquent, je vérifie la somme des octets envoyés / reçus et sélectionne la connexion la plus utilisée, qui n'est pas parfaite, mais devrait être correcte 9/10 fois.

public string GetDefaultMacAddress()
{
    Dictionary<string, long> macAddresses = new Dictionary<string, long>();
    foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
    {
        if (nic.OperationalStatus == OperationalStatus.Up)
            macAddresses[nic.GetPhysicalAddress().ToString()] = nic.GetIPStatistics().BytesSent + nic.GetIPStatistics().BytesReceived;
    }
    long maxValue = 0;
    string mac = "";
    foreach(KeyValuePair<string, long> pair in macAddresses)
    {
        if (pair.Value > maxValue)
        {
            mac = pair.Key;
            maxValue = pair.Value;
        }
    }
    return mac;
}

6

Cette méthode déterminera l'adresse MAC de l'interface réseau utilisée pour se connecter à l'url et au port spécifiés.

Toutes les réponses ici ne sont pas capables d'atteindre cet objectif.

J'ai écrit cette réponse il y a des années (en 2014). J'ai donc décidé de lui donner un petit "lifting". Veuillez consulter la section des mises à jour

    /// <summary>
    /// Get the MAC of the Netowrk Interface used to connect to the specified url.
    /// </summary>
    /// <param name="allowedURL">URL to connect to.</param>
    /// <param name="port">The port to use. Default is 80.</param>
    /// <returns></returns>
    private static PhysicalAddress GetCurrentMAC(string allowedURL, int port = 80)
    {
        //create tcp client
        var client = new TcpClient();

        //start connection
        client.Client.Connect(new IPEndPoint(Dns.GetHostAddresses(allowedURL)[0], port));

        //wai while connection is established
        while(!client.Connected)
        {
            Thread.Sleep(500);
        }

        //get the ip address from the connected endpoint
        var ipAddress = ((IPEndPoint)client.Client.LocalEndPoint).Address;

        //if the ip is ipv4 mapped to ipv6 then convert to ipv4
        if(ipAddress.IsIPv4MappedToIPv6)
            ipAddress = ipAddress.MapToIPv4();        

        Debug.WriteLine(ipAddress);

        //disconnect the client and free the socket
        client.Client.Disconnect(false);
        
        //this will dispose the client and close the connection if needed
        client.Close();

        var allNetworkInterfaces = NetworkInterface.GetAllNetworkInterfaces();

        //return early if no network interfaces found
        if(!(allNetworkInterfaces?.Length > 0))
            return null;

        foreach(var networkInterface in allNetworkInterfaces)
        {
            //get the unicast address of the network interface
            var unicastAddresses = networkInterface.GetIPProperties().UnicastAddresses;
           
            //skip if no unicast address found
            if(!(unicastAddresses?.Count > 0))
                continue;

            //compare the unicast addresses to see 
            //if any match the ip address used to connect over the network
            for(var i = 0; i < unicastAddresses.Count; i++)
            {
                var unicastAddress = unicastAddresses[i];

                //this is unlikely but if it is null just skip
                if(unicastAddress.Address == null)
                    continue;
                
                var ipAddressToCompare = unicastAddress.Address;

                Debug.WriteLine(ipAddressToCompare);

                //if the ip is ipv4 mapped to ipv6 then convert to ipv4
                if(ipAddressToCompare.IsIPv4MappedToIPv6)
                    ipAddressToCompare = ipAddressToCompare.MapToIPv4();

                Debug.WriteLine(ipAddressToCompare);

                //skip if the ip does not match
                if(!ipAddressToCompare.Equals(ipAddress))
                    continue;

                //return the mac address if the ip matches
                return networkInterface.GetPhysicalAddress();
            }
              
        }

        //not found so return null
        return null;
    }

Pour l'appeler, vous devez passer une URL pour vous connecter comme ceci:

var mac = GetCurrentMAC("www.google.com");

Vous pouvez également spécifier un numéro de port. Si non spécifié, la valeur par défaut est 80.

MISES À JOUR:

2020

  • Ajout de commentaires pour expliquer le code.
  • Corrigé pour être utilisé avec les systèmes d'exploitation plus récents qui utilisent IPV4 mappé sur IPV6 (comme Windows 10).
  • Nidification réduite.
  • Mise à jour du code en utilisant "var".

1
C'est très intéressant, je vais l'essayer, car dans mon cas j'aimerais que le client découvre a) l'adresse source utilisée pour communiquer avec mon serveur (ce ne sera PAS forcément sur internet) et b) quelle est l'adresse MAC est du NIC qui fournit cette adresse IP ...
Brian B

5

Vous pouvez opter pour l'ID NIC:

 foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) {
     if (nic.OperationalStatus == OperationalStatus.Up){
         if (nic.Id == "yay!")
     }
 }

Ce n'est pas l'adresse MAC, mais c'est un identifiant unique, si c'est ce que vous recherchez.


2

J'aime vraiment la solution d'AVee avec la métrique de connexion IP la plus basse! Mais si une deuxième carte réseau avec la même métrique est installée, la comparaison MAC pourrait échouer ...

Mieux vaut stocker la description de l'interface avec le MAC. Dans les comparaisons ultérieures, vous pouvez identifier le bon nic par cette chaîne. Voici un exemple de code:

   public static string GetMacAndDescription()
    {
        ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration where IPEnabled=true");
        IEnumerable<ManagementObject> objects = searcher.Get().Cast<ManagementObject>();
        string mac = (from o in objects orderby o["IPConnectionMetric"] select o["MACAddress"].ToString()).FirstOrDefault();
        string description = (from o in objects orderby o["IPConnectionMetric"] select o["Description"].ToString()).FirstOrDefault();
        return mac + ";" + description;
    }

    public static string GetMacByDescription( string description)
    {
        ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration where IPEnabled=true");
        IEnumerable<ManagementObject> objects = searcher.Get().Cast<ManagementObject>();
        string mac = (from o in objects where o["Description"].ToString() == description select o["MACAddress"].ToString()).FirstOrDefault();
        return mac;
    }

2

disons que j'ai un TcpConnection utilisant mon adresse IP locale de 192.168.0.182. Ensuite, si je souhaite connaître l'adresse mac de cette carte réseau, j'appellerai le meothod comme suit:GetMacAddressUsedByIp("192.168.0.182")

public static string GetMacAddressUsedByIp(string ipAddress)
    {
        var ips = new List<string>();
        string output;

        try
        {
            // Start the child process.
            Process p = new Process();
            // Redirect the output stream of the child process.
            p.StartInfo.UseShellExecute = false;

            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.FileName = "ipconfig";
            p.StartInfo.Arguments = "/all";
            p.Start();
            // Do not wait for the child process to exit before
            // reading to the end of its redirected stream.
            // p.WaitForExit();
            // Read the output stream first and then wait.
            output = p.StandardOutput.ReadToEnd();
            p.WaitForExit();

        }
        catch
        {
            return null;
        }

        // pattern to get all connections
        var pattern = @"(?xis) 
(?<Header>
     (\r|\n) [^\r]+ :  \r\n\r\n
)
(?<content>
    .+? (?= ( (\r\n\r\n)|($)) )
)";

        List<Match> matches = new List<Match>();

        foreach (Match m in Regex.Matches(output, pattern))
            matches.Add(m);

        var connection = matches.Select(m => new
        {
            containsIp = m.Value.Contains(ipAddress),
            containsPhysicalAddress = Regex.Match(m.Value, @"(?ix)Physical \s Address").Success,
            content = m.Value
        }).Where(x => x.containsIp && x.containsPhysicalAddress)
        .Select(m => Regex.Match(m.content, @"(?ix)  Physical \s address [^:]+ : \s* (?<Mac>[^\s]+)").Groups["Mac"].Value).FirstOrDefault();

        return connection;
    }

Ce n'est pas efficace ... Je ne recommanderais pas de faire cela.
Ivandro IG Jao

2

Je déteste vraiment déterrer ce vieux message, mais je pense que la question mérite une autre réponse spécifique à Windows 8-10.

À l'aide de NetworkInformation à partir de l' espace de noms Windows.Networking.Connectivity , vous pouvez obtenir l'ID de la carte réseau que Windows utilise. Ensuite, vous pouvez obtenir l'adresse MAC de l'interface à partir des GetAllNetworkInterfaces () mentionnés précédemment.

Cela ne fonctionnera pas dans les applications du Windows Store car NetworkInterface dans System.Net.NetworkInformation n'expose pas GetAllNetworkInterfaces.

string GetMacAddress()
{
    var connectionProfile = NetworkInformation.GetInternetConnectionProfile();
    if (connectionProfile == null) return "";

    var inUseId = connectionProfile.NetworkAdapter.NetworkAdapterId.ToString("B").ToUpperInvariant();
    if(string.IsNullOrWhiteSpace(inUseId)) return "";

    var mac = NetworkInterface.GetAllNetworkInterfaces()
        .Where(n => inUseId == n.Id)
        .Select(n => n.GetPhysicalAddress().GetAddressBytes().Select(b=>b.ToString("X2")))
        .Select(macBytes => string.Join(" ", macBytes))
        .FirstOrDefault();

    return mac;
}

2
string mac = "";
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
            {

                if (nic.OperationalStatus == OperationalStatus.Up && (!nic.Description.Contains("Virtual") && !nic.Description.Contains("Pseudo")))
                {
                    if (nic.GetPhysicalAddress().ToString() != "")
                    {
                        mac = nic.GetPhysicalAddress().ToString();
                    }
                }
            }
MessageBox.Show(mac);

2
Cette réponse pourrait être améliorée avec une brève explication de ce que fait le code et comment il résout le problème.
Greg the Incredulous

1

Blak3r a un peu changé son code. Au cas où vous auriez deux adaptateurs avec la même vitesse. Trier par MAC, de sorte que vous obtenez toujours la même valeur.

public string GetMacAddress()
{
    const int MIN_MAC_ADDR_LENGTH = 12;
    string macAddress = string.Empty;
    Dictionary<string, long> macPlusSpeed = new Dictionary<string, long>();
    try
    {
        foreach(NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
        {
            System.Diagnostics.Debug.WriteLine("Found MAC Address: " + nic.GetPhysicalAddress() + " Type: " + nic.NetworkInterfaceType);

            string tempMac = nic.GetPhysicalAddress().ToString();

            if(!string.IsNullOrEmpty(tempMac) && tempMac.Length >= MIN_MAC_ADDR_LENGTH)
                macPlusSpeed.Add(tempMac, nic.Speed);
        }

        macAddress = macPlusSpeed.OrderByDescending(row => row.Value).ThenBy(row => row.Key).FirstOrDefault().Key;
    }
    catch{}

    System.Diagnostics.Debug.WriteLine("Fastest MAC address: " + macAddress);

    return macAddress;
}

1
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
{
     if (nic.OperationalStatus == OperationalStatus.Up)
     {
            PhysicalAddress Mac = nic.GetPhysicalAddress();
     }
}

0

ipconfig.exeest implémenté en utilisant diverses DLL, y compris iphlpapi.dll... Google pour iphlpapirévèle une API Win32 correspondante documentée dans MSDN.


0

Essaye ça:

    /// <summary>
    /// returns the first MAC address from where is executed 
    /// </summary>
    /// <param name="flagUpOnly">if sets returns only the nic on Up status</param>
    /// <returns></returns>
    public static string[] getOperationalMacAddresses(Boolean flagUpOnly)
    {
        string[] macAddresses = new string[NetworkInterface.GetAllNetworkInterfaces().Count()];

        int i = 0;
        foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
        {
            if (nic.OperationalStatus == OperationalStatus.Up || !flagUpOnly)
            {
                macAddresses[i] += ByteToHex(nic.GetPhysicalAddress().GetAddressBytes());
                //break;
                i++;
            }
        }
        return macAddresses;
    }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.