2 // System.Net.NetworkInformation.IPGlobalProperties
5 // Gonzalo Paniagua Javier (gonzalo@novell.com)
6 // Atsushi Enomoto (atsushi@ximian.com)
8 // Copyright (c) 2006-2007 Novell, Inc. (http://www.novell.com)
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Collections.Generic;
31 using System.Collections.Specialized;
32 using System.Globalization;
34 using System.Net.Sockets;
35 using System.Runtime.InteropServices;
38 namespace System.Net.NetworkInformation {
39 public abstract class IPGlobalProperties {
40 protected IPGlobalProperties ()
44 public static IPGlobalProperties GetIPGlobalProperties ()
46 switch (Environment.OSVersion.Platform) {
48 MibIPGlobalProperties impl = null;
49 if (Directory.Exists (MibIPGlobalProperties.ProcDir)) {
50 impl = new MibIPGlobalProperties (MibIPGlobalProperties.ProcDir);
51 if (File.Exists (impl.StatisticsFile))
54 if (Directory.Exists (MibIPGlobalProperties.CompatProcDir)) {
55 impl = new MibIPGlobalProperties (MibIPGlobalProperties.CompatProcDir);
56 if (File.Exists (impl.StatisticsFile))
59 return new UnixIPGlobalProperties ();
61 return new Win32IPGlobalProperties ();
65 internal static IPGlobalProperties InternalGetIPGlobalProperties()
67 return GetIPGlobalProperties ();
70 public abstract TcpConnectionInformation [] GetActiveTcpConnections ();
71 public abstract IPEndPoint [] GetActiveTcpListeners ();
72 public abstract IPEndPoint [] GetActiveUdpListeners ();
73 public abstract IcmpV4Statistics GetIcmpV4Statistics ();
74 public abstract IcmpV6Statistics GetIcmpV6Statistics ();
75 public abstract IPGlobalStatistics GetIPv4GlobalStatistics ();
76 public abstract IPGlobalStatistics GetIPv6GlobalStatistics ();
77 public abstract TcpStatistics GetTcpIPv4Statistics ();
78 public abstract TcpStatistics GetTcpIPv6Statistics ();
79 public abstract UdpStatistics GetUdpIPv4Statistics ();
80 public abstract UdpStatistics GetUdpIPv6Statistics ();
82 public abstract string DhcpScopeName { get; }
83 public abstract string DomainName { get; }
84 public abstract string HostName { get; }
85 public abstract bool IsWinsProxy { get; }
86 public abstract NetBiosNodeType NodeType { get; }
89 abstract class CommonUnixIPGlobalProperties : IPGlobalProperties
92 static extern int gethostname ([MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 1)] byte [] name, int len);
95 static extern int getdomainname ([MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 1)] byte [] name, int len);
97 public override string DhcpScopeName {
98 get { return String.Empty; }
101 public override string DomainName {
103 byte [] bytes = new byte [256];
104 if (getdomainname (bytes, 256) != 0)
105 throw new NetworkInformationException ();
106 int len = Array.IndexOf<byte> (bytes, 0);
107 return Encoding.ASCII.GetString (bytes, 0, len < 0 ? 256 : len);
111 public override string HostName {
113 byte [] bytes = new byte [256];
114 if (gethostname (bytes, 256) != 0)
115 throw new NetworkInformationException ();
116 int len = Array.IndexOf<byte> (bytes, 0);
117 return Encoding.ASCII.GetString (bytes, 0, len < 0 ? 256 : len);
121 public override bool IsWinsProxy {
122 get { return false; } // no WINS
125 public override NetBiosNodeType NodeType {
126 get { return NetBiosNodeType.Unknown; } // no NetBios
130 class UnixIPGlobalProperties : CommonUnixIPGlobalProperties
132 public override TcpConnectionInformation [] GetActiveTcpConnections ()
134 throw new NotImplementedException ();
137 public override IPEndPoint [] GetActiveTcpListeners ()
139 throw new NotImplementedException ();
142 public override IPEndPoint [] GetActiveUdpListeners ()
144 throw new NotImplementedException ();
147 public override IcmpV4Statistics GetIcmpV4Statistics ()
149 throw new NotImplementedException ();
152 public override IcmpV6Statistics GetIcmpV6Statistics ()
154 throw new NotImplementedException ();
157 public override IPGlobalStatistics GetIPv4GlobalStatistics ()
159 throw new NotImplementedException ();
162 public override IPGlobalStatistics GetIPv6GlobalStatistics ()
164 throw new NotImplementedException ();
167 public override TcpStatistics GetTcpIPv4Statistics ()
169 throw new NotImplementedException ();
172 public override TcpStatistics GetTcpIPv6Statistics ()
174 throw new NotImplementedException ();
177 public override UdpStatistics GetUdpIPv4Statistics ()
179 throw new NotImplementedException ();
182 public override UdpStatistics GetUdpIPv6Statistics ()
184 throw new NotImplementedException ();
188 // It expects /proc/net/snmp (or /usr/compat/linux/proc/net/snmp),
190 // http://www.linuxdevcenter.com/linux/2000/11/16/example5.html
191 // http://www.linuxdevcenter.com/linux/2000/11/16/example2.html
192 class MibIPGlobalProperties : UnixIPGlobalProperties
194 public const string ProcDir = "/proc";
195 public const string CompatProcDir = "/usr/compat/linux/proc";
197 public readonly string StatisticsFile, StatisticsFileIPv6, TcpFile, Tcp6File, UdpFile, Udp6File;
199 public MibIPGlobalProperties (string procDir)
201 StatisticsFile = Path.Combine (procDir, "net/snmp");
202 StatisticsFileIPv6 = Path.Combine (procDir, "net/snmp6");
203 TcpFile = Path.Combine (procDir,"net/tcp");
204 Tcp6File = Path.Combine (procDir,"net/tcp6");
205 UdpFile = Path.Combine (procDir,"net/udp");
206 Udp6File = Path.Combine (procDir,"net/udp6");
209 StringDictionary GetProperties4 (string item)
211 string file = StatisticsFile;
213 string head = item + ": ";
214 using (StreamReader sr = new StreamReader (file, Encoding.ASCII)) {
215 string [] keys = null;
216 string [] values = null;
217 string s = String.Empty;
220 if (String.IsNullOrEmpty (s))
222 if (s.Length <= head.Length || String.CompareOrdinal (s, 0, head, 0, head.Length) != 0)
225 keys = s.Substring (head.Length).Split (' ');
226 else if (values != null)
227 // hmm, there may be better error type...
228 throw CreateException (file, String.Format ("Found duplicate line for values for the same item '{0}'", item));
230 values = s.Substring (head.Length).Split (' ');
233 } while (!sr.EndOfStream);
236 throw CreateException (file, String.Format ("No corresponding line was not found for '{0}'", item));
237 if (keys.Length != values.Length)
238 throw CreateException (file, String.Format ("The counts in the header line and the value line do not match for '{0}'", item));
239 StringDictionary dic = new StringDictionary ();
240 for (int i = 0; i < keys.Length; i++)
241 dic [keys [i]] = values [i];
246 StringDictionary GetProperties6 (string item)
248 if (!File.Exists (StatisticsFileIPv6))
249 throw new NetworkInformationException ();
251 string file = StatisticsFileIPv6;
254 using (StreamReader sr = new StreamReader (file, Encoding.ASCII)) {
255 StringDictionary dic = new StringDictionary ();
256 string s = String.Empty;
259 if (String.IsNullOrEmpty (s))
261 if (s.Length <= head.Length || String.CompareOrdinal (s, 0, head, 0, head.Length) != 0)
263 int idx = s.IndexOfAny (wsChars, head.Length);
265 throw CreateException (file, null);
266 dic [s.Substring (head.Length, idx - head.Length)] = s.Substring (idx + 1).Trim (wsChars);
267 } while (!sr.EndOfStream);
273 static readonly char [] wsChars = new char [] {' ', '\t'};
275 Exception CreateException (string file, string msg)
277 return new InvalidOperationException (String.Format ("Unsupported (unexpected) '{0}' file format. ", file) + msg);
279 IPEndPoint [] GetLocalAddresses (List<string []> list)
281 IPEndPoint [] ret = new IPEndPoint [list.Count];
282 for (int i = 0; i < ret.Length; i++)
283 ret [i] = ToEndpoint (list [i] [1]);
287 IPEndPoint ToEndpoint (string s)
289 int idx = s.IndexOf (':');
290 int port = int.Parse (s.Substring (idx + 1), NumberStyles.HexNumber);
292 return new IPEndPoint (long.Parse (s.Substring (0, idx), NumberStyles.HexNumber), port);
294 byte [] bytes = new byte [16];
295 for (int i = 0; (i << 1) < idx; i++)
296 bytes [i] = byte.Parse (s.Substring (i << 1, 2), NumberStyles.HexNumber);
297 return new IPEndPoint (new IPAddress (bytes), port);
301 void GetRows (string file, List<string []> list)
303 if (!File.Exists (file))
305 using (StreamReader sr = new StreamReader (file, Encoding.ASCII)) {
306 sr.ReadLine (); // skip first line
307 while (!sr.EndOfStream) {
308 string [] item = sr.ReadLine ().Split (wsChars, StringSplitOptions.RemoveEmptyEntries);
310 throw CreateException (file, null);
316 public override TcpConnectionInformation [] GetActiveTcpConnections ()
318 List<string []> list = new List<string []> ();
319 GetRows (TcpFile, list);
320 GetRows (Tcp6File, list);
322 TcpConnectionInformation [] ret = new TcpConnectionInformation [list.Count];
323 for (int i = 0; i < ret.Length; i++) {
324 // sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
325 IPEndPoint local = ToEndpoint (list [i] [1]);
326 IPEndPoint remote = ToEndpoint (list [i] [2]);
327 TcpState state = (TcpState) int.Parse (list [i] [3], NumberStyles.HexNumber);
328 ret [i] = new TcpConnectionInformationImpl (local, remote, state);
333 public override IPEndPoint [] GetActiveTcpListeners ()
335 List<string []> list = new List<string []> ();
336 GetRows (TcpFile, list);
337 GetRows (Tcp6File, list);
338 return GetLocalAddresses (list);
341 public override IPEndPoint [] GetActiveUdpListeners ()
343 List<string []> list = new List<string []> ();
344 GetRows (UdpFile, list);
345 GetRows (Udp6File, list);
346 return GetLocalAddresses (list);
349 public override IcmpV4Statistics GetIcmpV4Statistics ()
351 return new MibIcmpV4Statistics (GetProperties4 ("Icmp"));
354 public override IcmpV6Statistics GetIcmpV6Statistics ()
356 return new MibIcmpV6Statistics (GetProperties6 ("Icmp6"));
359 public override IPGlobalStatistics GetIPv4GlobalStatistics ()
361 return new MibIPGlobalStatistics (GetProperties4 ("Ip"));
364 public override IPGlobalStatistics GetIPv6GlobalStatistics ()
366 return new MibIPGlobalStatistics (GetProperties6 ("Ip6"));
369 public override TcpStatistics GetTcpIPv4Statistics ()
371 return new MibTcpStatistics (GetProperties4 ("Tcp"));
374 public override TcpStatistics GetTcpIPv6Statistics ()
376 // There is no TCP info in /proc/net/snmp,
377 // so it is shared with IPv4 info.
378 return new MibTcpStatistics (GetProperties4 ("Tcp"));
381 public override UdpStatistics GetUdpIPv4Statistics ()
383 return new MibUdpStatistics (GetProperties4 ("Udp"));
386 public override UdpStatistics GetUdpIPv6Statistics ()
388 return new MibUdpStatistics (GetProperties6 ("Udp6"));
392 class Win32IPGlobalProperties : IPGlobalProperties
394 public const int AF_INET = 2;
395 public const int AF_INET6 = 23;
397 // FIXME: it might be getting wrong table. I'm getting
398 // different results from .NET 2.0.
399 unsafe void FillTcpTable (out List<Win32_MIB_TCPROW> tab4, out List<Win32_MIB_TCP6ROW> tab6)
401 tab4 = new List<Win32_MIB_TCPROW> ();
403 GetTcpTable (null, ref size4, true); // get size
404 byte [] bytes4 = new byte [size4];
405 GetTcpTable (bytes4, ref size4, true); // get list
407 int structSize4 = Marshal.SizeOf (typeof (Win32_MIB_TCPROW));
409 fixed (byte* ptr = bytes4) {
410 int count = Marshal.ReadInt32 ((IntPtr) ptr);
411 for (int i = 0; i < count; i++) {
412 Win32_MIB_TCPROW row = new Win32_MIB_TCPROW ();
413 Marshal.PtrToStructure ((IntPtr) (ptr + i * structSize4 + 4), row);
418 tab6 = new List<Win32_MIB_TCP6ROW> ();
419 if (Environment.OSVersion.Version.Major >= 6) { // Vista
421 GetTcp6Table (null, ref size6, true); // get size
422 byte [] bytes6 = new byte [size6];
423 GetTcp6Table (bytes6, ref size6, true); // get list
425 int structSize6 = Marshal.SizeOf (typeof (Win32_MIB_TCP6ROW));
427 fixed (byte* ptr = bytes6) {
428 int count = Marshal.ReadInt32 ((IntPtr) ptr);
429 for (int i = 0; i < count; i++) {
430 Win32_MIB_TCP6ROW row = new Win32_MIB_TCP6ROW ();
431 Marshal.PtrToStructure ((IntPtr) (ptr + i * structSize6 + 4), row);
438 bool IsListenerState (TcpState state)
441 case TcpState.SynSent:
442 case TcpState.Listen:
443 case TcpState.FinWait1:
444 case TcpState.FinWait2:
445 case TcpState.CloseWait:
451 public override TcpConnectionInformation [] GetActiveTcpConnections ()
453 List<Win32_MIB_TCPROW> tab4 = null;
454 List<Win32_MIB_TCP6ROW> tab6 = null;
455 FillTcpTable (out tab4, out tab6);
456 int size4 = tab4.Count;
458 TcpConnectionInformation [] ret = new TcpConnectionInformation [size4 + tab6.Count];
459 for (int i = 0; i < size4; i++)
460 ret [i] = tab4 [i].TcpInfo;
461 for (int i = 0; i < tab6.Count; i++)
462 ret [size4 + i] = tab6 [i].TcpInfo;
466 public override IPEndPoint [] GetActiveTcpListeners ()
468 List<Win32_MIB_TCPROW> tab4 = null;
469 List<Win32_MIB_TCP6ROW> tab6 = null;
470 FillTcpTable (out tab4, out tab6);
472 List<IPEndPoint> ret = new List<IPEndPoint> ();
473 for (int i = 0, count = tab4.Count; i < count; i++)
474 if (IsListenerState (tab4 [i].State))
475 ret.Add (tab4 [i].LocalEndPoint);
476 for (int i = 0, count = tab6.Count; i < count; i++)
477 if (IsListenerState (tab6 [i].State))
478 ret.Add (tab6 [i].LocalEndPoint);
479 return ret.ToArray ();
482 public unsafe override IPEndPoint [] GetActiveUdpListeners ()
484 List<IPEndPoint> list = new List<IPEndPoint> ();
486 byte [] bytes4 = null;
488 GetUdpTable (null, ref size4, true); // get size
489 bytes4 = new byte [size4];
490 GetUdpTable (bytes4, ref size4, true); // get list
492 int structSize4 = Marshal.SizeOf (typeof (Win32_MIB_UDPROW));
494 fixed (byte* ptr = bytes4) {
495 int count = Marshal.ReadInt32 ((IntPtr) ptr);
496 for (int i = 0; i < count; i++) {
497 Win32_MIB_UDPROW row = new Win32_MIB_UDPROW ();
498 Marshal.PtrToStructure ((IntPtr) (ptr + i * structSize4 + 4), row);
499 list.Add (row.LocalEndPoint);
503 if (Environment.OSVersion.Version.Major >= 6) { // Vista
504 byte [] bytes6 = null;
506 GetUdp6Table (null, ref size6, true); // get size
507 bytes6 = new byte [size6];
508 GetUdp6Table (bytes6, ref size6, true); // get list
510 int structSize6 = Marshal.SizeOf (typeof (Win32_MIB_UDP6ROW));
512 fixed (byte* ptr = bytes6) {
513 int count = Marshal.ReadInt32 ((IntPtr) ptr);
514 for (int i = 0; i < count; i++) {
515 Win32_MIB_UDP6ROW row = new Win32_MIB_UDP6ROW ();
516 Marshal.PtrToStructure ((IntPtr) (ptr + i * structSize6 + 4), row);
517 list.Add (row.LocalEndPoint);
522 return list.ToArray ();
525 public override IcmpV4Statistics GetIcmpV4Statistics ()
527 if (!Socket.SupportsIPv4)
528 throw new NetworkInformationException ();
529 Win32_MIBICMPINFO stats;
530 GetIcmpStatistics (out stats, AF_INET);
531 return new Win32IcmpV4Statistics (stats);
534 public override IcmpV6Statistics GetIcmpV6Statistics ()
536 if (!Socket.OSSupportsIPv6)
537 throw new NetworkInformationException ();
538 Win32_MIB_ICMP_EX stats;
539 GetIcmpStatisticsEx (out stats, AF_INET6);
540 return new Win32IcmpV6Statistics (stats);
543 public override IPGlobalStatistics GetIPv4GlobalStatistics ()
545 if (!Socket.SupportsIPv4)
546 throw new NetworkInformationException ();
547 Win32_MIB_IPSTATS stats;
548 GetIpStatisticsEx (out stats, AF_INET);
549 return new Win32IPGlobalStatistics (stats);
552 public override IPGlobalStatistics GetIPv6GlobalStatistics ()
554 if (!Socket.OSSupportsIPv6)
555 throw new NetworkInformationException ();
556 Win32_MIB_IPSTATS stats;
557 GetIpStatisticsEx (out stats, AF_INET6);
558 return new Win32IPGlobalStatistics (stats);
561 public override TcpStatistics GetTcpIPv4Statistics ()
563 if (!Socket.SupportsIPv4)
564 throw new NetworkInformationException ();
565 Win32_MIB_TCPSTATS stats;
566 GetTcpStatisticsEx (out stats, AF_INET);
567 return new Win32TcpStatistics (stats);
570 public override TcpStatistics GetTcpIPv6Statistics ()
572 if (!Socket.OSSupportsIPv6)
573 throw new NetworkInformationException ();
574 Win32_MIB_TCPSTATS stats;
575 GetTcpStatisticsEx (out stats, AF_INET6);
576 return new Win32TcpStatistics (stats);
579 public override UdpStatistics GetUdpIPv4Statistics ()
581 if (!Socket.SupportsIPv4)
582 throw new NetworkInformationException ();
583 Win32_MIB_UDPSTATS stats;
584 GetUdpStatisticsEx (out stats, AF_INET);
585 return new Win32UdpStatistics (stats);
588 public override UdpStatistics GetUdpIPv6Statistics ()
590 if (!Socket.OSSupportsIPv6)
591 throw new NetworkInformationException ();
592 Win32_MIB_UDPSTATS stats;
593 GetUdpStatisticsEx (out stats, AF_INET6);
594 return new Win32UdpStatistics (stats);
597 public override string DhcpScopeName {
598 get { return Win32_FIXED_INFO.Instance.ScopeId; }
601 public override string DomainName {
602 get { return Win32_FIXED_INFO.Instance.DomainName; }
605 public override string HostName {
606 get { return Win32_FIXED_INFO.Instance.HostName; }
609 public override bool IsWinsProxy {
610 get { return Win32_FIXED_INFO.Instance.EnableProxy != 0; }
613 public override NetBiosNodeType NodeType {
614 get { return Win32_FIXED_INFO.Instance.NodeType; }
619 [DllImport ("iphlpapi.dll")]
620 static extern int GetTcpTable (byte [] pTcpTable, ref int pdwSize, bool bOrder);
622 [DllImport ("iphlpapi.dll")]
623 static extern int GetTcp6Table (byte [] TcpTable, ref int SizePointer, bool Order);
625 [DllImport ("iphlpapi.dll")]
626 static extern int GetUdpTable (byte [] pUdpTable, ref int pdwSize, bool bOrder);
628 [DllImport ("iphlpapi.dll")]
629 static extern int GetUdp6Table (byte [] Udp6Table, ref int SizePointer, bool Order);
631 [DllImport ("iphlpapi.dll")]
632 static extern int GetTcpStatisticsEx (out Win32_MIB_TCPSTATS pStats, int dwFamily);
634 [DllImport ("iphlpapi.dll")]
635 static extern int GetUdpStatisticsEx (out Win32_MIB_UDPSTATS pStats, int dwFamily);
637 [DllImport ("iphlpapi.dll")]
638 static extern int GetIcmpStatistics (out Win32_MIBICMPINFO pStats, int dwFamily);
640 [DllImport ("iphlpapi.dll")]
641 static extern int GetIcmpStatisticsEx (out Win32_MIB_ICMP_EX pStats, int dwFamily);
643 [DllImport ("iphlpapi.dll")]
644 static extern int GetIpStatisticsEx (out Win32_MIB_IPSTATS pStats, int dwFamily);
648 [StructLayout (LayoutKind.Explicit)]
649 struct Win32_IN6_ADDR
652 [MarshalAs ( UnmanagedType.ByValArray, SizeConst = 16)]
653 public byte [] Bytes;
656 [StructLayout (LayoutKind.Sequential)]
657 class Win32_MIB_TCPROW
659 public TcpState State;
660 public uint LocalAddr;
661 public int LocalPort;
662 public uint RemoteAddr;
663 public int RemotePort;
665 public IPEndPoint LocalEndPoint {
666 get { return new IPEndPoint (LocalAddr, LocalPort); }
669 public IPEndPoint RemoteEndPoint {
670 get { return new IPEndPoint (RemoteAddr, RemotePort); }
673 public TcpConnectionInformation TcpInfo {
674 get { return new TcpConnectionInformationImpl (LocalEndPoint, RemoteEndPoint, State); }
678 [StructLayout (LayoutKind.Sequential)]
679 class Win32_MIB_TCP6ROW
681 public TcpState State;
682 public Win32_IN6_ADDR LocalAddr;
683 public uint LocalScopeId;
684 public int LocalPort;
685 public Win32_IN6_ADDR RemoteAddr;
686 public uint RemoteScopeId;
687 public int RemotePort;
689 public IPEndPoint LocalEndPoint {
690 get { return new IPEndPoint (new IPAddress (LocalAddr.Bytes, LocalScopeId), LocalPort); }
693 public IPEndPoint RemoteEndPoint {
694 get { return new IPEndPoint (new IPAddress (RemoteAddr.Bytes, RemoteScopeId), RemotePort); }
697 public TcpConnectionInformation TcpInfo {
698 get { return new TcpConnectionInformationImpl (LocalEndPoint, RemoteEndPoint, State); }
702 [StructLayout (LayoutKind.Sequential)]
703 class Win32_MIB_UDPROW
705 public uint LocalAddr;
706 public int LocalPort;
708 public IPEndPoint LocalEndPoint {
709 get { return new IPEndPoint (LocalAddr, LocalPort); }
713 [StructLayout (LayoutKind.Sequential)]
714 class Win32_MIB_UDP6ROW
716 public Win32_IN6_ADDR LocalAddr;
717 public uint LocalScopeId;
718 public int LocalPort;
720 public IPEndPoint LocalEndPoint {
721 get { return new IPEndPoint (new IPAddress (LocalAddr.Bytes, LocalScopeId), LocalPort); }