2011-11-14 13 views
5

Uygulamamda (MVC3'te yazılmış admin web arayüzü) açık gömülü Linux üzerinde çalışan tüm TCP/IP ayarlarını listelemem gerekiyor. Bu IP-Adresse, Gateway ve alt ağ maskesini içerir.Alt ağ maskesi (leri) Linux'ta Mono kullanarak nasıl sorgulanır?

Aşağıdaki kod MS Net altında iyi çalışır ancak Mono 2.10 "IPv4Mask" özellik için bir NotImplemntedException atar:

var ipProperties = networkIntf.GetIPProperties(); 
var unicastIpInfo = ipProperties.UnicastAddresses.FirstOrDefault(); 
var subnetMask = unicastAddress != null ? unicastAddress.IPv4Mask.ToString() : ""; 

herkes bir mono kullanarak IPv4 alt ağ maskesini alabilirsiniz biliyor mu?

Bu soru zaten 2009 yılında soruldu ve herhangi bir cevap bulamadık.

+0

Onlardan bunları uygulamalarını isteyin ya da kendiniz uygulayın! – leppie

+0

Zaten Mono-Listede soruldu ancak herhangi bir yanıt almadı. Bunu benimsemek için Linux teknik bilgim yok. Yani belki başkası bir çözüm bulur. – Marc

+1

Her zaman 'ifconfig' olarak adlandırıp manuel olarak ayrıştırabilirsiniz. – leppie

cevap

5

Bazı Mono kaynak koduna baktım ve belirli bir ağ arabiriminin IPv4 alt ağ maskesini döndüren bir yardımcı oluşturmak için bazı kod parçacıklarını çıkardım. Kod mutlak bir güzellik değil ama işe yarıyor. Yukarıdaki helper'ın

[StructLayout(LayoutKind.Explicit)] 
struct ifa_ifu 
{ 
    [FieldOffset(0)] 
    public IntPtr ifu_broadaddr; 

    [FieldOffset(0)] 
    public IntPtr ifu_dstaddr; 
} 

[StructLayout(LayoutKind.Sequential)] 
struct ifaddrs 
{ 
    public IntPtr ifa_next; 
    public string ifa_name; 
    public uint ifa_flags; 
    public IntPtr ifa_addr; 
    public IntPtr ifa_netmask; 
    public ifa_ifu ifa_ifu; 
    public IntPtr ifa_data; 
} 

[StructLayout(LayoutKind.Sequential)] 
struct sockaddr_in 
{ 
    public ushort sin_family; 
    public ushort sin_port; 
    public uint sin_addr; 
} 

[StructLayout(LayoutKind.Sequential)] 
struct sockaddr_in6 
{ 
    public ushort sin6_family; /* AF_INET6 */ 
    public ushort sin6_port;  /* Transport layer port # */ 
    public uint sin6_flowinfo; /* IPv6 flow information */ 
    public in6_addr sin6_addr;  /* IPv6 address */ 
    public uint sin6_scope_id; /* scope id (new in RFC2553) */ 
} 

[StructLayout(LayoutKind.Sequential)] 
struct in6_addr 
{ 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] 
    public byte[] u6_addr8; 
} 

[StructLayout(LayoutKind.Sequential)] 
struct sockaddr_ll 
{ 
    public ushort sll_family; 
    public ushort sll_protocol; 
    public int sll_ifindex; 
    public ushort sll_hatype; 
    public byte sll_pkttype; 
    public byte sll_halen; 

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] 
    public byte[] sll_addr; 
} 

internal class IPInfoTools 
{ 
    const int AF_INET = 2; 
    const int AF_INET6 = 10; 
    const int AF_PACKET = 17; 

    [DllImport("libc")] 
    static extern int getifaddrs (out IntPtr ifap); 

    [DllImport ("libc")] 
    static extern void freeifaddrs (IntPtr ifap); 

    internal static string GetIPv4Mask(string networkInterfaceName) 
    { 
     IntPtr ifap; 
     if (getifaddrs(out ifap) != 0) 
     { 
      throw new SystemException("getifaddrs() failed"); 
     } 

     try 
     { 
      var next = ifap; 
      while (next != IntPtr.Zero) 
      { 
       var addr = (ifaddrs)Marshal.PtrToStructure(next, typeof(ifaddrs)); 
       var name = addr.ifa_name; 

       if (addr.ifa_addr != IntPtr.Zero) 
       { 
        var sockaddr = (sockaddr_in)Marshal.PtrToStructure(addr.ifa_addr, typeof(sockaddr_in)); 
        switch (sockaddr.sin_family) 
        { 
         case AF_INET6: 
          //sockaddr_in6 sockaddr6 = (sockaddr_in6)Marshal.PtrToStructure(addr.ifa_addr, typeof(sockaddr_in6)); 
          break; 
         case AF_INET: 
          if (name == networkInterfaceName) 
          { 
           var netmask = (sockaddr_in)Marshal.PtrToStructure(addr.ifa_netmask, typeof(sockaddr_in)); 
           var ipAddr = new IPAddress(netmask.sin_addr); // IPAddress to format into default string notation 
           return ipAddr.ToString(); 
          } 
          break; 
         case AF_PACKET: 
          { 
           var sockaddrll = (sockaddr_ll)Marshal.PtrToStructure(addr.ifa_addr, typeof(sockaddr_ll)); 
           if (sockaddrll.sll_halen > sockaddrll.sll_addr.Length) 
           { 
            Console.Error.WriteLine("Got a bad hardware address length for an AF_PACKET {0} {1}", 
                  sockaddrll.sll_halen, sockaddrll.sll_addr.Length); 
            next = addr.ifa_next; 
            continue; 
           } 
          } 
          break; 
        } 
       } 

       next = addr.ifa_next; 
      } 
     } 
     finally 
     { 
      freeifaddrs(ifap); 
     } 

     return null; 
    } 
} 

Kullanımı şu şekildedir:

String subnetMask = IPInfoTools.GetIPv4Mask("etc0"); 

Henüz bir yukarıdaki almak için Mono oldukça bazı dosyaları değiştirmek ihtiyacı olduğu Mono kaynak kodundaki Bunu düzeltmek başaramadı Kullanıldığı yerden (LinuxNetworkInterface) sorgulandığı yerdeki bilgiler (LinuxUnicastIPAddressInfo). Fakat kodumu Mono hata raporuna göndereceğim, bu yüzden Mono geliştiricilerinden biri belki bir göz atabilir.

1

Marc, sadece bu kodu SİZE ÇOK TEŞEKKÜR EDERİZ söylemek istedim. Uygulamamda çok kolay bir şekilde çalışmayı başarabiliyordum ve Mono 2.10.6'da Ubuntu 10.10'da harika çalışıyor. Keşke bunu bir defadan fazla tekrar edebilirim.

Mono için geçerli olmayan, Win32 sürümü System.Deployment kullandığı için Mono için uygulamanın özel bir sürümünü yapıyorum; böylece başvuru için, burada kullanılan kod:

UnicastIPAddressInformation addr = GetUnicastAddrFromNic(nic.GetIPProperties().UnicastAddresses); 

#if BUILD4MONO 
string mask = null; 
try { 
    mask = IPInfoTools.GetIPv4Mask(nic.Name); // Marc's function - nic.Name is eth0 or wlan1 etc. 
} catch (Exception ex) { // getifaddrs failed 
    Console.WriteLine("GetIPRangeInfoFromNetworkInterface failed: {0}", ex.Message); 
} 

if (mask == null || IPAddress.TryParse(mask, out rangeInfo.SubnetMask) == false) { 
    rangeInfo.SubnetMask = IPAddress.Parse("255.255.255.0"); // default to this 
} 
#else 
rangeInfo.SubnetMask = addr.IPv4Mask; // Win32 
#endif 

Not: nic sadece NetworkInterface nesnedir ve GetUnicastAddrFromNic() Sadece nic için tüm UnicastAddresses bakar yapılan bir fonksiyondur ve kimin AddressFamily ilkini döndürür InterNetwork.

Umarız Mono ekibinden biri çözümünüzü yaklaşan bir sürümde uygular.

+0

Güzel donanım - teşekkürler! Mono: Hepsini Mono'ya gönderdim ama onlardan bir şey duymadım. Hayal kırıklığı ama iyi bir şey ... – Marc

+1

Evet gibi ağ kodu gibi ortak bir şey için ASAP dahil görmek istiyorum, ancak M $ ile yetişmek ve çalışma kodlarını CLR ile güncel tutmak için yeterince zor olduğunu düşünüyorum. .. En azından şimdi, Windows b'de düzgün çalışan formumda .NET ve Mono oluşturma öğeleri arasındaki tutarsızlıkları gidermek için hareket edebilirim. Linux üzerinde yanlış bir şekilde gösteriliyor. Tekrar teşekkürler. – drew010

İlgili konular