• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lduchosal / ipnetwork / 728

29 Mar 2025 01:52PM UTC coverage: 93.279% (+0.008%) from 93.271%
728

Pull #348

appveyor

web-flow
Merge ccbb4594f into 6937bb93c
Pull Request #348: Feat: upgrade to net9

1596 of 1711 relevant lines covered (93.28%)

826874.15 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.75
/src/System.Net.IPNetwork/IPNetwork2.cs
1
// <copyright file="IPNetwork2.cs" company="IPNetwork">
2
// Copyright (c) IPNetwork. All rights reserved.
3
// </copyright>
4

5
namespace System.Net
6
{
7
    using System.Collections.Generic;
8
    using System.IO;
9
    using System.Net.Sockets;
10
    using System.Numerics;
11
    using System.Runtime.Serialization;
12
    using System.Text.RegularExpressions;
13

14
    /// <summary>
15
    /// IP Network utility class.
16
    /// Use IPNetwork.Parse to create instances.
17
    /// </summary>
18
    [Serializable]
19
    public sealed class IPNetwork2 : IComparable<IPNetwork2>, ISerializable
20
    {
21
        #region properties
22

23
        private readonly object _sync = new();
8,135,765✔
24
        private readonly int _hashCode;
25
        private BigInteger _ipaddress;
26
        private byte _cidr;
27
        private BigInteger? _cachedBroadcast;
28

29
        private AddressFamily _family;
30

31
        /// <summary>
32
        /// Gets or sets the value of the IPNetwork property.
33
        /// </summary>
34
        [DataMember(Name = "IPNetwork", IsRequired = true)]
35
        public string Value
36
        {
37
            get
38
            {
2,000,002✔
39
                return this.ToString();
2,000,002✔
40
            }
2,000,002✔
41

42
            set
43
            {
2,000,004✔
44
                var ipnetwork = IPNetwork2.Parse(value);
2,000,004✔
45
                this._ipaddress = ipnetwork._ipaddress;
2,000,004✔
46
                this._family = ipnetwork._family;
2,000,004✔
47
                this._cidr = ipnetwork._cidr;
2,000,004✔
48
                lock (_sync)
2,000,004✔
49
                {
2,000,004✔
50
                    this._cachedBroadcast = null;
2,000,004✔
51
                }
2,000,004✔
52
            }
2,000,004✔
53
        }
54

55
        #endregion
56

57
        #region accessors
58

59
        internal BigInteger _network
60
        {
61
            get
62
            {
13,168,225✔
63
                BigInteger uintNetwork = this._ipaddress & this._netmask;
13,168,225✔
64
                return uintNetwork;
13,168,225✔
65
            }
13,168,225✔
66
        }
67

68
        /// <summary>
69
        /// Gets network address.
70
        /// </summary>
71
        public IPAddress Network
72
        {
73
            get
74
            {
4,136,454✔
75
                return IPNetwork2.ToIPAddress(this._network, this._family);
4,136,454✔
76
            }
4,136,454✔
77
        }
78

79
        /// <summary>
80
        /// Gets address Family.
81
        /// </summary>
82
        public AddressFamily AddressFamily
83
        {
84
            get
85
            {
133,946✔
86
                return this._family;
133,946✔
87
            }
133,946✔
88
        }
89

90
        internal BigInteger _netmask
91
        {
92
            get
93
            {
13,302,611✔
94
                return IPNetwork2.ToUint(this._cidr, this._family);
13,302,611✔
95
            }
13,302,611✔
96
        }
97

98
        /// <summary>
99
        /// Gets netmask.
100
        /// </summary>
101
        public IPAddress Netmask
102
        {
103
            get
104
            {
367✔
105
                return IPNetwork2.ToIPAddress(this._netmask, this._family);
367✔
106
            }
367✔
107
        }
108

109
        internal BigInteger _broadcast
110
        {
111
            get
112
            {
663,269✔
113
                var cached = this._cachedBroadcast;
663,269✔
114
                if (cached != null)
663,269✔
115
                {
529,452✔
116
                    return cached.Value;
529,452✔
117
                }
118

119
                lock (_sync)
133,817✔
120
                {
133,817✔
121
                    var cached2 = this._cachedBroadcast;
133,817✔
122
                    if (cached2 != null)
133,817✔
123
                    {
×
124
                        return cached2.Value;
×
125
                    }
126

127
                    var network = this._network;
133,817✔
128
                    var computed = CreateBroadcast(ref network, this._netmask, this._family);
133,817✔
129
                    this._cachedBroadcast = computed;
133,817✔
130
                    return computed;
133,817✔
131
                }
132
            }
663,269✔
133
        }
134

135
        /// <summary>
136
        /// Gets broadcast address.
137
        /// </summary>
138
        public IPAddress Broadcast
139
        {
140
            get
141
            {
66,830✔
142
                if (this._family == Sockets.AddressFamily.InterNetworkV6)
66,830✔
143
                {
31✔
144
                    return null;
31✔
145
                }
146

147
                return IPNetwork2.ToIPAddress(this._broadcast, this._family);
66,799✔
148
            }
66,830✔
149
        }
150

151
        /// <summary>
152
        /// Gets first usable IP adress in Network.
153
        /// </summary>
154
        public IPAddress FirstUsable
155
        {
156
            get
157
            {
2,355✔
158
                BigInteger first = this._family == Sockets.AddressFamily.InterNetworkV6
2,355✔
159
                    ? this._network
2,355✔
160
                    : (this.Usable <= 0) ? this._network : this._network + 1;
2,355✔
161
                return IPNetwork2.ToIPAddress(first, this._family);
2,355✔
162
            }
2,355✔
163
        }
164

165
        /// <summary>
166
        /// Gets last usable IP adress in Network.
167
        /// </summary>
168
        public IPAddress LastUsable
169
        {
170
            get
171
            {
2,594✔
172
                BigInteger last = this._family == Sockets.AddressFamily.InterNetworkV6
2,594✔
173
                    ? this._broadcast
2,594✔
174
                    : (this.Usable <= 0) ? this._network : this._broadcast - 1;
2,594✔
175
                return IPNetwork2.ToIPAddress(last, this._family);
2,594✔
176
            }
2,594✔
177
        }
178

179
        /// <summary>
180
        /// Gets number of usable IP adress in Network.
181
        /// </summary>
182
        public BigInteger Usable
183
        {
184
            get
185
            {
2,972✔
186
                if (this._family == Sockets.AddressFamily.InterNetworkV6)
2,972✔
187
                {
32✔
188
                    return this.Total;
32✔
189
                }
190

191
                byte[] mask = new byte[] { 0xff, 0xff, 0xff, 0xff, 0x00 };
2,940✔
192
                var bmask = new BigInteger(mask);
2,940✔
193
                BigInteger usableIps = (this._cidr > 30) ? 0 : ((bmask >> this._cidr) - 1);
2,940✔
194
                return usableIps;
2,940✔
195
            }
2,972✔
196
        }
197

198
        /// <summary>
199
        /// Gets number of IP adress in Network.
200
        /// </summary>
201
        public BigInteger Total
202
        {
203
            get
204
            {
2,601✔
205
                int max = this._family == Sockets.AddressFamily.InterNetwork ? 32 : 128;
2,601✔
206
                var count = BigInteger.Pow(2, max - this._cidr);
2,601✔
207
                return count;
2,601✔
208
            }
2,601✔
209
        }
210

211
        /// <summary>
212
        /// Gets the CIDR netmask notation.
213
        /// </summary>
214
        public byte Cidr
215
        {
216
            get
217
            {
4,205,333✔
218
                return this._cidr;
4,205,333✔
219
            }
4,205,333✔
220
        }
221

222
        #endregion
223

224
        #region constructor
225

226
#if TRAVISCI
227
        public
228
#else
229
        /// <summary>
230
        /// Initializes a new instance of the <see cref="IPNetwork2"/> class with the specified IP address, address family, and CIDR.
231
        /// </summary>
232
        /// <param name="ipaddress">The IP address of the network.</param>
233
        /// <param name="family">The address family of the network.</param>
234
        /// <param name="cidr">The CIDR (Classless Inter-Domain Routing) notation of the network.</param>
235
        internal
6,133,729✔
236
#endif
6,133,729✔
237
            IPNetwork2(BigInteger ipaddress, AddressFamily family, byte cidr)
6,133,729✔
238
        {
6,133,729✔
239
            this.Init(ipaddress, family, cidr);
6,133,729✔
240
            this._hashCode = this.ComputeHashCode();
6,133,728✔
241
        }
6,133,728✔
242

243
        /// <summary>
244
        /// Initializes a new instance of the <see cref="IPNetwork2"/> class.
245
        /// Creates a new IPNetwork.
246
        /// </summary>
247
        /// <param name="ipaddress">An ipaddress.</param>
248
        /// <param name="cidr">A byte representing the netmask in cidr format (/24).</param>
249
        /// <exception cref="ArgumentNullException">ipaddress is null.</exception>
250
        public IPNetwork2(IPAddress ipaddress, byte cidr)
2,033✔
251
        {
2,033✔
252
            if (ipaddress == null)
2,033✔
253
            {
1✔
254
                throw new ArgumentNullException("ipaddress");
1✔
255
            }
256

257
            BigInteger uintIpAddress = ToBigInteger(ipaddress);
2,032✔
258

259
            this.Init(uintIpAddress, ipaddress.AddressFamily, cidr);
2,032✔
260
            this._hashCode = this.ComputeHashCode();
2,030✔
261
        }
2,030✔
262

263
        private void Init(BigInteger ipaddress, AddressFamily family, byte cidr)
264
        {
6,135,761✔
265
            int maxCidr = family == AddressFamily.InterNetwork ? 32 : 128;
6,135,761✔
266
            if (cidr > maxCidr)
6,135,761✔
267
            {
3✔
268
                throw new ArgumentOutOfRangeException("cidr");
3✔
269
            }
270

271
            this._ipaddress = ipaddress;
6,135,758✔
272
            this._family = family;
6,135,758✔
273
            this._cidr = cidr;
6,135,758✔
274
        }
6,135,758✔
275

276
        #endregion
277

278
        #region parsers
279

280
        /// <summary>
281
        /// 192.168.168.100 - 255.255.255.0
282
        ///
283
        /// ```
284
        /// Network   : 192.168.168.0
285
        /// Netmask   : 255.255.255.0
286
        /// Cidr      : 24
287
        /// Start     : 192.168.168.1
288
        /// End       : 192.168.168.254
289
        /// Broadcast : 192.168.168.255
290
        /// ```.
291
        ///
292
        /// </summary>
293
        /// <param name="ipaddress">A string containing an ip address to convert.</param>
294
        /// <param name="netmask">A string representing a netmask in std format (255.255.255.0).</param>
295
        /// <returns>An IPNetwork equivalent to the network contained in ipaddress/netmask.</returns>
296
        public static IPNetwork2 Parse(string ipaddress, string netmask)
297
        {
14✔
298
            IPNetwork2.InternalParse(false, ipaddress, netmask, out IPNetwork2 ipnetwork);
14✔
299
            return ipnetwork;
3✔
300
        }
3✔
301

302
        /// <summary>
303
        /// 192.168.168.100/24
304
        ///
305
        /// Network   : 192.168.168.0
306
        /// Netmask   : 255.255.255.0
307
        /// Cidr      : 24
308
        /// Start     : 192.168.168.1
309
        /// End       : 192.168.168.254
310
        /// Broadcast : 192.168.168.255.
311
        /// </summary>
312
        /// <param name="ipaddress">A string containing an ip address to convert.</param>
313
        /// <param name="cidr">A byte representing the netmask in cidr format (/24).</param>
314
        /// <returns>An IPNetwork equivalent to the network contained in ipaddress/cidr.</returns>
315
        public static IPNetwork2 Parse(string ipaddress, byte cidr)
316
        {
26✔
317
            IPNetwork2.InternalParse(false, ipaddress, cidr, out IPNetwork2 ipnetwork);
26✔
318
            return ipnetwork;
20✔
319
        }
20✔
320

321
        /// <summary>
322
        /// 192.168.168.100 255.255.255.0
323
        ///
324
        /// Network   : 192.168.168.0
325
        /// Netmask   : 255.255.255.0
326
        /// Cidr      : 24
327
        /// Start     : 192.168.168.1
328
        /// End       : 192.168.168.254
329
        /// Broadcast : 192.168.168.255.
330
        /// </summary>
331
        /// <param name="ipaddress">A string containing an ip address to convert.</param>
332
        /// <param name="netmask">A netmask to be used to create the IPNetwork.</param>
333
        /// <returns>An IPNetwork equivalent to the network contained in ipaddress/netmask.</returns>
334
        public static IPNetwork2 Parse(IPAddress ipaddress, IPAddress netmask)
335
        {
6✔
336
            IPNetwork2.InternalParse(false, ipaddress, netmask, out IPNetwork2 ipnetwork);
6✔
337
            return ipnetwork;
2✔
338
        }
2✔
339

340
        /// <summary>
341
        /// 192.168.0.1/24
342
        /// 192.168.0.1 255.255.255.0
343
        ///
344
        /// Network   : 192.168.0.0
345
        /// Netmask   : 255.255.255.0
346
        /// Cidr      : 24
347
        /// Start     : 192.168.0.1
348
        /// End       : 192.168.0.254
349
        /// Broadcast : 192.168.0.255.
350
        /// </summary>
351
        /// <param name="network">A string containing an ip network to convert.</param>
352
        /// <returns>An IPNetwork equivalent to the network contained in string network.</returns>
353
        public static IPNetwork2 Parse(string network)
354
        {
4,000,643✔
355
            IPNetwork2.InternalParse(false, network, CidrGuess.ClassFull, true, out IPNetwork2 ipnetwork);
4,000,643✔
356
            return ipnetwork;
4,000,637✔
357
        }
4,000,637✔
358

359
        /// <summary>
360
        /// 192.168.0.1/24
361
        /// 192.168.0.1 255.255.255.0
362
        ///
363
        /// Network   : 192.168.0.0
364
        /// Netmask   : 255.255.255.0
365
        /// Cidr      : 24
366
        /// Start     : 192.168.0.1
367
        /// End       : 192.168.0.254
368
        /// Broadcast : 192.168.0.255.
369
        /// </summary>
370
        /// <param name="network">A string containing an ip network to convert.</param>
371
        /// <param name="sanitanize">Whether to sanitize network or not.</param>
372
        /// <returns>An IPNetwork equivalent to the network contained in string network.</returns>
373
        public static IPNetwork2 Parse(string network, bool sanitanize)
374
        {
×
375
            IPNetwork2.InternalParse(false, network, CidrGuess.ClassFull, sanitanize, out IPNetwork2 ipnetwork);
×
376
            return ipnetwork;
×
377
        }
×
378

379
        /// <summary>
380
        /// 192.168.0.1/24
381
        /// 192.168.0.1 255.255.255.0
382
        ///
383
        /// Network   : 192.168.0.0
384
        /// Netmask   : 255.255.255.0
385
        /// Cidr      : 24
386
        /// Start     : 192.168.0.1
387
        /// End       : 192.168.0.254
388
        /// Broadcast : 192.168.0.255.
389
        /// </summary>
390
        /// <param name="network">A string containing an ip network to convert.</param>
391
        /// <param name="cidrGuess">A ICidrGuess implementation that will be used to guess CIDR during converion.</param>
392
        /// <returns>An IPNetwork equivalent to the network contained in string network.</returns>
393
        public static IPNetwork2 Parse(string network, ICidrGuess cidrGuess)
394
        {
16✔
395
            IPNetwork2.InternalParse(false, network, cidrGuess, true, out IPNetwork2 ipnetwork);
16✔
396
            return ipnetwork;
16✔
397
        }
16✔
398

399
        /// <summary>
400
        /// 192.168.0.1/24
401
        /// 192.168.0.1 255.255.255.0
402
        ///
403
        /// Network   : 192.168.0.0
404
        /// Netmask   : 255.255.255.0
405
        /// Cidr      : 24
406
        /// Start     : 192.168.0.1
407
        /// End       : 192.168.0.254
408
        /// Broadcast : 192.168.0.255.
409
        /// </summary>
410
        /// <param name="network">A string containing an ip network to convert.</param>
411
        /// <param name="cidrGuess">A ICidrGuess implementation that will be used to guess CIDR during converion.</param>
412
        /// <param name="sanitanize">Whether to sanitize network or not.</param>
413
        /// <returns>An IPNetwork equivalent to the network contained in string network.</returns>
414
        public static IPNetwork2 Parse(string network, ICidrGuess cidrGuess, bool sanitanize)
415
        {
×
416
            IPNetwork2.InternalParse(false, network, cidrGuess, sanitanize, out IPNetwork2 ipnetwork);
×
417
            return ipnetwork;
×
418
        }
×
419

420
        #endregion
421

422
        #region TryParse
423

424
        /// <summary>
425
        /// 192.168.168.100 - 255.255.255.0
426
        ///
427
        /// Network   : 192.168.168.0
428
        /// Netmask   : 255.255.255.0
429
        /// Cidr      : 24
430
        /// Start     : 192.168.168.1
431
        /// End       : 192.168.168.254
432
        /// Broadcast : 192.168.168.255.
433
        /// </summary>
434
        /// <param name="ipaddress">A string containing an ip address to convert.</param>
435
        /// <param name="netmask">A string containing a netmaks to convert (255.255.255.0).</param>
436
        /// <param name="ipnetwork">When this method returns, contains the IPNetwork value equivalent of the ip adress contained in ipaddress with the netmask corresponding to cidr, if the conversion succeeded, or null if the conversion failed. The conversion fails if the s parameter is null or Empty, is not of the correct format, or represents an invalid ip address. This parameter is passed uninitialized; any value originally supplied in result will be overwritten.</param>
437
        /// <returns>true if ipaddress/netmask was converted successfully; otherwise, false..</returns>
438
        public static bool TryParse(string ipaddress, string netmask, out IPNetwork2 ipnetwork)
439
        {
20✔
440
            IPNetwork2.InternalParse(true, ipaddress, netmask, out IPNetwork2 ipnetwork2);
20✔
441
            bool parsed = ipnetwork2 != null;
20✔
442
            ipnetwork = ipnetwork2;
20✔
443

444
            return parsed;
20✔
445
        }
20✔
446

447
        /// <summary>
448
        /// 192.168.168.100/24
449
        ///
450
        /// Network   : 192.168.168.0
451
        /// Netmask   : 255.255.255.0
452
        /// Cidr      : 24
453
        /// Start     : 192.168.168.1
454
        /// End       : 192.168.168.254
455
        /// Broadcast : 192.168.168.255.
456
        /// </summary>
457
        /// <param name="ipaddress">A string containing an ip address to convert.</param>
458
        /// <param name="cidr">A byte representing the netmask in cidr format (/24).</param>
459
        /// <param name="ipnetwork">When this method returns, contains the IPNetwork value equivalent of the ip adress contained in ipaddress with the netmask corresponding to cidr, if the conversion succeeded, or null if the conversion failed. The conversion fails if the s parameter is null or Empty, is not of the correct format, or represents an invalid ip address. This parameter is passed uninitialized; any value originally supplied in result will be overwritten.</param>
460
        /// <returns>true if ipaddress/cidr was converted successfully; otherwise, false..</returns>
461
        public static bool TryParse(string ipaddress, byte cidr, out IPNetwork2 ipnetwork)
462
        {
68✔
463
            IPNetwork2.InternalParse(true, ipaddress, cidr, out IPNetwork2 ipnetwork2);
68✔
464
            bool parsed = ipnetwork2 != null;
68✔
465
            ipnetwork = ipnetwork2;
68✔
466

467
            return parsed;
68✔
468
        }
68✔
469

470
        /// <summary>
471
        /// 192.168.0.1/24
472
        /// 192.168.0.1 255.255.255.0
473
        ///
474
        /// Network   : 192.168.0.0
475
        /// Netmask   : 255.255.255.0
476
        /// Cidr      : 24
477
        /// Start     : 192.168.0.1
478
        /// End       : 192.168.0.254
479
        /// Broadcast : 192.168.0.255.
480
        /// </summary>
481
        /// <param name="network">A string containing an ip network to convert.</param>
482
        /// <param name="ipnetwork">When this method returns, contains the IPNetwork value equivalent of the ip adress contained in ipaddress with the netmask corresponding to cidr, if the conversion succeeded, or null if the conversion failed. The conversion fails if the s parameter is null or Empty, is not of the correct format, or represents an invalid ip address. This parameter is passed uninitialized; any value originally supplied in result will be overwritten.</param>
483
        /// <returns>true if network was converted successfully; otherwise, false..</returns>
484
        public static bool TryParse(string network, out IPNetwork2 ipnetwork)
485
        {
44✔
486
            bool sanitanize = true;
44✔
487
            IPNetwork2.InternalParse(true, network, CidrGuess.ClassFull, sanitanize, out IPNetwork2 ipnetwork2);
44✔
488
            bool parsed = ipnetwork2 != null;
44✔
489
            ipnetwork = ipnetwork2;
44✔
490

491
            return parsed;
44✔
492
        }
44✔
493

494
        /// <summary>
495
        /// 192.168.0.1/24
496
        /// 192.168.0.1 255.255.255.0
497
        ///
498
        /// Network   : 192.168.0.0
499
        /// Netmask   : 255.255.255.0
500
        /// Cidr      : 24
501
        /// Start     : 192.168.0.1
502
        /// End       : 192.168.0.254
503
        /// Broadcast : 192.168.0.255.
504
        /// </summary>
505
        /// <param name="network">A string containing an ip network to convert.</param>
506
        /// <param name="sanitanize">Whether to sanitize network or not.</param>
507
        /// <param name="ipnetwork">When this method returns, contains the IPNetwork value equivalent of the ip adress contained in ipaddress with the netmask corresponding to cidr, if the conversion succeeded, or null if the conversion failed. The conversion fails if the s parameter is null or Empty, is not of the correct format, or represents an invalid ip address. This parameter is passed uninitialized; any value originally supplied in result will be overwritten.</param>
508
        /// <returns>true if network was converted successfully; otherwise, false..</returns>
509
        public static bool TryParse(string network, bool sanitanize, out IPNetwork2 ipnetwork)
510
        {
12✔
511
            IPNetwork2.InternalParse(true, network, CidrGuess.ClassFull, sanitanize, out IPNetwork2 ipnetwork2);
12✔
512
            bool parsed = ipnetwork2 != null;
12✔
513
            ipnetwork = ipnetwork2;
12✔
514

515
            return parsed;
12✔
516
        }
12✔
517

518
        /// <summary>
519
        /// 192.168.0.1/24
520
        /// 192.168.0.1 255.255.255.0
521
        ///
522
        /// Network   : 192.168.0.0
523
        /// Netmask   : 255.255.255.0
524
        /// Cidr      : 24
525
        /// Start     : 192.168.0.1
526
        /// End       : 192.168.0.254
527
        /// Broadcast : 192.168.0.255.
528
        /// </summary>
529
        /// <param name="ipaddress">An IPAdresse to convert.</param>
530
        /// <param name="netmask">A IPAdresse to be used as netmaks to convert.</param>
531
        /// <param name="ipnetwork">When this method returns, contains the IPNetwork value equivalent of the ip adress contained in ipaddress with the netmask corresponding to cidr, if the conversion succeeded, or null if the conversion failed. The conversion fails if the s parameter is null or Empty, is not of the correct format, or represents an invalid ip address. This parameter is passed uninitialized; any value originally supplied in result will be overwritten.</param>
532
        /// <returns>true if network was converted successfully; otherwise, false..</returns>
533
        public static bool TryParse(IPAddress ipaddress, IPAddress netmask, out IPNetwork2 ipnetwork)
534
        {
4✔
535
            IPNetwork2.InternalParse(true, ipaddress, netmask, out IPNetwork2 ipnetwork2);
4✔
536
            bool parsed = ipnetwork2 != null;
4✔
537
            ipnetwork = ipnetwork2;
4✔
538

539
            return parsed;
4✔
540
        }
4✔
541

542
        /// <summary>
543
        /// 192.168.0.1/24
544
        /// 192.168.0.1 255.255.255.0
545
        ///
546
        /// Network   : 192.168.0.0
547
        /// Netmask   : 255.255.255.0
548
        /// Cidr      : 24
549
        /// Start     : 192.168.0.1
550
        /// End       : 192.168.0.254
551
        /// Broadcast : 192.168.0.255.
552
        /// </summary>
553
        /// <param name="network">A string containing an ip network to convert.</param>
554
        /// <param name="cidrGuess">A ICidrGuess implementation that will be used to guess CIDR during converion.</param>
555
        /// <param name="ipnetwork">When this method returns, contains the IPNetwork value equivalent of the ip adress contained in ipaddress with the netmask corresponding to cidr, if the conversion succeeded, or null if the conversion failed. The conversion fails if the s parameter is null or Empty, is not of the correct format, or represents an invalid ip address. This parameter is passed uninitialized; any value originally supplied in result will be overwritten.</param>
556
        /// <returns>true if network was converted successfully; otherwise, false..</returns>
557
        public static bool TryParse(string network, ICidrGuess cidrGuess, out IPNetwork2 ipnetwork)
558
        {
×
559
            IPNetwork2.InternalParse(true, network, cidrGuess, true, out IPNetwork2 ipnetwork2);
×
560
            bool parsed = ipnetwork2 != null;
×
561
            ipnetwork = ipnetwork2;
×
562

563
            return parsed;
×
564
        }
×
565

566
        /// <summary>
567
        /// 192.168.0.1/24
568
        /// 192.168.0.1 255.255.255.0
569
        ///
570
        /// Network   : 192.168.0.0
571
        /// Netmask   : 255.255.255.0
572
        /// Cidr      : 24
573
        /// Start     : 192.168.0.1
574
        /// End       : 192.168.0.254
575
        /// Broadcast : 192.168.0.255.
576
        /// </summary>
577
        /// <param name="network">A string containing an ip network to convert.</param>
578
        /// <param name="cidrGuess">A ICidrGuess implementation that will be used to guess CIDR during converion.</param>
579
        /// <param name="sanitanize">Whether to sanitize network or not.</param>
580
        /// <param name="ipnetwork">When this method returns, contains the IPNetwork value equivalent of the ip adress contained in ipaddress with the netmask corresponding to cidr, if the conversion succeeded, or null if the conversion failed. The conversion fails if the s parameter is null or Empty, is not of the correct format, or represents an invalid ip address. This parameter is passed uninitialized; any value originally supplied in result will be overwritten.</param>
581
        /// <returns>true if network was converted successfully; otherwise, false..</returns>
582
        public static bool TryParse(string network, ICidrGuess cidrGuess, bool sanitanize, out IPNetwork2 ipnetwork)
583
        {
×
584
            IPNetwork2.InternalParse(true, network, cidrGuess, sanitanize, out IPNetwork2 ipnetwork2);
×
585
            bool parsed = ipnetwork2 != null;
×
586
            ipnetwork = ipnetwork2;
×
587

588
            return parsed;
×
589
        }
×
590

591
        #endregion
592

593
        #region InternalParse
594

595
        /// <summary>
596
        /// 192.168.168.100 - 255.255.255.0
597
        ///
598
        /// Network   : 192.168.168.0
599
        /// Netmask   : 255.255.255.0
600
        /// Cidr      : 24
601
        /// Start     : 192.168.168.1
602
        /// End       : 192.168.168.254
603
        /// Broadcast : 192.168.168.255.
604
        /// </summary>
605
        /// <param name="tryParse">Whether to throw exception or not during conversion.</param>
606
        /// <param name="ipaddress">A string containing an ip address to convert.</param>
607
        /// <param name="netmask">A string containing a netmask to convert (255.255.255.0).</param>
608
        /// <param name="ipnetwork">The resulting IPNetwork.</param>
609
        private static void InternalParse(bool tryParse, string ipaddress, string netmask, out IPNetwork2 ipnetwork)
610
        {
81✔
611
            if (string.IsNullOrEmpty(ipaddress))
81✔
612
            {
6✔
613
                if (tryParse == false)
6✔
614
                {
3✔
615
                    throw new ArgumentNullException("ipaddress");
3✔
616
                }
617

618
                ipnetwork = null;
3✔
619
                return;
3✔
620
            }
621

622
            if (string.IsNullOrEmpty(netmask))
75✔
623
            {
7✔
624
                if (tryParse == false)
7✔
625
                {
4✔
626
                    throw new ArgumentNullException("netmask");
4✔
627
                }
628

629
                ipnetwork = null;
3✔
630
                return;
3✔
631
            }
632

633
            bool ipaddressParsed = IPAddress.TryParse(ipaddress, out IPAddress ip);
68✔
634
            if (ipaddressParsed == false)
68✔
635
            {
5✔
636
                if (tryParse == false)
5✔
637
                {
3✔
638
                    throw new ArgumentException("ipaddress");
3✔
639
                }
640

641
                ipnetwork = null;
2✔
642
                return;
2✔
643
            }
644

645
            bool netmaskParsed = IPAddress.TryParse(netmask, out IPAddress mask);
63✔
646
            if (netmaskParsed == false)
63✔
647
            {
4✔
648
                if (tryParse == false)
4✔
649
                {
2✔
650
                    throw new ArgumentException("netmask");
2✔
651
                }
652

653
                ipnetwork = null;
2✔
654
                return;
2✔
655
            }
656

657
            IPNetwork2.InternalParse(tryParse, ip, mask, out ipnetwork);
59✔
658
        }
68✔
659

660
        private static void InternalParse(bool tryParse, string network, ICidrGuess cidrGuess, bool sanitanize, out IPNetwork2 ipnetwork)
661
        {
4,000,715✔
662
            if (string.IsNullOrEmpty(network))
4,000,715✔
663
            {
4✔
664
                if (tryParse == false)
4✔
665
                {
2✔
666
                    throw new ArgumentNullException("network");
2✔
667
                }
668

669
                ipnetwork = null;
2✔
670
                return;
2✔
671
            }
672

673
            if (sanitanize)
4,000,711✔
674
            {
4,000,705✔
675
                network = Regex.Replace(network, @"[^0-9a-fA-F\.\/\s\:]+", string.Empty, RegexOptions.None, TimeSpan.FromMilliseconds(100));
4,000,705✔
676
                network = Regex.Replace(network, @"\s{2,}", " ", RegexOptions.None, TimeSpan.FromMilliseconds(100));
4,000,705✔
677
                network = network.Trim();
4,000,705✔
678
            }
4,000,705✔
679

680
            StringSplitOptions splitOptions = sanitanize ? StringSplitOptions.RemoveEmptyEntries : StringSplitOptions.None;
4,000,711✔
681
            string[] args = network.Split(new char[] { ' ', '/' }, splitOptions);
4,000,711✔
682
            byte cidr = 0;
4,000,711✔
683

684
            if (args.Length == 0)
4,000,711✔
685
            {
1✔
686
                if (tryParse == false)
1✔
687
                {
×
688
                    throw new ArgumentNullException("network");
×
689
                }
690
                
691
                ipnetwork = null;
1✔
692
                return;
1✔
693
            }
694
            
695
            if (args.Length == 1)
4,000,710✔
696
            {
46✔
697
                string cidrlessNetwork = args[0];
46✔
698
                if (cidrGuess.TryGuessCidr(cidrlessNetwork, out cidr))
46✔
699
                {
41✔
700
                    IPNetwork2.InternalParse(tryParse, cidrlessNetwork, cidr, out ipnetwork);
41✔
701
                    return;
41✔
702
                }
703

704
                if (tryParse == false)
5✔
705
                {
2✔
706
                    throw new ArgumentException("network");
2✔
707
                }
708

709
                ipnetwork = null;
3✔
710
                return;
3✔
711
            }
712

713
            if (byte.TryParse(args[1], out cidr))
4,000,664✔
714
            {
4,000,617✔
715
                IPNetwork2.InternalParse(tryParse, args[0], cidr, out ipnetwork);
4,000,617✔
716
                return;
4,000,617✔
717
            }
718

719
            IPNetwork2.InternalParse(tryParse, args[0], args[1], out ipnetwork);
47✔
720
            return;
45✔
721
        }
4,000,709✔
722

723
        /// <summary>
724
        /// 192.168.168.100 255.255.255.0
725
        ///
726
        /// Network   : 192.168.168.0
727
        /// Netmask   : 255.255.255.0
728
        /// Cidr      : 24
729
        /// Start     : 192.168.168.1
730
        /// End       : 192.168.168.254
731
        /// Broadcast : 192.168.168.255.
732
        /// </summary>
733
        /// <param name="tryParse">Whether to throw exception or not during conversion.</param>
734
        /// <param name="ipaddress">An ip address to convert.</param>
735
        /// <param name="netmask">A netmask to convert (255.255.255.0).</param>
736
        /// <param name="ipnetwork">The resulting IPNetwork.</param>
737
        private static void InternalParse(bool tryParse, IPAddress ipaddress, IPAddress netmask, out IPNetwork2 ipnetwork)
738
        {
4,000,773✔
739
            if (ipaddress == null)
4,000,773✔
740
            {
4✔
741
                if (tryParse == false)
4✔
742
                {
2✔
743
                    throw new ArgumentNullException("ipaddress");
2✔
744
                }
745

746
                ipnetwork = null;
2✔
747
                return;
2✔
748
            }
749

750
            if (netmask == null)
4,000,769✔
751
            {
4✔
752
                if (tryParse == false)
4✔
753
                {
2✔
754
                    throw new ArgumentNullException("netmask");
2✔
755
                }
756

757
                ipnetwork = null;
2✔
758
                return;
2✔
759
            }
760

761
            var uintIpAddress = IPNetwork2.ToBigInteger(ipaddress);
4,000,765✔
762
            bool parsed = IPNetwork2.TryToCidr(netmask, out byte? cidr2);
4,000,765✔
763
            if (parsed == false)
4,000,765✔
764
            {
3✔
765
                if (tryParse == false)
3✔
766
                {
1✔
767
                    throw new ArgumentException("netmask");
1✔
768
                }
769

770
                ipnetwork = null;
2✔
771
                return;
2✔
772
            }
773

774
            byte cidr = (byte)cidr2;
4,000,762✔
775

776
            var ipnet = new IPNetwork2(uintIpAddress, ipaddress.AddressFamily, cidr);
4,000,762✔
777
            ipnetwork = ipnet;
4,000,762✔
778

779
            return;
4,000,762✔
780
        }
4,000,768✔
781

782
        /// <summary>
783
        /// 192.168.168.100/24
784
        ///
785
        /// Network   : 192.168.168.0
786
        /// Netmask   : 255.255.255.0
787
        /// Cidr      : 24
788
        /// Start     : 192.168.168.1
789
        /// End       : 192.168.168.254
790
        /// Broadcast : 192.168.168.255.
791
        /// </summary>
792
        /// <param name="tryParse">Whether to throw exception or not during conversion.</param>
793
        /// <param name="ipaddress">A string containing an ip address to convert.</param>
794
        /// <param name="cidr">A byte representing the CIDR to be used in conversion (/24).</param>
795
        /// <param name="ipnetwork">The resulting IPNetwork.</param>
796
        private static void InternalParse(bool tryParse, string ipaddress, byte cidr, out IPNetwork2 ipnetwork)
797
        {
4,000,752✔
798
            if (string.IsNullOrEmpty(ipaddress))
4,000,752✔
799
            {
6✔
800
                if (tryParse == false)
6✔
801
                {
2✔
802
                    throw new ArgumentNullException("ipaddress");
2✔
803
                }
804

805
                ipnetwork = null;
4✔
806
                return;
4✔
807
            }
808

809
            bool ipaddressParsed = IPAddress.TryParse(ipaddress, out IPAddress ip);
4,000,746✔
810
            if (ipaddressParsed == false)
4,000,746✔
811
            {
38✔
812
                if (tryParse == false)
38✔
813
                {
2✔
814
                    throw new ArgumentException("ipaddress");
2✔
815
                }
816

817
                ipnetwork = null;
36✔
818
                return;
36✔
819
            }
820

821
            bool parsedNetmask = IPNetwork2.TryToNetmask(cidr, ip.AddressFamily, out IPAddress mask);
4,000,708✔
822
            if (parsedNetmask == false)
4,000,708✔
823
            {
4✔
824
                if (tryParse == false)
4✔
825
                {
2✔
826
                    throw new ArgumentException("cidr");
2✔
827
                }
828

829
                ipnetwork = null;
2✔
830
                return;
2✔
831
            }
832

833
            IPNetwork2.InternalParse(tryParse, ip, mask, out ipnetwork);
4,000,704✔
834
        }
4,000,746✔
835
        #endregion
836

837
        #region converters
838

839
        #region ToUint
840

841
        /// <summary>
842
        /// Convert an ipadress to decimal
843
        /// 0.0.0.0 -> 0
844
        /// 0.0.1.0 -> 256.
845
        /// </summary>
846
        /// <param name="ipaddress">A string containing an ip address to convert.</param>
847
        /// <returns>A number representing the ipaddress.</returns>
848
        public static BigInteger ToBigInteger(IPAddress ipaddress)
849
        {
4,203,504✔
850
            IPNetwork2.InternalToBigInteger(false, ipaddress, out BigInteger? uintIpAddress);
4,203,504✔
851

852
            return (BigInteger)uintIpAddress;
4,203,502✔
853
        }
4,203,502✔
854

855
        /// <summary>
856
        /// Convert an ipadress to decimal
857
        /// 0.0.0.0 -> 0
858
        /// 0.0.1.0 -> 256.
859
        /// </summary>
860
        /// <param name="ipaddress">A string containing an ip address to convert.</param>
861
        /// <param name="uintIpAddress">A number representing the IPAdress.</param>
862
        /// <returns>true if ipaddress was converted successfully; otherwise, false.</returns>
863
        public static bool TryToBigInteger(IPAddress ipaddress, out BigInteger? uintIpAddress)
864
        {
4,000,840✔
865
            IPNetwork2.InternalToBigInteger(true, ipaddress, out BigInteger? uintIpAddress2);
4,000,840✔
866
            bool parsed = uintIpAddress2 != null;
4,000,840✔
867
            uintIpAddress = uintIpAddress2;
4,000,840✔
868

869
            return parsed;
4,000,840✔
870
        }
4,000,840✔
871

872
#if TRAVISCI
873
        public
874
#else
875
        internal
876
#endif
877
            static void InternalToBigInteger(bool tryParse, IPAddress ipaddress, out BigInteger? uintIpAddress)
878
        {
8,204,344✔
879
            if (ipaddress == null)
8,204,344✔
880
            {
4✔
881
                if (tryParse == false)
4✔
882
                {
2✔
883
                    throw new ArgumentNullException("ipaddress");
2✔
884
                }
885

886
                uintIpAddress = null;
2✔
887
                return;
2✔
888
            }
889

890
#if NET5_0 || NETSTANDARD2_1
891
            byte[] bytes = ipaddress.AddressFamily == AddressFamily.InterNetwork ? new byte[4] : new byte[16];
892
            Span<byte> span = bytes.AsSpan();
893
            if (!ipaddress.TryWriteBytes(span, out _))
894
            {
895
                if (tryParse == false)
896
                {
897
                    throw new ArgumentException("ipaddress");
898
                }
899

900
                uintIpAddress = null;
901
                return;
902
            }
903

904
            uintIpAddress = new BigInteger(span, isUnsigned: true, isBigEndian: true);
905
#elif NET45 || NET46 || NET47 || NETSTANDARD20
906
            byte[] bytes = ipaddress.GetAddressBytes();
907
            bytes.AsSpan().Reverse();
908

909
            // add trailing 0 to make unsigned
910
            byte[] unsigned = new byte[bytes.Length + 1];
911
            Buffer.BlockCopy(bytes, 0, unsigned, 0, bytes.Length);
912
            uintIpAddress = new BigInteger(unsigned);
913
#else
914
            byte[] bytes = ipaddress.GetAddressBytes();
8,204,340✔
915
            Array.Reverse(bytes);
8,204,340✔
916

917
            // add trailing 0 to make unsigned
918
            byte[] unsigned = new byte[bytes.Length + 1];
8,204,340✔
919
            Buffer.BlockCopy(bytes, 0, unsigned, 0, bytes.Length);
8,204,340✔
920
            uintIpAddress = new BigInteger(unsigned);
8,204,340✔
921
#endif
922
        }
8,204,342✔
923

924
        /// <summary>
925
        /// Convert a cidr to BigInteger netmask.
926
        /// </summary>
927
        /// <param name="cidr">A byte representing the netmask in cidr format (/24).</param>
928
        /// <param name="family">Either IPv4 or IPv6.</param>
929
        /// <returns>A number representing the netmask exprimed in CIDR.</returns>
930
        public static BigInteger ToUint(byte cidr, AddressFamily family)
931
        {
17,303,541✔
932
            IPNetwork2.InternalToBigInteger(false, cidr, family, out BigInteger? uintNetmask);
17,303,541✔
933

934
            return (BigInteger)uintNetmask;
17,303,540✔
935
        }
17,303,540✔
936

937
        /// <summary>
938
        /// Convert a cidr to uint netmask.
939
        /// </summary>
940
        /// <param name="cidr">A byte representing the netmask in cidr format (/24).</param>
941
        /// <param name="family">Either IPv4 or IPv6.</param>
942
        /// <param name="uintNetmask">A number representing the netmask.</param>
943
        /// <returns>true if cidr was converted successfully; otherwise, false.</returns>
944
        public static bool TryToUint(byte cidr, AddressFamily family, out BigInteger? uintNetmask)
945
        {
1✔
946
            IPNetwork2.InternalToBigInteger(true, cidr, family, out BigInteger? uintNetmask2);
1✔
947
            bool parsed = uintNetmask2 != null;
1✔
948
            uintNetmask = uintNetmask2;
1✔
949

950
            return parsed;
1✔
951
        }
1✔
952

953
        /// <summary>
954
        /// Convert a cidr to uint netmask.
955
        /// </summary>
956
        /// <param name="tryParse">Whether to throw exception or not during conversion.</param>
957
        /// <param name="cidr">A byte representing the netmask in cidr format (/24).</param>
958
        /// <param name="family">Either IPv4 or IPv6.</param>
959
        /// <param name="uintNetmask">A number representing the netmask.</param>
960
#if TRAVISCI
961
        public
962
#else
963
        internal
964
#endif
965
            static void InternalToBigInteger(bool tryParse, byte cidr, AddressFamily family, out BigInteger? uintNetmask)
966
        {
17,303,547✔
967
            if (family == AddressFamily.InterNetwork && cidr > 32)
17,303,547✔
968
            {
2✔
969
                if (tryParse == false)
2✔
970
                {
1✔
971
                    throw new ArgumentOutOfRangeException("cidr");
1✔
972
                }
973

974
                uintNetmask = null;
1✔
975
                return;
1✔
976
            }
977

978
            if (family == AddressFamily.InterNetworkV6 && cidr > 128)
17,303,545✔
979
            {
2✔
980
                if (tryParse == false)
2✔
981
                {
1✔
982
                    throw new ArgumentOutOfRangeException("cidr");
1✔
983
                }
984

985
                uintNetmask = null;
1✔
986
                return;
1✔
987
            }
988

989
            if (family != AddressFamily.InterNetwork
17,303,543✔
990
                && family != AddressFamily.InterNetworkV6)
17,303,543✔
991
            {
2✔
992
                if (tryParse == false)
2✔
993
                {
1✔
994
                    throw new NotSupportedException(family.ToString());
1✔
995
                }
996

997
                uintNetmask = null;
1✔
998
                return;
1✔
999
            }
1000

1001
            if (family == AddressFamily.InterNetwork)
17,303,541✔
1002
            {
17,296,328✔
1003
                uintNetmask = cidr == 0 ? 0 : 0xffffffff << (32 - cidr);
17,296,328✔
1004
                return;
17,296,328✔
1005
            }
1006

1007
            var mask = new BigInteger(new byte[]
7,213✔
1008
            {
7,213✔
1009
                0xff, 0xff, 0xff, 0xff,
7,213✔
1010
                0xff, 0xff, 0xff, 0xff,
7,213✔
1011
                0xff, 0xff, 0xff, 0xff,
7,213✔
1012
                0xff, 0xff, 0xff, 0xff,
7,213✔
1013
                0x00,
7,213✔
1014
            });
7,213✔
1015

1016
            BigInteger masked = cidr == 0 ? 0 : mask << (128 - cidr);
7,213✔
1017
            byte[] m = masked.ToByteArray();
7,213✔
1018
            byte[] bmask = new byte[17];
7,213✔
1019
            int copy = m.Length > 16 ? 16 : m.Length;
7,213✔
1020
            Array.Copy(m, 0, bmask, 0, copy);
7,213✔
1021
            uintNetmask = new BigInteger(bmask);
7,213✔
1022
        }
17,303,544✔
1023

1024
        #endregion
1025

1026
        #region ToCidr
1027

1028
        /// <summary>
1029
        /// Convert netmask to CIDR
1030
        ///  255.255.255.0 -> 24
1031
        ///  255.255.0.0   -> 16
1032
        ///  255.0.0.0     -> 8.
1033
        /// </summary>
1034
        /// <param name="tryParse">Whether to throw exception or not during conversion.</param>
1035
        /// <param name="netmask">A number representing the netmask to convert.</param>
1036
        /// <param name="family">Either IPv4 or IPv6.</param>
1037
        /// <param name="cidr">A byte representing the netmask in cidr format (/24).</param>
1038
        private static void InternalToCidr(bool tryParse, BigInteger netmask, AddressFamily family, out byte? cidr)
1039
        {
4,000,827✔
1040
            if (!IPNetwork2.InternalValidNetmask(netmask, family))
4,000,827✔
1041
            {
6✔
1042
                if (tryParse == false)
6✔
1043
                {
2✔
1044
                    throw new ArgumentException("netmask");
2✔
1045
                }
1046

1047
                cidr = null;
4✔
1048
                return;
4✔
1049
            }
1050

1051
            byte cidr2 = IPNetwork2.BitsSet(netmask, family);
4,000,821✔
1052
            cidr = cidr2;
4,000,821✔
1053

1054
            return;
4,000,821✔
1055
        }
4,000,825✔
1056

1057
        /// <summary>
1058
        /// Convert netmask to CIDR
1059
        ///  255.255.255.0 -> 24
1060
        ///  255.255.0.0   -> 16
1061
        ///  255.0.0.0     -> 8.
1062
        /// </summary>
1063
        /// <param name="netmask">An IPAdress representing the CIDR to convert.</param>
1064
        /// <returns>A byte representing the CIDR converted from the netmask.</returns>
1065
        public static byte ToCidr(IPAddress netmask)
1066
        {
33✔
1067
            IPNetwork2.InternalToCidr(false, netmask, out byte? cidr);
33✔
1068
            return (byte)cidr;
30✔
1069
        }
30✔
1070

1071
        /// <summary>
1072
        /// Convert netmask to CIDR
1073
        ///  255.255.255.0 -> 24
1074
        ///  255.255.0.0   -> 16
1075
        ///  255.0.0.0     -> 8.
1076
        /// </summary>
1077
        /// <param name="netmask">An IPAdress representing the CIDR to convert.</param>
1078
        /// <param name="cidr">A byte representing the netmask in cidr format (/24).</param>
1079
        /// <returns>true if netmask was converted successfully; otherwise, false.</returns>
1080
        public static bool TryToCidr(IPAddress netmask, out byte? cidr)
1081
        {
4,000,796✔
1082
            IPNetwork2.InternalToCidr(true, netmask, out byte? cidr2);
4,000,796✔
1083
            bool parsed = cidr2 != null;
4,000,796✔
1084
            cidr = cidr2;
4,000,796✔
1085
            return parsed;
4,000,796✔
1086
        }
4,000,796✔
1087

1088
        private static void InternalToCidr(bool tryParse, IPAddress netmask, out byte? cidr)
1089
        {
4,000,829✔
1090
            if (netmask == null)
4,000,829✔
1091
            {
2✔
1092
                if (tryParse == false)
2✔
1093
                {
1✔
1094
                    throw new ArgumentNullException("netmask");
1✔
1095
                }
1096

1097
                cidr = null;
1✔
1098
                return;
1✔
1099
            }
1100

1101
            bool parsed = IPNetwork2.TryToBigInteger(netmask, out BigInteger? uintNetmask2);
4,000,827✔
1102

1103
            // 20180217 lduchosal
1104
            // impossible to reach code.
1105
            // if (parsed == false) {
1106
            //     if (tryParse == false) {
1107
            //         throw new ArgumentException("netmask");
1108
            //     }
1109
            //     cidr = null;
1110
            //     return;
1111
            // }
1112
            var uintNetmask = (BigInteger)uintNetmask2;
4,000,827✔
1113

1114
            IPNetwork2.InternalToCidr(tryParse, uintNetmask, netmask.AddressFamily, out byte? cidr2);
4,000,827✔
1115
            cidr = cidr2;
4,000,825✔
1116

1117
            return;
4,000,825✔
1118
        }
4,000,826✔
1119

1120
        #endregion
1121

1122
        #region ToNetmask
1123

1124
        /// <summary>
1125
        /// Convert CIDR to netmask
1126
        ///  24 -> 255.255.255.0
1127
        ///  16 -> 255.255.0.0
1128
        ///  8 -> 255.0.0.0.
1129
        /// </summary>
1130
        /// <see href="http://snipplr.com/view/15557/cidr-class-for-ipv4/"/>
1131
        /// <param name="cidr">A byte representing the netmask in cidr format (/24).</param>
1132
        /// <param name="family">Either IPv4 or IPv6.</param>
1133
        /// <returns>An IPAdress representing cidr.</returns>
1134
        public static IPAddress ToNetmask(byte cidr, AddressFamily family)
1135
        {
15✔
1136
            IPNetwork2.InternalToNetmask(false, cidr, family, out IPAddress netmask);
15✔
1137

1138
            return netmask;
11✔
1139
        }
11✔
1140

1141
        /// <summary>
1142
        /// Convert CIDR to netmask
1143
        ///  24 -> 255.255.255.0
1144
        ///  16 -> 255.255.0.0
1145
        ///  8 -> 255.0.0.0.
1146
        /// </summary>
1147
        /// <see href="http://snipplr.com/view/15557/cidr-class-for-ipv4/"/>
1148
        /// <param name="cidr">A byte representing the netmask in cidr format (/24).</param>
1149
        /// <param name="family">Either IPv4 or IPv6.</param>
1150
        /// <param name="netmask">The resulting netmask.</param>
1151
        /// <returns>true if cidr was converted successfully; otherwise, false.</returns>
1152
        public static bool TryToNetmask(byte cidr, AddressFamily family, out IPAddress netmask)
1153
        {
4,000,721✔
1154
            IPNetwork2.InternalToNetmask(true, cidr, family, out IPAddress netmask2);
4,000,721✔
1155
            bool parsed = netmask2 != null;
4,000,721✔
1156
            netmask = netmask2;
4,000,721✔
1157

1158
            return parsed;
4,000,721✔
1159
        }
4,000,721✔
1160

1161
#if TRAVISCI
1162
        public
1163
#else
1164
        internal
1165
#endif
1166
            static void InternalToNetmask(bool tryParse, byte cidr, AddressFamily family, out IPAddress netmask)
1167
        {
4,000,737✔
1168
            if (family != AddressFamily.InterNetwork
4,000,737✔
1169
                && family != AddressFamily.InterNetworkV6)
4,000,737✔
1170
            {
2✔
1171
                if (tryParse == false)
2✔
1172
                {
1✔
1173
                    throw new ArgumentException("family");
1✔
1174
                }
1175

1176
                netmask = null;
1✔
1177
                return;
1✔
1178
            }
1179

1180
            // 20180217 lduchosal
1181
            // impossible to reach code, byte cannot be negative :
1182
            //
1183
            // if (cidr < 0) {
1184
            //     if (tryParse == false) {
1185
            //         throw new ArgumentOutOfRangeException("cidr");
1186
            //     }
1187
            //     netmask = null;
1188
            //     return;
1189
            // }
1190
            int maxCidr = family == Sockets.AddressFamily.InterNetwork ? 32 : 128;
4,000,735✔
1191
            if (cidr > maxCidr)
4,000,735✔
1192
            {
10✔
1193
                if (tryParse == false)
10✔
1194
                {
3✔
1195
                    throw new ArgumentOutOfRangeException("cidr");
3✔
1196
                }
1197

1198
                netmask = null;
7✔
1199
                return;
7✔
1200
            }
1201

1202
            BigInteger mask = IPNetwork2.ToUint(cidr, family);
4,000,725✔
1203
            var netmask2 = IPNetwork2.ToIPAddress(mask, family);
4,000,725✔
1204
            netmask = netmask2;
4,000,725✔
1205

1206
            return;
4,000,725✔
1207
        }
4,000,733✔
1208

1209
        #endregion
1210

1211
        #endregion
1212

1213
        #region utils
1214

1215
        #region BitsSet
1216

1217
        /// <summary>
1218
        /// Count bits set to 1 in netmask.
1219
        /// </summary>
1220
        /// <see href="http://stackoverflow.com/questions/109023/best-algorithm-to-count-the-number-of-set-bits-in-a-32-bit-integer"/>
1221
        /// <param name="netmask">A number representing the netmask to count bits from.</param>
1222
        /// <param name="family">Either IPv4 or IPv6.</param>
1223
        /// <returns>The number of bytes set to 1.</returns>
1224
        private static byte BitsSet(BigInteger netmask, AddressFamily family)
1225
        {
4,000,829✔
1226
            string s = netmask.ToBinaryString();
4,000,829✔
1227

1228
            return (byte)s.Replace("0", string.Empty)
4,000,829✔
1229
                .ToCharArray()
4,000,829✔
1230
                .Length;
4,000,829✔
1231
        }
4,000,829✔
1232

1233
        /// <summary>
1234
        /// Count bits set to 1 in netmask.
1235
        /// </summary>
1236
        /// <param name="netmask">A number representing the netmask to count bits from.</param>
1237
        /// <returns>The number of bytes set to 1.</returns>
1238
        public static uint BitsSet(IPAddress netmask)
1239
        {
8✔
1240
            var uintNetmask = IPNetwork2.ToBigInteger(netmask);
8✔
1241
            uint bits = IPNetwork2.BitsSet(uintNetmask, netmask.AddressFamily);
8✔
1242

1243
            return bits;
8✔
1244
        }
8✔
1245

1246
        #endregion
1247

1248
        #region ValidNetmask
1249

1250
        /// <summary>
1251
        /// return true if netmask is a valid netmask
1252
        /// 255.255.255.0, 255.0.0.0, 255.255.240.0, ...
1253
        /// </summary>
1254
        /// <see href="http://www.actionsnip.com/snippets/tomo_atlacatl/calculate-if-a-netmask-is-valid--as2-"/>
1255
        /// <param name="netmask">A number representing the netmask to validate.</param>
1256
        /// <returns>true if netmask is a valid IP Netmask; otherwise, false.</returns>
1257
        public static bool ValidNetmask(IPAddress netmask)
1258
        {
11✔
1259
            if (netmask == null)
11✔
1260
            {
1✔
1261
                throw new ArgumentNullException("netmask");
1✔
1262
            }
1263

1264
            var uintNetmask = IPNetwork2.ToBigInteger(netmask);
10✔
1265
            bool valid = IPNetwork2.InternalValidNetmask(uintNetmask, netmask.AddressFamily);
10✔
1266

1267
            return valid;
10✔
1268
        }
10✔
1269

1270
#if TRAVISCI
1271
        public
1272
#else
1273
        internal
1274
#endif
1275
            static bool InternalValidNetmask(BigInteger netmask, AddressFamily family)
1276
        {
4,000,838✔
1277
            if (family != AddressFamily.InterNetwork
4,000,838✔
1278
                && family != AddressFamily.InterNetworkV6)
4,000,838✔
1279
            {
1✔
1280
                throw new ArgumentException("family");
1✔
1281
            }
1282

1283
            BigInteger mask = family == AddressFamily.InterNetwork
4,000,837✔
1284
                ? new BigInteger(0x0ffffffff)
4,000,837✔
1285
                : new BigInteger(new byte[]
4,000,837✔
1286
                {
4,000,837✔
1287
                    0xff, 0xff, 0xff, 0xff,
4,000,837✔
1288
                    0xff, 0xff, 0xff, 0xff,
4,000,837✔
1289
                    0xff, 0xff, 0xff, 0xff,
4,000,837✔
1290
                    0xff, 0xff, 0xff, 0xff,
4,000,837✔
1291
                    0x00,
4,000,837✔
1292
                });
4,000,837✔
1293

1294
            BigInteger neg = (~netmask) & mask;
4,000,837✔
1295
            bool isNetmask = ((neg + 1) & neg) == 0;
4,000,837✔
1296

1297
            return isNetmask;
4,000,837✔
1298
        }
4,000,837✔
1299

1300
        #endregion
1301

1302
        #region ToIPAddress
1303

1304
        /// <summary>
1305
        /// Transform a uint ipaddress into IPAddress object.
1306
        /// </summary>
1307
        /// <param name="ipaddress">A number representing an ip address to convert.</param>
1308
        /// <param name="family">Either IPv4 or IPv6.</param>
1309
        /// <returns>An ip adress.</returns>
1310
        public static IPAddress ToIPAddress(BigInteger ipaddress, AddressFamily family)
1311
        {
8,209,499✔
1312
            int width = family == AddressFamily.InterNetwork ? 4 : 16;
8,209,499✔
1313
            byte[] bytes = ipaddress.ToByteArray();
8,209,499✔
1314
            byte[] bytes2 = new byte[width];
8,209,499✔
1315
            int copy = bytes.Length > width ? width : bytes.Length;
8,209,499✔
1316
            Array.Copy(bytes, 0, bytes2, 0, copy);
8,209,499✔
1317
            Array.Reverse(bytes2);
8,209,499✔
1318

1319
            byte[] sized = Resize(bytes2, family);
8,209,499✔
1320
            var ip = new IPAddress(sized);
8,209,497✔
1321
            return ip;
8,209,497✔
1322
        }
8,209,497✔
1323

1324
#if TRAVISCI
1325
        public
1326
#else
1327
        internal
1328
#endif
1329
            static byte[] Resize(byte[] bytes, AddressFamily family)
1330
        {
8,209,500✔
1331
            if (family != AddressFamily.InterNetwork
8,209,500✔
1332
                && family != AddressFamily.InterNetworkV6)
8,209,500✔
1333
            {
2✔
1334
                throw new ArgumentException("family");
2✔
1335
            }
1336

1337
            int width = family == AddressFamily.InterNetwork ? 4 : 16;
8,209,498✔
1338

1339
            if (bytes.Length > width)
8,209,498✔
1340
            {
1✔
1341
                throw new ArgumentException("bytes");
1✔
1342
            }
1343

1344
            byte[] result = new byte[width];
8,209,497✔
1345
            Array.Copy(bytes, 0, result, 0, bytes.Length);
8,209,497✔
1346

1347
            return result;
8,209,497✔
1348
        }
8,209,497✔
1349

1350
        #endregion
1351

1352
        #endregion
1353

1354
        #region contains
1355

1356
        /// <summary>
1357
        /// return true if ipaddress is contained in network.
1358
        /// </summary>
1359
        /// <param name="contains">A string containing an ip address to convert.</param>
1360
        /// <returns>true if ipaddress is contained into the IP Network; otherwise, false.</returns>
1361
        public bool Contains(IPAddress contains)
1362
        {
189✔
1363
            if (contains == null)
189✔
1364
            {
2✔
1365
                throw new ArgumentNullException("contains");
2✔
1366
            }
1367

1368
            if (this.AddressFamily != contains.AddressFamily)
187✔
1369
            {
1✔
1370
                return false;
1✔
1371
            }
1372

1373
            BigInteger uintNetwork = this._network;
186✔
1374
            BigInteger uintBroadcast = this._broadcast; // CreateBroadcast(ref uintNetwork, this._netmask, this._family);
186✔
1375
            var uintAddress = IPNetwork2.ToBigInteger(contains);
186✔
1376

1377
            bool result = uintAddress >= uintNetwork
186✔
1378
                && uintAddress <= uintBroadcast;
186✔
1379

1380
            return result;
186✔
1381
        }
187✔
1382

1383
        /// <summary>
1384
        /// Determines whether the given IP address is part of the given IP network.
1385
        /// </summary>
1386
        /// <param name="network">The IP network.</param>
1387
        /// <param name="ipaddress">The IP address.</param>
1388
        /// <returns>
1389
        /// <c>true</c> if the IP address is part of the IP network; otherwise, <c>false</c>.
1390
        /// </returns>
1391
        [Obsolete("static Contains is deprecated, please use instance Contains.")]
1392
        public static bool Contains(IPNetwork2 network, IPAddress ipaddress)
1393
        {
2✔
1394
            if (network == null)
2✔
1395
            {
1✔
1396
                throw new ArgumentNullException("network");
1✔
1397
            }
1398

1399
            return network.Contains(ipaddress);
1✔
1400
        }
1✔
1401

1402
        /// <summary>
1403
        /// return true is network2 is fully contained in network.
1404
        /// </summary>
1405
        /// <param name="contains">The network to test.</param>
1406
        /// <returns>It returns the boolean value. If network2 is in IPNetwork then it returns True, otherwise returns False.</returns>
1407
        public bool Contains(IPNetwork2 contains)
1408
        {
264,304✔
1409
            if (contains == null)
264,304✔
1410
            {
1✔
1411
                throw new ArgumentNullException("contains");
1✔
1412
            }
1413

1414
            BigInteger uintNetwork = this._network;
264,303✔
1415
            BigInteger uintBroadcast = this._broadcast; // CreateBroadcast(ref uintNetwork, this._netmask, this._family);
264,303✔
1416

1417
            BigInteger uintFirst = contains._network;
264,303✔
1418
            BigInteger uintLast = contains._broadcast; // CreateBroadcast(ref uintFirst, network2._netmask, network2._family);
264,303✔
1419

1420
            bool result = uintFirst >= uintNetwork
264,303✔
1421
                && uintLast <= uintBroadcast;
264,303✔
1422

1423
            return result;
264,303✔
1424
        }
264,303✔
1425

1426
        /// <summary>
1427
        /// Determines if the given <paramref name="network"/> contains the specified <paramref name="network2"/>.
1428
        /// </summary>
1429
        /// <param name="network">The network to check for containment.</param>
1430
        /// <param name="network2">The network to check if it is contained.</param>
1431
        /// <returns>
1432
        /// <c>true</c> if the <paramref name="network"/> contains the <paramref name="network2"/>; otherwise, <c>false</c>.
1433
        /// </returns>
1434
        [Obsolete("static Contains is deprecated, please use instance Contains.")]
1435
        public static bool Contains(IPNetwork2 network, IPNetwork2 network2)
1436
        {
2✔
1437
            if (network == null)
2✔
1438
            {
1✔
1439
                throw new ArgumentNullException("network");
1✔
1440
            }
1441

1442
            return network.Contains(network2);
1✔
1443
        }
1✔
1444

1445
        private static BigInteger CreateBroadcast(ref BigInteger network, BigInteger netmask, AddressFamily family)
1446
        {
133,817✔
1447
            int width = family == AddressFamily.InterNetwork ? 4 : 16;
133,817✔
1448
            BigInteger uintBroadcast = network + netmask.PositiveReverse(width);
133,817✔
1449

1450
            return uintBroadcast;
133,817✔
1451
        }
133,817✔
1452

1453
        #endregion
1454

1455
        #region overlap
1456

1457
        /// <summary>
1458
        /// return true is network2 overlap network.
1459
        /// </summary>
1460
        /// <param name="network2">The network to test.</param>
1461
        /// <returns>true if network2 overlaps into the IP Network; otherwise, false.</returns>
1462
        public bool Overlap(IPNetwork2 network2)
1463
        {
16✔
1464
            if (network2 == null)
16✔
1465
            {
2✔
1466
                throw new ArgumentNullException("network2");
2✔
1467
            }
1468

1469
            BigInteger uintNetwork = this._network;
14✔
1470
            BigInteger uintBroadcast = this._broadcast;
14✔
1471

1472
            BigInteger uintFirst = network2._network;
14✔
1473
            BigInteger uintLast = network2._broadcast;
14✔
1474

1475
            bool overlap =
14✔
1476
                (uintFirst >= uintNetwork && uintFirst <= uintBroadcast)
14✔
1477
                || (uintLast >= uintNetwork && uintLast <= uintBroadcast)
14✔
1478
                || (uintFirst <= uintNetwork && uintLast >= uintBroadcast)
14✔
1479
                || (uintFirst >= uintNetwork && uintLast <= uintBroadcast);
14✔
1480

1481
            return overlap;
14✔
1482
        }
14✔
1483

1484
        /// <summary>
1485
        /// Determines if two IPNetwork2 objects overlap each other.
1486
        /// </summary>
1487
        /// <param name="network">The first IPNetwork2 object.</param>
1488
        /// <param name="network2">The second IPNetwork2 object.</param>
1489
        /// <returns>Returns true if the two IPNetwork2 objects overlap, otherwise false.</returns>
1490
        [Obsolete("static Overlap is deprecated, please use instance Overlap.")]
1491
        public static bool Overlap(IPNetwork2 network, IPNetwork2 network2)
1492
        {
2✔
1493
            if (network == null)
2✔
1494
            {
1✔
1495
                throw new ArgumentNullException("network");
1✔
1496
            }
1497

1498
            return network.Overlap(network2);
1✔
1499
        }
1✔
1500

1501
        #endregion
1502

1503
        #region ToString
1504

1505
        /// <summary>
1506
        /// Returns a string representation of the object.
1507
        /// </summary>
1508
        /// <returns>
1509
        /// A string representation of the object which includes the Network and Cidr values separated by a "/".
1510
        /// </returns>
1511
        public override string ToString()
1512
        {
4,002,531✔
1513
            return string.Format("{0}/{1}", this.Network, this.Cidr);
4,002,531✔
1514
        }
4,002,531✔
1515

1516
        #endregion
1517

1518
        #region IANA block
1519

1520
        private static readonly Lazy<IPNetwork2> _iana_ablock_reserved = new(() => IPNetwork2.Parse("10.0.0.0/8"));
2✔
1521
        private static readonly Lazy<IPNetwork2> _iana_bblock_reserved = new(() => IPNetwork2.Parse("172.16.0.0/12"));
2✔
1522
        private static readonly Lazy<IPNetwork2> _iana_cblock_reserved = new(() => IPNetwork2.Parse("192.168.0.0/16"));
2✔
1523

1524
        /// <summary>
1525
        /// Gets 10.0.0.0/8.
1526
        /// </summary>
1527
        /// <returns>The IANA reserved IPNetwork 10.0.0.0/8.</returns>
1528
        public static IPNetwork2 IANA_ABLK_RESERVED1
1529
        {
1530
            get
1531
            {
28✔
1532
                return _iana_ablock_reserved.Value;
28✔
1533
            }
28✔
1534
        }
1535

1536
        /// <summary>
1537
        /// Gets 172.12.0.0/12.
1538
        /// </summary>
1539
        /// <returns>The IANA reserved IPNetwork 172.12.0.0/12.</returns>
1540
        public static IPNetwork2 IANA_BBLK_RESERVED1
1541
        {
1542
            get
1543
            {
8✔
1544
                return _iana_bblock_reserved.Value;
8✔
1545
            }
8✔
1546
        }
1547

1548
        /// <summary>
1549
        /// Gets 192.168.0.0/16.
1550
        /// </summary>
1551
        /// <returns>The IANA reserved IPNetwork 192.168.0.0/16.</returns>
1552
        public static IPNetwork2 IANA_CBLK_RESERVED1
1553
        {
1554
            get
1555
            {
14✔
1556
                return _iana_cblock_reserved.Value;
14✔
1557
            }
14✔
1558
        }
1559

1560
        /// <summary>
1561
        /// return true if ipaddress is contained in
1562
        /// IANA_ABLK_RESERVED1, IANA_BBLK_RESERVED1, IANA_CBLK_RESERVED1.
1563
        /// </summary>
1564
        /// <param name="ipaddress">A string containing an ip address to convert.</param>
1565
        /// <returns>true if ipaddress is a IANA reserverd IP Netowkr ; otherwise, false.</returns>
1566
        public static bool IsIANAReserved(IPAddress ipaddress)
1567
        {
5✔
1568
            if (ipaddress == null)
5✔
1569
            {
1✔
1570
                throw new ArgumentNullException("ipaddress");
1✔
1571
            }
1572

1573
            return IPNetwork2.IANA_ABLK_RESERVED1.Contains(ipaddress)
4✔
1574
                || IPNetwork2.IANA_BBLK_RESERVED1.Contains(ipaddress)
4✔
1575
                || IPNetwork2.IANA_CBLK_RESERVED1.Contains(ipaddress);
4✔
1576
        }
4✔
1577

1578
        /// <summary>
1579
        /// return true if ipnetwork is contained in
1580
        /// IANA_ABLK_RESERVED1, IANA_BBLK_RESERVED1, IANA_CBLK_RESERVED1.
1581
        /// </summary>
1582
        /// <returns>true if the ipnetwork is a IANA reserverd IP Netowkr ; otherwise, false.</returns>
1583
        public bool IsIANAReserved()
1584
        {
6✔
1585
            return IPNetwork2.IANA_ABLK_RESERVED1.Contains(this)
6✔
1586
                || IPNetwork2.IANA_BBLK_RESERVED1.Contains(this)
6✔
1587
                || IPNetwork2.IANA_CBLK_RESERVED1.Contains(this);
6✔
1588
        }
6✔
1589

1590
        /// <summary>
1591
        /// Determines whether the specified IP network is reserved according to the IANA Reserved ranges.
1592
        /// </summary>
1593
        /// <param name="ipnetwork">The IP network to check.</param>
1594
        /// <returns>
1595
        /// <c>true</c> if the specified IP network is reserved according to the IANA Reserved ranges; otherwise, <c>false</c>.
1596
        /// </returns>
1597
        /// <remarks>
1598
        /// <para>
1599
        /// This method is obsolete and should not be used. Please use the instance method <see cref="IsIANAReserved"/> instead.
1600
        /// </para>
1601
        /// <para>
1602
        /// Throws an <see cref="ArgumentNullException"/> if <paramref name="ipnetwork"/> is <c>null</c>.
1603
        /// </para>
1604
        /// </remarks>
1605
        [Obsolete("static IsIANAReserved is deprecated, please use instance IsIANAReserved.")]
1606
        public static bool IsIANAReserved(IPNetwork2 ipnetwork)
1607
        {
2✔
1608
            if (ipnetwork == null)
2✔
1609
            {
1✔
1610
                throw new ArgumentNullException("ipnetwork");
1✔
1611
            }
1612

1613
            return ipnetwork.IsIANAReserved();
1✔
1614
        }
1✔
1615

1616
        #endregion
1617

1618
        #region Subnet
1619

1620
        /// <summary>
1621
        /// Subnet a network into multiple nets of cidr mask
1622
        /// Subnet 192.168.0.0/24 into cidr 25 gives 192.168.0.0/25, 192.168.0.128/25
1623
        /// Subnet 10.0.0.0/8 into cidr 9 gives 10.0.0.0/9, 10.128.0.0/9.
1624
        /// </summary>
1625
        /// <param name="cidr">A byte representing the CIDR to be used to subnet the current IPNetwork.</param>
1626
        /// <returns>A IPNetworkCollection splitted by CIDR.</returns>
1627
        public IPNetworkCollection Subnet(byte cidr)
1628
        {
159✔
1629
            IPNetwork2.InternalSubnet(false, this, cidr, out IPNetworkCollection ipnetworkCollection);
159✔
1630

1631
            return ipnetworkCollection;
155✔
1632
        }
155✔
1633

1634
        /// <summary>
1635
        /// Subnet method is used to divide the given IP network into subnets with the specified CIDR.
1636
        /// </summary>
1637
        /// <param name="network">The IP network to be subnetted.</param>
1638
        /// <param name="cidr">The CIDR (Classless Inter-Domain Routing) value used to subnet the network.</param>
1639
        /// <returns>
1640
        /// A collection of subnets created from the given network using the specified CIDR.
1641
        /// </returns>
1642
        [Obsolete("static Subnet is deprecated, please use instance Subnet.")]
1643
        public static IPNetworkCollection Subnet(IPNetwork2 network, byte cidr)
1644
        {
2✔
1645
            if (network == null)
2✔
1646
            {
1✔
1647
                throw new ArgumentNullException("network");
1✔
1648
            }
1649

1650
            return network.Subnet(cidr);
1✔
1651
        }
1✔
1652

1653
        /// <summary>
1654
        /// Subnet a network into multiple nets of cidr mask
1655
        /// Subnet 192.168.0.0/24 into cidr 25 gives 192.168.0.0/25, 192.168.0.128/25
1656
        /// Subnet 10.0.0.0/8 into cidr 9 gives 10.0.0.0/9, 10.128.0.0/9.
1657
        /// </summary>
1658
        /// <param name="cidr">A byte representing the CIDR to be used to subnet the current IPNetwork.</param>
1659
        /// <param name="ipnetworkCollection">The resulting subnetted IPNetwork.</param>
1660
        /// <returns>true if network was split successfully; otherwise, false.</returns>
1661
        public bool TrySubnet(byte cidr, out IPNetworkCollection ipnetworkCollection)
1662
        {
10✔
1663
            IPNetwork2.InternalSubnet(true, this, cidr, out IPNetworkCollection inc);
10✔
1664
            if (inc == null)
10✔
1665
            {
4✔
1666
                ipnetworkCollection = null;
4✔
1667
                return false;
4✔
1668
            }
1669

1670
            ipnetworkCollection = inc;
6✔
1671
            return true;
6✔
1672
        }
10✔
1673

1674
        /// <summary>
1675
        /// Subnet a network into multiple nets of cidr mask
1676
        /// Subnet 192.168.0.0/24 into cidr 25 gives 192.168.0.0/25, 192.168.0.128/25
1677
        /// Subnet 10.0.0.0/8 into cidr 9 gives 10.0.0.0/9, 10.128.0.0/9.
1678
        /// </summary>
1679
        /// <param name="network"></param>
1680
        /// <param name="cidr">A byte representing the CIDR to be used to subnet the current IPNetwork.</param>
1681
        /// <param name="ipnetworkCollection">The resulting subnetted IPNetwork.</param>
1682
        /// <returns>true if network was split successfully; otherwise, false.</returns>
1683
        [Obsolete("static TrySubnet is deprecated, please use instance TrySubnet.")]
1684
        public static bool TrySubnet(IPNetwork2 network, byte cidr, out IPNetworkCollection ipnetworkCollection)
1685
        {
2✔
1686
            if (network == null)
2✔
1687
            {
1✔
1688
                throw new ArgumentNullException("network");
1✔
1689
            }
1690

1691
            return network.TrySubnet(cidr, out ipnetworkCollection);
1✔
1692
        }
1✔
1693

1694
#if TRAVISCI
1695
        public
1696
#else
1697
        internal
1698
#endif
1699
            static void InternalSubnet(bool trySubnet, IPNetwork2 network, byte cidr, out IPNetworkCollection ipnetworkCollection)
1700
        {
171✔
1701
            if (network == null)
171✔
1702
            {
2✔
1703
                if (trySubnet == false)
2✔
1704
                {
1✔
1705
                    throw new ArgumentNullException("network");
1✔
1706
                }
1707

1708
                ipnetworkCollection = null;
1✔
1709
                return;
1✔
1710
            }
1711

1712
            int maxCidr = network._family == Sockets.AddressFamily.InterNetwork ? 32 : 128;
169✔
1713
            if (cidr > maxCidr)
169✔
1714
            {
4✔
1715
                if (trySubnet == false)
4✔
1716
                {
2✔
1717
                    throw new ArgumentOutOfRangeException("cidr");
2✔
1718
                }
1719

1720
                ipnetworkCollection = null;
2✔
1721
                return;
2✔
1722
            }
1723

1724
            if (cidr < network.Cidr)
165✔
1725
            {
4✔
1726
                if (trySubnet == false)
4✔
1727
                {
2✔
1728
                    throw new ArgumentException("cidr");
2✔
1729
                }
1730

1731
                ipnetworkCollection = null;
2✔
1732
                return;
2✔
1733
            }
1734

1735
            ipnetworkCollection = new IPNetworkCollection(network, cidr);
161✔
1736
            return;
161✔
1737
        }
166✔
1738

1739
        #endregion
1740

1741
        #region Supernet
1742

1743
        /// <summary>
1744
        /// Supernet two consecutive cidr equal subnet into a single one
1745
        /// 192.168.0.0/24 + 192.168.1.0/24 = 192.168.0.0/23
1746
        /// 10.1.0.0/16 + 10.0.0.0/16 = 10.0.0.0/15
1747
        /// 192.168.0.0/24 + 192.168.0.0/25 = 192.168.0.0/24.
1748
        /// </summary>
1749
        /// <param name="network2">The network to supernet with.</param>
1750
        /// <returns>A supernetted IP Network.</returns>
1751
        public IPNetwork2 Supernet(IPNetwork2 network2)
1752
        {
10✔
1753
            IPNetwork2.InternalSupernet(false, this, network2, out IPNetwork2 supernet);
10✔
1754
            return supernet;
5✔
1755
        }
5✔
1756

1757
        /// <summary>
1758
        /// Supernet two consecutive cidr equal subnet into a single one
1759
        /// 192.168.0.0/24 + 192.168.1.0/24 = 192.168.0.0/23
1760
        /// 10.1.0.0/16 + 10.0.0.0/16 = 10.0.0.0/15
1761
        /// 192.168.0.0/24 + 192.168.0.0/25 = 192.168.0.0/24.
1762
        /// </summary>
1763
        /// <param name="network"></param>
1764
        /// <param name="network2">The network to supernet with.</param>
1765
        /// <returns>A supernetted IP Network.</returns>
1766
        [Obsolete("static Supernet is deprecated, please use instance Supernet.")]
1767
        public static IPNetwork2 Supernet(IPNetwork2 network, IPNetwork2 network2)
1768
        {
1✔
1769
            return network.Supernet(network2);
1✔
1770
        }
1✔
1771

1772
        /// <summary>
1773
        /// Try to supernet two consecutive cidr equal subnet into a single one
1774
        /// 192.168.0.0/24 + 192.168.1.0/24 = 192.168.0.0/23
1775
        /// 10.1.0.0/16 + 10.0.0.0/16 = 10.0.0.0/15
1776
        /// 192.168.0.0/24 + 192.168.0.0/25 = 192.168.0.0/24.
1777
        /// </summary>
1778
        /// <param name="network2">The network to supernet with.</param>
1779
        /// <param name="supernet">The resulting IPNetwork.</param>
1780
        /// <returns>true if network2 was supernetted successfully; otherwise, false.</returns>
1781
        public bool TrySupernet(IPNetwork2 network2, out IPNetwork2 supernet)
1782
        {
132,131✔
1783
            IPNetwork2.InternalSupernet(true, this, network2, out IPNetwork2 outSupernet);
132,131✔
1784
            bool parsed = outSupernet != null;
132,131✔
1785
            supernet = outSupernet;
132,131✔
1786
            return parsed;
132,131✔
1787
        }
132,131✔
1788

1789
        /// <summary>
1790
        /// Try to supernet two consecutive cidr equal subnet into a single one
1791
        /// 192.168.0.0/24 + 192.168.1.0/24 = 192.168.0.0/23
1792
        /// 10.1.0.0/16 + 10.0.0.0/16 = 10.0.0.0/15
1793
        /// 192.168.0.0/24 + 192.168.0.0/25 = 192.168.0.0/24.
1794
        /// </summary>
1795
        /// <param name="network"></param>
1796
        /// <param name="network2">The network to supernet with.</param>
1797
        /// <param name="supernet">The resulting IPNetwork.</param>
1798
        /// <returns>true if network2 was supernetted successfully; otherwise, false.</returns>
1799
        [Obsolete("static TrySupernet is deprecated, please use instance TrySupernet.")]
1800
        public static bool TrySupernet(IPNetwork2 network, IPNetwork2 network2, out IPNetwork2 supernet)
1801
        {
3✔
1802
            if (network == null)
3✔
1803
            {
2✔
1804
                throw new ArgumentNullException("network");
2✔
1805
            }
1806

1807
            return network.TrySupernet(network2, out supernet);
1✔
1808
        }
1✔
1809

1810
#if TRAVISCI
1811
        public
1812
#else
1813
        internal
1814
#endif
1815
            static void InternalSupernet(bool trySupernet, IPNetwork2 network1, IPNetwork2 network2, out IPNetwork2 supernet)
1816
        {
132,143✔
1817
            if (network1 == null)
132,143✔
1818
            {
2✔
1819
                if (trySupernet == false)
2✔
1820
                {
1✔
1821
                    throw new ArgumentNullException("network1");
1✔
1822
                }
1823

1824
                supernet = null;
1✔
1825
                return;
1✔
1826
            }
1827

1828
            if (network2 == null)
132,141✔
1829
            {
3✔
1830
                if (trySupernet == false)
3✔
1831
                {
1✔
1832
                    throw new ArgumentNullException("network2");
1✔
1833
                }
1834

1835
                supernet = null;
2✔
1836
                return;
2✔
1837
            }
1838

1839
            if (network1.Contains(network2))
132,138✔
1840
            {
9✔
1841
                supernet = new IPNetwork2(network1._network, network1._family, network1.Cidr);
9✔
1842
                return;
9✔
1843
            }
1844

1845
            if (network2.Contains(network1))
132,129✔
1846
            {
3✔
1847
                supernet = new IPNetwork2(network2._network, network2._family, network2.Cidr);
3✔
1848
                return;
3✔
1849
            }
1850

1851
            if (network1._cidr != network2._cidr)
132,126✔
1852
            {
66,039✔
1853
                if (trySupernet == false)
66,039✔
1854
                {
1✔
1855
                    throw new ArgumentException("cidr");
1✔
1856
                }
1857

1858
                supernet = null;
66,038✔
1859
                return;
66,038✔
1860
            }
1861

1862
            IPNetwork2 first = (network1._network < network2._network) ? network1 : network2;
66,087✔
1863
            IPNetwork2 last = (network1._network > network2._network) ? network1 : network2;
66,087✔
1864

1865
            // Starting from here :
1866
            // network1 and network2 have the same cidr,
1867
            // network1 does not contain network2,
1868
            // network2 does not contain network1,
1869
            // first is the lower subnet
1870
            // last is the higher subnet
1871
            if ((first._broadcast + 1) != last._network)
66,087✔
1872
            {
10✔
1873
                if (trySupernet == false)
10✔
1874
                {
2✔
1875
                    throw new ArgumentOutOfRangeException("network1");
2✔
1876
                }
1877

1878
                supernet = null;
8✔
1879
                return;
8✔
1880
            }
1881

1882
            BigInteger uintSupernet = first._network;
66,077✔
1883
            byte cidrSupernet = (byte)(first._cidr - 1);
66,077✔
1884

1885
            var networkSupernet = new IPNetwork2(uintSupernet, first._family, cidrSupernet);
66,077✔
1886
            if (networkSupernet._network != first._network)
66,077✔
1887
            {
7✔
1888
                if (trySupernet == false)
7✔
1889
                {
1✔
1890
                    throw new ArgumentException("network");
1✔
1891
                }
1892

1893
                supernet = null;
6✔
1894
                return;
6✔
1895
            }
1896

1897
            supernet = networkSupernet;
66,070✔
1898
            return;
66,070✔
1899
        }
132,137✔
1900

1901
        #endregion
1902

1903
        #region GetHashCode
1904

1905
        /// <inheritdoc />
1906
        public override int GetHashCode()
1907
        {
6,000,033✔
1908
            return this._hashCode;
6,000,033✔
1909
        }
6,000,033✔
1910

1911
        /// <summary>
1912
        /// 20221105 : ldvhcosal
1913
        /// GetHashCode uses mutable attributes. That introduce undefined behaviour on Hashtable and dictionary.
1914
        /// </summary>
1915
        /// <returns>An number representing the hashCode.</returns>
1916
        private int ComputeHashCode()
1917
        {
6,135,758✔
1918
            return string.Format(
6,135,758✔
1919
                "{0}|{1}|{2}",
6,135,758✔
1920
                this._family.GetHashCode(),
6,135,758✔
1921
                this._network.GetHashCode(),
6,135,758✔
1922
                this._cidr.GetHashCode()).GetHashCode();
6,135,758✔
1923
        }
6,135,758✔
1924

1925
        #endregion
1926

1927
        #region SupernetArray
1928

1929
        /// <summary>
1930
        /// Supernet a list of subnet
1931
        /// 192.168.0.0/24 + 192.168.1.0/24 = 192.168.0.0/23
1932
        /// 192.168.0.0/24 + 192.168.1.0/24 + 192.168.2.0/24 + 192.168.3.0/24 = 192.168.0.0/22.
1933
        /// </summary>
1934
        /// <param name="ipnetworks">A list of IPNetwork to merge into common supernets.</param>
1935
        /// <returns>The result of IPNetwork if merges succeed, the first ipnetwork otherwise.</returns>
1936
        public static IPNetwork2[] Supernet(IPNetwork2[] ipnetworks)
1937
        {
15✔
1938
            InternalSupernet(false, ipnetworks, out IPNetwork2[] supernet);
15✔
1939
            return supernet;
14✔
1940
        }
14✔
1941

1942
        /// <summary>
1943
        /// Supernet a list of subnet
1944
        /// 192.168.0.0/24 + 192.168.1.0/24 = 192.168.0.0/23
1945
        /// 192.168.0.0/24 + 192.168.1.0/24 + 192.168.2.0/24 + 192.168.3.0/24 = 192.168.0.0/22.
1946
        /// </summary>
1947
        /// <param name="ipnetworks">A list of IPNetwork to merge into common supernets.</param>
1948
        /// <param name="supernet">The result of IPNetwork merges.</param>
1949
        /// <returns>true if ipnetworks was supernetted successfully; otherwise, false.</returns>
1950
        public static bool TrySupernet(IPNetwork2[] ipnetworks, out IPNetwork2[] supernet)
1951
        {
7✔
1952
            bool supernetted = InternalSupernet(true, ipnetworks, out supernet);
7✔
1953
            return supernetted;
7✔
1954
        }
7✔
1955

1956
#if TRAVISCI
1957
        public
1958
#else
1959
        internal
1960
#endif
1961
        static bool InternalSupernet(bool trySupernet, IPNetwork2[] ipnetworks, out IPNetwork2[] supernet)
1962
        {
22✔
1963
            if (ipnetworks == null)
22✔
1964
            {
3✔
1965
                if (trySupernet == false)
3✔
1966
                {
1✔
1967
                    throw new ArgumentNullException("ipnetworks");
1✔
1968
                }
1969

1970
                supernet = null;
2✔
1971
                return false;
2✔
1972
            }
1973

1974
            if (ipnetworks.Length <= 0)
19✔
1975
            {
1✔
1976
                supernet = new IPNetwork2[0];
1✔
1977
                return true;
1✔
1978
            }
1979

1980
            var supernetted = new List<IPNetwork2>();
18✔
1981
            List<IPNetwork2> ipns = IPNetwork2.Array2List(ipnetworks);
18✔
1982
            Stack<IPNetwork2> current = IPNetwork2.List2Stack(ipns);
18✔
1983
            int previousCount = 0;
18✔
1984
            int currentCount = current.Count;
18✔
1985

1986
            while (previousCount != currentCount)
83✔
1987
            {
65✔
1988
                supernetted.Clear();
65✔
1989
                while (current.Count > 1)
132,181✔
1990
                {
132,116✔
1991
                    IPNetwork2 ipn1 = current.Pop();
132,116✔
1992
                    IPNetwork2 ipn2 = current.Peek();
132,116✔
1993

1994
                    bool success = ipn1.TrySupernet(ipn2, out IPNetwork2 outNetwork);
132,116✔
1995
                    if (success)
132,116✔
1996
                    {
66,072✔
1997
                        current.Pop();
66,072✔
1998
                        current.Push(outNetwork);
66,072✔
1999
                    }
66,072✔
2000
                    else
2001
                    {
66,044✔
2002
                        supernetted.Add(ipn1);
66,044✔
2003
                    }
66,044✔
2004
                }
132,116✔
2005

2006
                if (current.Count == 1)
65✔
2007
                {
65✔
2008
                    supernetted.Add(current.Pop());
65✔
2009
                }
65✔
2010

2011
                previousCount = currentCount;
65✔
2012
                currentCount = supernetted.Count;
65✔
2013
                current = IPNetwork2.List2Stack(supernetted);
65✔
2014
            }
65✔
2015

2016
            supernet = supernetted.ToArray();
18✔
2017
            return true;
18✔
2018
        }
21✔
2019

2020
        private static Stack<IPNetwork2> List2Stack(List<IPNetwork2> list)
2021
        {
83✔
2022
            var stack = new Stack<IPNetwork2>();
83✔
2023
            list.ForEach(new Action<IPNetwork2>(
83✔
2024
                delegate(IPNetwork2 ipn)
83✔
2025
                {
132,209✔
2026
                    stack.Push(ipn);
132,209✔
2027
                }));
132,292✔
2028
            return stack;
83✔
2029
        }
83✔
2030

2031
        private static List<IPNetwork2> Array2List(IPNetwork2[] array)
2032
        {
18✔
2033
            var ipns = new List<IPNetwork2>();
18✔
2034
            ipns.AddRange(array);
18✔
2035
            IPNetwork2.RemoveNull(ipns);
18✔
2036
            ipns.Sort(new Comparison<IPNetwork2>(
18✔
2037
                delegate(IPNetwork2 ipn1, IPNetwork2 ipn2)
18✔
2038
                {
850,489✔
2039
                    int networkCompare = ipn1._network.CompareTo(ipn2._network);
850,489✔
2040
                    if (networkCompare == 0)
850,489✔
2041
                    {
1✔
2042
                        int cidrCompare = ipn1._cidr.CompareTo(ipn2._cidr);
1✔
2043
                        return cidrCompare;
1✔
2044
                    }
18✔
2045

18✔
2046
                    return networkCompare;
850,488✔
2047
                }));
850,507✔
2048
            ipns.Reverse();
18✔
2049

2050
            return ipns;
18✔
2051
        }
18✔
2052

2053
        private static void RemoveNull(List<IPNetwork2> ipns)
2054
        {
18✔
2055
            ipns.RemoveAll(new Predicate<IPNetwork2>(
18✔
2056
                delegate(IPNetwork2 ipn)
18✔
2057
                {
66,104✔
2058
                    if (ipn == null)
66,104✔
2059
                    {
4✔
2060
                        return true;
4✔
2061
                    }
18✔
2062

18✔
2063
                    return false;
66,100✔
2064
                }));
66,122✔
2065
        }
18✔
2066

2067
        #endregion
2068

2069
        #region WideSubnet
2070

2071
        /// <summary>
2072
        /// Finds the widest subnet that can contain both the start and end IP addresses.
2073
        /// </summary>
2074
        /// <param name="start">The starting IP address.</param>
2075
        /// <param name="end">The ending IP address.</param>
2076
        /// <returns>The widest subnet that contains both the start and end IP addresses.</returns>
2077
        /// <exception cref="ArgumentNullException">Thrown when either the start or end IP address is null or empty.</exception>
2078
        /// <exception cref="ArgumentException">Thrown when the start or end IP addresses are not valid.</exception>
2079
        /// <exception cref="NotSupportedException">Thrown when the start and end IP addresses have different address families.</exception>
2080
        public static IPNetwork2 WideSubnet(string start, string end)
2081
        {
1✔
2082
            if (string.IsNullOrEmpty(start))
1✔
2083
            {
×
2084
                throw new ArgumentNullException("start");
×
2085
            }
2086

2087
            if (string.IsNullOrEmpty(end))
1✔
2088
            {
×
2089
                throw new ArgumentNullException("end");
×
2090
            }
2091

2092
            if (!IPAddress.TryParse(start, out IPAddress startIP))
1✔
2093
            {
×
2094
                throw new ArgumentException("start");
×
2095
            }
2096

2097
            if (!IPAddress.TryParse(end, out IPAddress endIP))
1✔
2098
            {
×
2099
                throw new ArgumentException("end");
×
2100
            }
2101

2102
            if (startIP.AddressFamily != endIP.AddressFamily)
1✔
2103
            {
×
2104
                throw new NotSupportedException("MixedAddressFamily");
×
2105
            }
2106

2107
            var ipnetwork = new IPNetwork2(0, startIP.AddressFamily, 0);
1✔
2108
            for (byte cidr = 32; cidr >= 0; cidr--)
40✔
2109
            {
20✔
2110
                var wideSubnet = IPNetwork2.Parse(start, cidr);
20✔
2111
                if (wideSubnet.Contains(endIP))
20✔
2112
                {
1✔
2113
                    ipnetwork = wideSubnet;
1✔
2114
                    break;
1✔
2115
                }
2116
            }
19✔
2117

2118
            return ipnetwork;
1✔
2119
        }
1✔
2120

2121
        /// <summary>
2122
        /// Attempts to find the widest subnet that contains both the start and end IP addresses. objects.
2123
        /// </summary>
2124
        /// <param name="ipnetworks">An array of IPNetwork2 objects to wide subnet.</param>
2125
        /// <param name="ipnetwork">When this method returns, contains the wide subnet of the IPNetwork2 objects, if wide subnet was successful; otherwise, null.</param>
2126
        /// <returns>true if wide subnet was successful; otherwise, false.</returns>
2127
        public static bool TryWideSubnet(IPNetwork2[] ipnetworks, out IPNetwork2 ipnetwork)
2128
        {
6✔
2129
            IPNetwork2.InternalWideSubnet(true, ipnetworks, out IPNetwork2 ipn);
6✔
2130
            if (ipn == null)
6✔
2131
            {
2✔
2132
                ipnetwork = null;
2✔
2133
                return false;
2✔
2134
            }
2135

2136
            ipnetwork = ipn;
4✔
2137

2138
            return true;
4✔
2139
        }
6✔
2140

2141
        /// <summary>
2142
        /// Finds the widest subnet from an array of IP networks. </summary> <param name="ipnetworks">An array of IPNetwork2 objects representing the IP networks.</param> <returns>The widest subnet as an IPNetwork2 object.</returns>
2143
        /// /
2144
        public static IPNetwork2 WideSubnet(IPNetwork2[] ipnetworks)
2145
        {
6✔
2146
            IPNetwork2.InternalWideSubnet(false, ipnetworks, out IPNetwork2 ipn);
6✔
2147
            return ipn;
3✔
2148
        }
3✔
2149

2150
        internal static void InternalWideSubnet(bool tryWide, IPNetwork2[] ipnetworks, out IPNetwork2 ipnetwork)
2151
        {
12✔
2152
            if (ipnetworks == null)
12✔
2153
            {
2✔
2154
                if (tryWide == false)
2✔
2155
                {
1✔
2156
                    throw new ArgumentNullException("ipnetworks");
1✔
2157
                }
2158

2159
                ipnetwork = null;
1✔
2160
                return;
1✔
2161
            }
2162

2163
            IPNetwork2[] nnin = Array.FindAll<IPNetwork2>(ipnetworks, new Predicate<IPNetwork2>(
10✔
2164
                delegate(IPNetwork2 ipnet)
10✔
2165
                {
23✔
2166
                    return ipnet != null;
23✔
2167
                }));
33✔
2168

2169
            if (nnin.Length <= 0)
10✔
2170
            {
2✔
2171
                if (tryWide == false)
2✔
2172
                {
1✔
2173
                    throw new ArgumentException("ipnetworks");
1✔
2174
                }
2175

2176
                ipnetwork = null;
1✔
2177
                return;
1✔
2178
            }
2179

2180
            if (nnin.Length == 1)
8✔
2181
            {
1✔
2182
                IPNetwork2 ipn0 = nnin[0];
1✔
2183
                ipnetwork = ipn0;
1✔
2184
                return;
1✔
2185
            }
2186

2187
            Array.Sort<IPNetwork2>(nnin);
7✔
2188
            IPNetwork2 nnin0 = nnin[0];
7✔
2189
            BigInteger uintNnin0 = nnin0._ipaddress;
7✔
2190

2191
            IPNetwork2 nninX = nnin[nnin.Length - 1];
7✔
2192
            IPAddress ipaddressX = nninX.Broadcast;
7✔
2193

2194
            AddressFamily family = ipnetworks[0]._family;
7✔
2195
            foreach (IPNetwork2 ipnx in ipnetworks)
64✔
2196
            {
22✔
2197
                if (ipnx._family != family)
22✔
2198
                {
1✔
2199
                    throw new ArgumentException("MixedAddressFamily");
1✔
2200
                }
2201
            }
21✔
2202

2203
            var ipn = new IPNetwork2(0, family, 0);
6✔
2204
            for (byte cidr = nnin0._cidr; cidr >= 0; cidr--)
264✔
2205
            {
132✔
2206
                var wideSubnet = new IPNetwork2(uintNnin0, family, cidr);
132✔
2207
                if (wideSubnet.Contains(ipaddressX))
132✔
2208
                {
6✔
2209
                    ipn = wideSubnet;
6✔
2210
                    break;
6✔
2211
                }
2212
            }
126✔
2213

2214
            ipnetwork = ipn;
6✔
2215
            return;
6✔
2216
        }
9✔
2217

2218
        #endregion
2219

2220
        #region Print
2221

2222
        /// <summary>
2223
        /// Print an ipnetwork in a clear representation string.
2224
        /// </summary>
2225
        /// <returns>Dump an IPNetwork representation as string.</returns>
2226
        public string Print()
2227
        {
2✔
2228
            using (var sw = new StringWriter())
2✔
2229
            {
2✔
2230
                sw.WriteLine("IPNetwork   : {0}", this.ToString());
2✔
2231
                sw.WriteLine("Network     : {0}", this.Network);
2✔
2232
                sw.WriteLine("Netmask     : {0}", this.Netmask);
2✔
2233
                sw.WriteLine("Cidr        : {0}", this.Cidr);
2✔
2234
                sw.WriteLine("Broadcast   : {0}", this.Broadcast);
2✔
2235
                sw.WriteLine("FirstUsable : {0}", this.FirstUsable);
2✔
2236
                sw.WriteLine("LastUsable  : {0}", this.LastUsable);
2✔
2237
                sw.WriteLine("Usable      : {0}", this.Usable);
2✔
2238

2239
                return sw.ToString();
2✔
2240
            }
2241
        }
2✔
2242

2243
        /// <summary>
2244
        /// Print an ipnetwork in a clear representation string.
2245
        /// </summary>
2246
        /// <returns>Dump an IPNetwork representation as string.</returns>
2247
        [Obsolete("static Print is deprecated, please use instance Print.")]
2248
        public static string Print(IPNetwork2 ipnetwork)
2249
        {
2✔
2250
            if (ipnetwork == null)
2✔
2251
            {
1✔
2252
                throw new ArgumentNullException("ipnetwork");
1✔
2253
            }
2254

2255
            return ipnetwork.Print();
1✔
2256
        }
1✔
2257

2258
        #endregion
2259

2260
        #region TryGuessCidr
2261

2262
        /// <summary>
2263
        /// Delegate to CidrGuess ClassFull guessing of cidr.
2264
        /// </summary>
2265
        /// <param name="ip">A string representing an IPAdress that will be used to guess the corresponding CIDR.</param>
2266
        /// <param name="cidr">The resulting CIDR as byte.</param>
2267
        /// <returns>true if cidr was guessed successfully; otherwise, false.</returns>
2268
        public static bool TryGuessCidr(string ip, out byte cidr)
2269
        {
9✔
2270
            return CidrGuess.ClassFull.TryGuessCidr(ip, out cidr);
9✔
2271
        }
9✔
2272

2273
        /// <summary>
2274
        /// Try to parse cidr. Have to be >= 0 and &lt;= 32 or 128.
2275
        /// </summary>
2276
        /// <param name="sidr">A string representing a byte CIRD (/24).</param>
2277
        /// <param name="family">Either IPv4 or IPv6.</param>
2278
        /// <param name="cidr">The resulting CIDR as byte.</param>
2279
        /// <returns>true if cidr was converted successfully; otherwise, false.</returns>
2280
        public static bool TryParseCidr(string sidr, AddressFamily family, out byte? cidr)
2281
        {
11✔
2282
            byte b = 0;
11✔
2283
            if (!byte.TryParse(sidr, out b))
11✔
2284
            {
2✔
2285
                cidr = null;
2✔
2286
                return false;
2✔
2287
            }
2288

2289
            if (!IPNetwork2.TryToNetmask(b, family, out IPAddress netmask))
9✔
2290
            {
2✔
2291
                cidr = null;
2✔
2292
                return false;
2✔
2293
            }
2294

2295
            cidr = b;
7✔
2296
            return true;
7✔
2297
        }
11✔
2298

2299
        #endregion
2300

2301
        #region ListIPAddress
2302

2303
        /// <summary>
2304
        /// List all ip addresses in a subnet.
2305
        /// </summary>
2306
        /// <param name="ipnetwork">The network to list IPAdresses.</param>
2307
        /// <returns>All the IPAdresses contained in ipnetwork.</returns>
2308
        [Obsolete("static ListIPAddress is deprecated, please use instance ListIPAddress.")]
2309
        public static IPAddressCollection ListIPAddress(IPNetwork2 ipnetwork)
2310
        {
1✔
2311
            return ipnetwork.ListIPAddress();
1✔
2312
        }
1✔
2313

2314
        /// <summary>
2315
        /// List all ip addresses in a subnet.
2316
        /// </summary>
2317
        /// <param name="filter">Filter IPAdresses from IPNetwork.</param>
2318
        /// <returns>The filterted IPAdresses contained in ipnetwork.</returns>
2319
        public IPAddressCollection ListIPAddress(FilterEnum filter = FilterEnum.All)
2320
        {
32✔
2321
            return new IPAddressCollection(this, filter);
32✔
2322
        }
32✔
2323

2324
        #endregion
2325

2326
        #region IComparable<IPNetwork> Members
2327

2328
        /// <summary>
2329
        /// Compares two IPNetwork2 instances.
2330
        /// </summary>
2331
        /// <param name="left">The first IPNetwork2 instance to compare.</param>
2332
        /// <param name="right">The second IPNetwork2 instance to compare.</param>
2333
        /// <returns>
2334
        /// A value indicating the relative order of the two IPNetwork2 instances.
2335
        /// Zero if the instances are equal.
2336
        /// A negative value if <paramref name="left"/> is less than <paramref name="right"/>.
2337
        /// A positive value if <paramref name="left"/> is greater than <paramref name="right"/>.
2338
        /// </returns>
2339
        public static int Compare(IPNetwork2 left, IPNetwork2 right)
2340
        {
727,389✔
2341
            // two null IPNetworks are equal
2342
            if (ReferenceEquals(left, null) && ReferenceEquals(right, null))
727,389✔
2343
            {
66,144✔
2344
                return 0;
66,144✔
2345
            }
2346

2347
            // two same IPNetworks are equal
2348
            if (ReferenceEquals(left, right))
661,245✔
2349
            {
8✔
2350
                return 0;
8✔
2351
            }
2352

2353
            // null is always sorted first
2354
            if (ReferenceEquals(left, null))
661,237✔
2355
            {
1✔
2356
                return -1;
1✔
2357
            }
2358

2359
            if (ReferenceEquals(right, null))
661,236✔
2360
            {
661,067✔
2361
                return 1;
661,067✔
2362
            }
2363

2364
            // first test family
2365
            int result = left._family.CompareTo(right._family);
169✔
2366
            if (result != 0)
169✔
2367
            {
2✔
2368
                return result;
2✔
2369
            }
2370

2371
            // second test the network
2372
            result = left._network.CompareTo(right._network);
167✔
2373
            if (result != 0)
167✔
2374
            {
44✔
2375
                return result;
44✔
2376
            }
2377

2378
            // then test the cidr
2379
            result = left._cidr.CompareTo(right._cidr);
123✔
2380
            return result;
123✔
2381
        }
727,389✔
2382

2383
        /// <summary>
2384
        /// Compare two ipnetworks.
2385
        /// </summary>
2386
        /// <param name="other">The other network to compare to.</param>
2387
        /// <returns>A signed number indicating the relative values of this instance and value..</returns>
2388
        public int CompareTo(IPNetwork2 other)
2389
        {
38✔
2390
            return Compare(this, other);
38✔
2391
        }
38✔
2392

2393
        /// <summary>
2394
        /// Compare two ipnetworks.
2395
        /// </summary>
2396
        /// <param name="obj">The other object to compare to.</param>
2397
        /// <returns>A signed number indicating the relative values of this instance and value..</returns>
2398
        public int CompareTo(object obj)
2399
        {
3✔
2400
            // null is at less
2401
            if (obj == null)
3✔
2402
            {
1✔
2403
                return 1;
1✔
2404
            }
2405

2406
            // convert to a proper Cidr object
2407
            var other = obj as IPNetwork2;
2✔
2408

2409
            // type problem if null
2410
            if (other == null)
2✔
2411
            {
1✔
2412
                throw new ArgumentException(
1✔
2413
                    "The supplied parameter is an invalid type. Please supply an IPNetwork type.",
1✔
2414
                    "obj");
1✔
2415
            }
2416

2417
            // perform the comparision
2418
            return this.CompareTo(other);
1✔
2419
        }
2✔
2420

2421
        #endregion
2422

2423
        #region IEquatable<IPNetwork> Members
2424

2425
        /// <summary>
2426
        /// Compare two ipnetworks.
2427
        /// </summary>
2428
        /// <param name="left">An IPNetwork to compare.</param>
2429
        /// <param name="right">An other IPNetwork to compare to.</param>
2430
        /// <returns>true if obj has the same value as this instance; otherwise, false.</returns>
2431
        public static bool Equals(IPNetwork2 left, IPNetwork2 right)
2432
        {
727,345✔
2433
            return Compare(left, right) == 0;
727,345✔
2434
        }
727,345✔
2435

2436
        /// <summary>
2437
        /// Compare two ipnetworks.
2438
        /// </summary>
2439
        /// <param name="other">An IPNetwork to compare to this instance.</param>
2440
        /// <returns>true if obj has the same value as this instance; otherwise, false.</returns>
2441
        public bool Equals(IPNetwork2 other)
2442
        {
9✔
2443
            return Equals(this, other);
9✔
2444
        }
9✔
2445

2446
        /// <summary>
2447
        /// Compare two ipnetworks.
2448
        /// </summary>
2449
        /// <param name="obj">An object value to compare to this instance.</param>
2450
        /// <returns>true if obj has the same value as this instance; otherwise, false.</returns>
2451
        public override bool Equals(object obj)
2452
        {
126✔
2453
            return Equals(this, obj as IPNetwork2);
126✔
2454
        }
126✔
2455

2456
        #endregion
2457

2458
        #region Operators
2459

2460
        /// <summary>
2461
        /// Compares two IPNetwork.
2462
        /// </summary>
2463
        /// <param name="left">left instance.</param>
2464
        /// <param name="right">Right instance.</param>
2465
        /// <returns>true if left equals right; otherwise, false.</returns>
2466
        public static bool operator ==(IPNetwork2 left, IPNetwork2 right)
2467
        {
594,906✔
2468
            return Equals(left, right);
594,906✔
2469
        }
594,906✔
2470

2471
        /// <summary>
2472
        /// Compares two IPNetwork.
2473
        /// </summary>
2474
        /// <param name="left">left instance.</param>
2475
        /// <param name="right">Right instance.</param>
2476
        /// <returns>true if left does not equals right; otherwise, false.</returns>
2477
        public static bool operator !=(IPNetwork2 left, IPNetwork2 right)
2478
        {
132,304✔
2479
            return !Equals(left, right);
132,304✔
2480
        }
132,304✔
2481

2482
        /// <summary>
2483
        /// Compares two IPNetwork.
2484
        /// </summary>
2485
        /// <param name="left">left instance.</param>
2486
        /// <param name="right">Right instance.</param>
2487
        /// <returns>true if left is less than right; otherwise, false.</returns>
2488
        public static bool operator <(IPNetwork2 left, IPNetwork2 right)
2489
        {
2✔
2490
            return Compare(left, right) < 0;
2✔
2491
        }
2✔
2492

2493
        /// <summary>
2494
        /// Compares two IPNetwork.
2495
        /// </summary>
2496
        /// <param name="left">left instance.</param>
2497
        /// <param name="right">Right instance.</param>
2498
        /// <returns>true if left is greater than right; otherwise, false.</returns>
2499
        public static bool operator >(IPNetwork2 left, IPNetwork2 right)
2500
        {
2✔
2501
            return Compare(left, right) > 0;
2✔
2502
        }
2✔
2503

2504
        #endregion
2505

2506
        #region XmlSerialization
2507

2508
        /// <summary>
2509
        /// Initializes a new instance of the <see cref="IPNetwork2"/> class.
2510
        /// Created for DataContractSerialization. Better use static methods IPNetwork.Parse() to create IPNetworks.
2511
        /// </summary>
2512
        public IPNetwork2()
2513
            : this(0, AddressFamily.InterNetwork, 0)
2,000,003✔
2514
        {
2,000,003✔
2515
        }
2,000,003✔
2516

2517
        #endregion
2518

2519
        #region ISerializable
2520
        internal struct IPNetworkInteral
2521
        {
2522
            public BigInteger IPAddress;
2523
            public byte Cidr;
2524
            public AddressFamily AddressFamily;
2525
        }
2526

2527
        private IPNetwork2(SerializationInfo info, StreamingContext context)
2,000,003✔
2528
        {
2,000,003✔
2529
            string sipnetwork = (string)info.GetValue("IPNetwork", typeof(string));
2,000,003✔
2530
            var ipnetwork = IPNetwork2.Parse(sipnetwork);
2,000,003✔
2531

2532
            this._ipaddress = ipnetwork._ipaddress;
2,000,003✔
2533
            this._cidr = ipnetwork._cidr;
2,000,003✔
2534
            this._family = ipnetwork._family;
2,000,003✔
2535
        }
2,000,003✔
2536

2537
        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
2538
        {
2,000,004✔
2539
            info.AddValue("IPNetwork", this.ToString());
2,000,004✔
2540
        }
2,000,004✔
2541

2542
        #endregion
2543

2544
        #region WildcardMask
2545

2546
        /// <summary>
2547
        /// Gets netmask Inverse
2548
        /// https://en.wikipedia.org/wiki/Wildcard_mask
2549
        ///
2550
        /// A wildcard mask is a mask of bits that indicates which parts of an IP address are available for examination.
2551
        /// In the Cisco IOS,[1] they are used in several places, for example:
2552
        ///    To indicate the size of a network or subnet for some routing protocols, such as OSPF.
2553
        ///    To indicate what IP addresses should be permitted or denied in access control lists(ACLs).
2554
        ///
2555
        /// A wildcard mask can be thought of as an inverted subnet mask.For example,
2556
        /// a subnet mask of 255.255.255.0 (binary equivalent = 11111111.11111111.11111111.00000000)
2557
        /// inverts to a wildcard mask of 0.0.0.255 (binary equivalent = 00000000.00000000.00000000.11111111).
2558
        ///
2559
        /// A wild card mask is a matching rule.[2] The rule for a wildcard mask is:
2560
        ///     0 means that the equivalent bit must match
2561
        ///     1 means that the equivalent bit does not matter
2562
        ///
2563
        /// Any wildcard bit-pattern can be masked for examination.For example, a wildcard mask of 0.0.0.254
2564
        /// (binary equivalent = 00000000.00000000.00000000.11111110) applied to IP address 10.10.10.2
2565
        /// (00001010.00001010.00001010.00000010) will match even-numbered IP addresses 10.10.10.0, 10.10.10.2,
2566
        /// 10.10.10.4, 10.10.10.6 etc.
2567
        ///
2568
        /// Same mask applied to 10.10.10.1 (00001010.00001010.00001010.00000001) will match
2569
        /// odd-numbered IP addresses 10.10.10.1, 10.10.10.3, 10.10.10.5 etc.
2570
        ///
2571
        /// A network and wildcard mask combination of 1.1.1.1 0.0.0.0 would match an interface configured
2572
        /// exactly with 1.1.1.1 only, and nothing else.
2573
        ///
2574
        /// Wildcard masks are used in situations where subnet masks may not apply.For example,
2575
        /// when two affected hosts fall in different subnets, the use of a wildcard mask will
2576
        /// group them together.
2577
        ///
2578
        /// List of wildcard masks
2579
        /// Slash Netmask Wildcard mask
2580
        /// /32   255.255.255.255    0.0.0.0
2581
        /// /31   255.255.255.254    0.0.0.1
2582
        /// /30   255.255.255.252    0.0.0.3
2583
        /// /29   255.255.255.248    0.0.0.7
2584
        /// /28   255.255.255.240    0.0.0.15
2585
        /// /27   255.255.255.224    0.0.0.31
2586
        /// /26   255.255.255.192    0.0.0.63
2587
        /// /25   255.255.255.128    0.0.0.127
2588
        /// /24   255.255.255.0      0.0.0.255
2589
        /// /23   255.255.254.0      0.0.1.255
2590
        /// /22   255.255.252.0      0.0.3.255
2591
        /// /21   255.255.248.0      0.0.7.255
2592
        /// /20   255.255.240.0      0.0.15.255
2593
        /// /19   255.255.224.0      0.0.31.255
2594
        /// /18   255.255.192.0      0.0.63.255
2595
        /// /17   255.255.128.0      0.0.127.255
2596
        /// /16   255.255.0.0        0.0.255.255
2597
        /// /15   255.254.0.0        0.1.255.255
2598
        /// /14   255.252.0.0        0.3.255.255
2599
        /// /13   255.248.0.0        0.7.255.255
2600
        /// /12   255.240.0.0        0.15.255.255
2601
        /// /11   255.224.0.0        0.31.255.255
2602
        /// /10   255.192.0.0        0.63.255.255
2603
        /// /9    255.128.0.0        0.127.255.255
2604
        /// /8    255.0.0.0          0.255.255.255
2605
        /// /7    254.0.0.0          1.255.255.255
2606
        /// /6    252.0.0.0          3.255.255.255
2607
        /// /5    248.0.0.0          7.255.255.255
2608
        /// /4    240.0.0.0          15.255.255.255
2609
        /// /3    224.0.0.0          31.255.255.255
2610
        /// /2    192.0.0.0          63.255.255.255
2611
        /// /1    128.0.0.0          127.255.255.255
2612
        /// /0    0.0.0.0            255.255.255.255.
2613
        ///
2614
        /// </summary>
2615
        public IPAddress WildcardMask
2616
        {
2617
            get
2618
            {
202✔
2619
                byte cidr = this._family == AddressFamily.InterNetwork ? (byte)32 : (byte)128;
202✔
2620
                BigInteger netmask = IPNetwork2.ToUint(cidr, this._family);
202✔
2621
                BigInteger wildcardmask = netmask - this._netmask;
202✔
2622

2623
                return IPNetwork2.ToIPAddress(wildcardmask, this._family);
202✔
2624
            }
202✔
2625
        }
2626
        #endregion
2627
    }
2628
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc