// // Authors: // Ben Motmans // Nicholas Terry // // Copyright (C) 2007 Ben Motmans // Copyright (C) 2014 Nicholas Terry // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Text; namespace Mono.Nat.Pmp { internal abstract class Pmp { public static List sockets; protected static Dictionary> gatewayLists; internal static void CreateSocketsAndAddGateways() { sockets = new List(); gatewayLists = new Dictionary>(); try { foreach (NetworkInterface n in NetworkInterface.GetAllNetworkInterfaces()) { if (n.OperationalStatus != OperationalStatus.Up && n.OperationalStatus != OperationalStatus.Unknown) continue; IPInterfaceProperties properties = n.GetIPProperties(); List gatewayList = new List(); foreach (GatewayIPAddressInformation gateway in properties.GatewayAddresses) { if (gateway.Address.AddressFamily == AddressFamily.InterNetwork) { gatewayList.Add(new IPEndPoint(gateway.Address, PmpConstants.ServerPort)); } } if (gatewayList.Count == 0) { /* Mono on OSX doesn't give any gateway addresses, so check DNS entries */ foreach (var gw2 in properties.DnsAddresses) { if (gw2.AddressFamily == AddressFamily.InterNetwork) { gatewayList.Add(new IPEndPoint(gw2, PmpConstants.ServerPort)); } } foreach (var unicast in properties.UnicastAddresses) { if (/*unicast.DuplicateAddressDetectionState == DuplicateAddressDetectionState.Preferred && unicast.AddressPreferredLifetime != UInt32.MaxValue && */unicast.Address.AddressFamily == AddressFamily.InterNetwork) { var bytes = unicast.Address.GetAddressBytes(); bytes[3] = 1; gatewayList.Add(new IPEndPoint(new IPAddress(bytes), PmpConstants.ServerPort)); } } } if (gatewayList.Count > 0) { foreach (UnicastIPAddressInformation address in properties.UnicastAddresses) { if (address.Address.AddressFamily == AddressFamily.InterNetwork) { UdpClient client; try { client = new UdpClient(new IPEndPoint(address.Address, 0)); } catch (SocketException) { continue; // Move on to the next address. } gatewayLists.Add(client, gatewayList); sockets.Add(client); } } } } } catch (Exception) { // NAT-PMP does not use multicast, so there isn't really a good fallback. } } } }