2011-11-14 13 views
5

open-embedded Linuxで動作する私のアプリケーション(MVC3で書かれた管理Webインターフェイス)では、すべてのTCP/IP設定をリストアップする必要があります。これには、IPアドレス、ゲートウェイ、サブネットマスクが含まれます。LinuxでMonoを使用してサブネットマスクを照会する方法は?

次のコードは、MSの.Netの下でも動作しますが、モノラル2.10は"IPv4Mask"プロパティのNotImplemntedExceptionをスロー:

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

は、1つのモノを使用してIPv4サブネットマスクを取得することができますどのように誰もが知っていますか?

この質問は2009年に既に質問されていますが、それに対する回答は見つかりませんでした。

+0

これを実装するか、自分で実装するかを尋ねます。 – leppie

+0

既にMono-Listに尋ねられましたが、何の応答もありませんでした。自分でLinuxのノウハウを実装する必要はありません。だから、他の人が回避策を知っているかもしれない。 – Marc

+1

'ifconfig'を呼び出すだけで、手動で解析することができます。 – leppie

答えて

5

Monoのソースコードをいくつか見て、特定のネットワークインターフェイスのIPv4サブネットマスクを返すヘルパーを構築するためのコードスニペットをいくつか抽出しました。コードは絶対的な美しさではありませんが、機能します。上記のヘルパーの

[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; 
    } 
} 

使用法は、このようなものです:

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

私はまだ1は、上記を得るためにモノにかなりいくつかのファイルを変更する必要があるとして、モノラルソースコードでこの問題を解決するために管理していませんでしたそれが照会される場所(LinuxNetworkInterface)から使用される場所(LinuxUnicastIPAddressInfo)までの情報。しかし、Monoのバグレポートに自分のコードを掲載して、Monoの開発者の一人が一見するかもしれません。

1

マーク、ちょうどありがとうございます。このコードはです。私はそれを私のアプリケーションで非常に簡単に動作させることができたし、Mono 2.10.6のUbuntu 10.10でうまくいきます。私はこれを複数回アップヴォートすることができたらいいと思う。

Monoで利用できないSystem.DeploymentがWin32バージョンで使用されているので、Mono用の特別なバージョンのアプリケーションをビルドします。その参考のために、ここで私が使用したコードは次のとおりです。

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 

注:nicはちょうどNetworkInterfaceオブジェクトであり、GetUnicastAddrFromNic()は、私はちょうどNICのすべてのUnicastAddressesを見て、そのAddressFamily最初のものを返すことを行った関数でありますInterNetworkです。

Monoチームの誰かが、今後のバージョンであなたのソリューションを適用したいと願っています。

+0

素敵な拡張 - ありがとう! モノ:全員モノに提出しましたが、何も聞いていませんでした。期待していたのですが... ... – Marc

+1

ネットワーキングコードとして一般的なものがありました。私はそれがすぐに含まれていることを確認したいと思いますが、M $に追いついてCLRで作業コードを最新の状態に保つだけで十分です。少なくとも今、私は、WindowsとWindowsでうまく動作するフォーム上の.NETとMonoのレンダリング要素の不一致を修正することができます。b Linuxで誤って表示されます。再度、感謝します。 – drew010

関連する問題