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

lduchosal / ipnetwork / 581

02 Jun 2023 08:29AM UTC coverage: 94.615%. Remained the same
581

push

appveyor

web-flow
Merge pull request #271 from lduchosal/dependabot/nuget/Microsoft.CodeCoverage-17.6.1

Build(deps): Bump Microsoft.CodeCoverage from 17.6.0 to 17.6.1

1599 of 1690 relevant lines covered (94.62%)

1185099.52 hits per line

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

99.03
/src/System.Net.IPNetwork/IPNetwork.cs
1
// <copyright file="IPNetwork.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.ComponentModel;
9
    using System.IO;
10
    using System.Net.Sockets;
11
    using System.Numerics;
12
    using System.Runtime.Serialization;
13
    using System.Text.RegularExpressions;
14

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

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

30
        private AddressFamily _family;
31

32
        [DataMember(Name = "IPNetwork", IsRequired = true)]
33
        public string Value
34
        {
35
            get
36
            {
2,000,002✔
37
                return this.ToString();
2,000,002✔
38
            }
2,000,002✔
39

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

53
        #endregion
54

55
        #region accessors
56

57
        internal BigInteger _network
58
        {
59
            get
60
            {
17,168,543✔
61
                BigInteger uintNetwork = this._ipaddress & this._netmask;
17,168,543✔
62
                return uintNetwork;
17,168,543✔
63
            }
17,168,543✔
64
        }
65

66
        /// <summary>
67
        /// Gets network address.
68
        /// </summary>
69
        public IPAddress Network
70
        {
71
            get
72
            {
6,136,455✔
73
                return IPNetwork.ToIPAddress(this._network, this._family);
6,136,455✔
74
            }
6,136,455✔
75
        }
76

77
        /// <summary>
78
        /// Gets address Family.
79
        /// </summary>
80
        public AddressFamily AddressFamily
81
        {
82
            get
83
            {
134,039✔
84
                return this._family;
134,039✔
85
            }
134,039✔
86
        }
87

88
        internal BigInteger _netmask
89
        {
90
            get
91
            {
17,303,023✔
92
                return IPNetwork.ToUint(this._cidr, this._family);
17,303,023✔
93
            }
17,303,023✔
94
        }
95

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

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

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

125
                    var network = this._network;
133,911✔
126
                    var computed = CreateBroadcast(ref network, this._netmask, this._family);
133,911✔
127
                    this._cachedBroadcast = computed;
133,911✔
128
                    return computed;
133,911✔
129
                }
130
            }
663,363✔
131
        }
132

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

145
                return IPNetwork.ToIPAddress(this._broadcast, this._family);
66,799✔
146
            }
66,830✔
147
        }
148

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

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

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

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

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

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

220
        #endregion
221

222
        #region constructor
223

224
#if TRAVISCI
225
        public
226
#else
227
        internal
8,133,842✔
228
#endif
8,133,842✔
229
            IPNetwork(BigInteger ipaddress, AddressFamily family, byte cidr)
8,133,842✔
230
        {
8,133,842✔
231
            this.Init(ipaddress, family, cidr);
8,133,842✔
232
            this._hashCode = this.ComputeHashCode();
8,133,841✔
233
        }
8,133,841✔
234

235
        /// <summary>
236
        /// Initializes a new instance of the <see cref="IPNetwork"/> class.
237
        /// Creates a new IPNetwork.
238
        /// </summary>
239
        /// <param name="ipaddress">An ipaddress.</param>
240
        /// <param name="cidr">A byte representing the netmask in cidr format (/24).</param>
241
        /// <exception cref="ArgumentNullException">ipaddress is null.</exception>
242
        public IPNetwork(IPAddress ipaddress, byte cidr)
2,033✔
243
        {
2,033✔
244
            if (ipaddress == null)
2,033✔
245
            {
1✔
246
                throw new ArgumentNullException("ipaddress");
1✔
247
            }
248

249
            BigInteger uintIpAddress = ToBigInteger(ipaddress);
2,032✔
250

251
            this.Init(uintIpAddress, ipaddress.AddressFamily, cidr);
2,032✔
252
            this._hashCode = this.ComputeHashCode();
2,030✔
253
        }
2,030✔
254

255
        private void Init(BigInteger ipaddress, AddressFamily family, byte cidr)
256
        {
8,135,874✔
257
            int maxCidr = family == AddressFamily.InterNetwork ? 32 : 128;
8,135,874✔
258
            if (cidr > maxCidr)
8,135,874✔
259
            {
3✔
260
                throw new ArgumentOutOfRangeException("cidr");
3✔
261
            }
262

263
            this._ipaddress = ipaddress;
8,135,871✔
264
            this._family = family;
8,135,871✔
265
            this._cidr = cidr;
8,135,871✔
266
        }
8,135,871✔
267

268
        #endregion
269

270
        #region parsers
271

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

294
        /// <summary>
295
        /// 192.168.168.100/24
296
        ///
297
        /// Network   : 192.168.168.0
298
        /// Netmask   : 255.255.255.0
299
        /// Cidr      : 24
300
        /// Start     : 192.168.168.1
301
        /// End       : 192.168.168.254
302
        /// Broadcast : 192.168.168.255.
303
        /// </summary>
304
        /// <param name="ipaddress">A string containing an ip address to convert.</param>
305
        /// <param name="cidr">A byte representing the netmask in cidr format (/24).</param>
306
        /// <returns>An IPNetwork equivalent to the network contained in ipaddress/cidr.</returns>
307
        public static IPNetwork Parse(string ipaddress, byte cidr)
308
        {
119✔
309
            IPNetwork.InternalParse(false, ipaddress, cidr, out IPNetwork ipnetwork);
119✔
310
            return ipnetwork;
113✔
311
        }
113✔
312

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

332
        /// <summary>
333
        /// 192.168.0.1/24
334
        /// 192.168.0.1 255.255.255.0
335
        ///
336
        /// Network   : 192.168.0.0
337
        /// Netmask   : 255.255.255.0
338
        /// Cidr      : 24
339
        /// Start     : 192.168.0.1
340
        /// End       : 192.168.0.254
341
        /// Broadcast : 192.168.0.255.
342
        /// </summary>
343
        /// <param name="network">A string containing an ip network to convert.</param>
344
        /// <returns>An IPNetwork equivalent to the network contained in string network.</returns>
345
        public static IPNetwork Parse(string network)
346
        {
6,000,657✔
347
            IPNetwork.InternalParse(false, network, CidrGuess.ClassFull, true, out IPNetwork ipnetwork);
6,000,657✔
348
            return ipnetwork;
6,000,651✔
349
        }
6,000,651✔
350

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

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

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

412
        #endregion
413

414
        #region TryParse
415

416
        /// <summary>
417
        /// 192.168.168.100 - 255.255.255.0
418
        ///
419
        /// Network   : 192.168.168.0
420
        /// Netmask   : 255.255.255.0
421
        /// Cidr      : 24
422
        /// Start     : 192.168.168.1
423
        /// End       : 192.168.168.254
424
        /// Broadcast : 192.168.168.255.
425
        /// </summary>
426
        /// <param name="ipaddress">A string containing an ip address to convert.</param>
427
        /// <param name="netmask">A string containing a netmaks to convert (255.255.255.0).</param>
428
        /// <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>
429
        /// <returns>true if ipaddress/netmask was converted successfully; otherwise, false..</returns>
430
        public static bool TryParse(string ipaddress, string netmask, out IPNetwork ipnetwork)
431
        {
20✔
432
            IPNetwork.InternalParse(true, ipaddress, netmask, out IPNetwork ipnetwork2);
20✔
433
            bool parsed = ipnetwork2 != null;
20✔
434
            ipnetwork = ipnetwork2;
20✔
435

436
            return parsed;
20✔
437
        }
20✔
438

439
        /// <summary>
440
        /// 192.168.168.100/24
441
        ///
442
        /// Network   : 192.168.168.0
443
        /// Netmask   : 255.255.255.0
444
        /// Cidr      : 24
445
        /// Start     : 192.168.168.1
446
        /// End       : 192.168.168.254
447
        /// Broadcast : 192.168.168.255.
448
        /// </summary>
449
        /// <param name="ipaddress">A string containing an ip address to convert.</param>
450
        /// <param name="cidr">A byte representing the netmask in cidr format (/24).</param>
451
        /// <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>
452
        /// <returns>true if ipaddress/cidr was converted successfully; otherwise, false..</returns>
453
        public static bool TryParse(string ipaddress, byte cidr, out IPNetwork ipnetwork)
454
        {
68✔
455
            IPNetwork.InternalParse(true, ipaddress, cidr, out IPNetwork ipnetwork2);
68✔
456
            bool parsed = ipnetwork2 != null;
68✔
457
            ipnetwork = ipnetwork2;
68✔
458

459
            return parsed;
68✔
460
        }
68✔
461

462
        /// <summary>
463
        /// 192.168.0.1/24
464
        /// 192.168.0.1 255.255.255.0
465
        ///
466
        /// Network   : 192.168.0.0
467
        /// Netmask   : 255.255.255.0
468
        /// Cidr      : 24
469
        /// Start     : 192.168.0.1
470
        /// End       : 192.168.0.254
471
        /// Broadcast : 192.168.0.255.
472
        /// </summary>
473
        /// <param name="network">A string containing an ip network to convert.</param>
474
        /// <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>
475
        /// <returns>true if network was converted successfully; otherwise, false..</returns>
476
        public static bool TryParse(string network, out IPNetwork ipnetwork)
477
        {
43✔
478
            bool sanitanize = true;
43✔
479
            IPNetwork.InternalParse(true, network, CidrGuess.ClassFull, sanitanize, out IPNetwork ipnetwork2);
43✔
480
            bool parsed = ipnetwork2 != null;
43✔
481
            ipnetwork = ipnetwork2;
43✔
482

483
            return parsed;
43✔
484
        }
43✔
485

486
        /// <summary>
487
        /// 192.168.0.1/24
488
        /// 192.168.0.1 255.255.255.0
489
        ///
490
        /// Network   : 192.168.0.0
491
        /// Netmask   : 255.255.255.0
492
        /// Cidr      : 24
493
        /// Start     : 192.168.0.1
494
        /// End       : 192.168.0.254
495
        /// Broadcast : 192.168.0.255.
496
        /// </summary>
497
        /// <param name="network">A string containing an ip network to convert.</param>
498
        /// <param name="sanitanize">Whether to sanitize network or not.</param>
499
        /// <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>
500
        /// <returns>true if network was converted successfully; otherwise, false..</returns>
501
        public static bool TryParse(string network, bool sanitanize, out IPNetwork ipnetwork)
502
        {
12✔
503
            IPNetwork.InternalParse(true, network, CidrGuess.ClassFull, sanitanize, out IPNetwork ipnetwork2);
12✔
504
            bool parsed = ipnetwork2 != null;
12✔
505
            ipnetwork = ipnetwork2;
12✔
506

507
            return parsed;
12✔
508
        }
12✔
509

510
        /// <summary>
511
        /// 192.168.0.1/24
512
        /// 192.168.0.1 255.255.255.0
513
        ///
514
        /// Network   : 192.168.0.0
515
        /// Netmask   : 255.255.255.0
516
        /// Cidr      : 24
517
        /// Start     : 192.168.0.1
518
        /// End       : 192.168.0.254
519
        /// Broadcast : 192.168.0.255.
520
        /// </summary>
521
        /// <param name="ipaddress">An IPAdresse to convert.</param>
522
        /// <param name="netmask">A IPAdresse to be used as netmaks to convert.</param>
523
        /// <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>
524
        /// <returns>true if network was converted successfully; otherwise, false..</returns>
525
        public static bool TryParse(IPAddress ipaddress, IPAddress netmask, out IPNetwork ipnetwork)
526
        {
4✔
527
            IPNetwork.InternalParse(true, ipaddress, netmask, out IPNetwork ipnetwork2);
4✔
528
            bool parsed = ipnetwork2 != null;
4✔
529
            ipnetwork = ipnetwork2;
4✔
530

531
            return parsed;
4✔
532
        }
4✔
533

534
        #endregion
535

536
        #region InternalParse
537

538
        /// <summary>
539
        /// 192.168.168.100 - 255.255.255.0
540
        ///
541
        /// Network   : 192.168.168.0
542
        /// Netmask   : 255.255.255.0
543
        /// Cidr      : 24
544
        /// Start     : 192.168.168.1
545
        /// End       : 192.168.168.254
546
        /// Broadcast : 192.168.168.255.
547
        /// </summary>
548
        /// <param name="tryParse">Whether to throw exception or not during conversion.</param>
549
        /// <param name="ipaddress">A string containing an ip address to convert.</param>
550
        /// <param name="netmask">A string containing a netmask to convert (255.255.255.0).</param>
551
        /// <param name="ipnetwork">The resulting IPNetwork.</param>
552
        private static void InternalParse(bool tryParse, string ipaddress, string netmask, out IPNetwork ipnetwork)
553
        {
81✔
554
            if (string.IsNullOrEmpty(ipaddress))
81✔
555
            {
6✔
556
                if (tryParse == false)
6✔
557
                {
3✔
558
                    throw new ArgumentNullException("ipaddress");
3✔
559
                }
560

561
                ipnetwork = null;
3✔
562
                return;
3✔
563
            }
564

565
            if (string.IsNullOrEmpty(netmask))
75✔
566
            {
7✔
567
                if (tryParse == false)
7✔
568
                {
4✔
569
                    throw new ArgumentNullException("netmask");
4✔
570
                }
571

572
                ipnetwork = null;
3✔
573
                return;
3✔
574
            }
575

576
            bool ipaddressParsed = IPAddress.TryParse(ipaddress, out IPAddress ip);
68✔
577
            if (ipaddressParsed == false)
68✔
578
            {
5✔
579
                if (tryParse == false)
5✔
580
                {
3✔
581
                    throw new ArgumentException("ipaddress");
3✔
582
                }
583

584
                ipnetwork = null;
2✔
585
                return;
2✔
586
            }
587

588
            bool netmaskParsed = IPAddress.TryParse(netmask, out IPAddress mask);
63✔
589
            if (netmaskParsed == false)
63✔
590
            {
4✔
591
                if (tryParse == false)
4✔
592
                {
2✔
593
                    throw new ArgumentException("netmask");
2✔
594
                }
595

596
                ipnetwork = null;
2✔
597
                return;
2✔
598
            }
599

600
            IPNetwork.InternalParse(tryParse, ip, mask, out ipnetwork);
59✔
601
        }
68✔
602

603
        private static void InternalParse(bool tryParse, string network, ICidrGuess cidrGuess, bool sanitanize, out IPNetwork ipnetwork)
604
        {
6,000,728✔
605
            if (string.IsNullOrEmpty(network))
6,000,728✔
606
            {
4✔
607
                if (tryParse == false)
4✔
608
                {
2✔
609
                    throw new ArgumentNullException("network");
2✔
610
                }
611

612
                ipnetwork = null;
2✔
613
                return;
2✔
614
            }
615

616
            if (sanitanize)
6,000,724✔
617
            {
6,000,718✔
618
                network = Regex.Replace(network, @"[^0-9a-fA-F\.\/\s\:]+", string.Empty);
6,000,718✔
619
                network = Regex.Replace(network, @"\s{2,}", " ");
6,000,718✔
620
                network = network.Trim();
6,000,718✔
621
            }
6,000,718✔
622

623
            StringSplitOptions splitOptions = sanitanize ? StringSplitOptions.RemoveEmptyEntries : StringSplitOptions.None;
6,000,724✔
624
            string[] args = network.Split(new char[] { ' ', '/' }, splitOptions);
6,000,724✔
625
            byte cidr = 0;
6,000,724✔
626

627
            if (args.Length == 1)
6,000,724✔
628
            {
46✔
629
                string cidrlessNetwork = args[0];
46✔
630
                if (cidrGuess.TryGuessCidr(cidrlessNetwork, out cidr))
46✔
631
                {
41✔
632
                    IPNetwork.InternalParse(tryParse, cidrlessNetwork, cidr, out ipnetwork);
41✔
633
                    return;
41✔
634
                }
635

636
                if (tryParse == false)
5✔
637
                {
2✔
638
                    throw new ArgumentException("network");
2✔
639
                }
640

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

645
            if (byte.TryParse(args[1], out cidr))
6,000,678✔
646
            {
6,000,631✔
647
                IPNetwork.InternalParse(tryParse, args[0], cidr, out ipnetwork);
6,000,631✔
648
                return;
6,000,631✔
649
            }
650

651
            IPNetwork.InternalParse(tryParse, args[0], args[1], out ipnetwork);
47✔
652
            return;
45✔
653
        }
6,000,722✔
654

655
        /// <summary>
656
        /// 192.168.168.100 255.255.255.0
657
        ///
658
        /// Network   : 192.168.168.0
659
        /// Netmask   : 255.255.255.0
660
        /// Cidr      : 24
661
        /// Start     : 192.168.168.1
662
        /// End       : 192.168.168.254
663
        /// Broadcast : 192.168.168.255.
664
        /// </summary>
665
        /// <param name="tryParse">Whether to throw exception or not during conversion.</param>
666
        /// <param name="ipaddress">An ip address to convert.</param>
667
        /// <param name="netmask">A netmask to convert (255.255.255.0).</param>
668
        /// <param name="ipnetwork">The resulting IPNetwork.</param>
669
        private static void InternalParse(bool tryParse, IPAddress ipaddress, IPAddress netmask, out IPNetwork ipnetwork)
670
        {
6,000,880✔
671
            if (ipaddress == null)
6,000,880✔
672
            {
4✔
673
                if (tryParse == false)
4✔
674
                {
2✔
675
                    throw new ArgumentNullException("ipaddress");
2✔
676
                }
677

678
                ipnetwork = null;
2✔
679
                return;
2✔
680
            }
681

682
            if (netmask == null)
6,000,876✔
683
            {
4✔
684
                if (tryParse == false)
4✔
685
                {
2✔
686
                    throw new ArgumentNullException("netmask");
2✔
687
                }
688

689
                ipnetwork = null;
2✔
690
                return;
2✔
691
            }
692

693
            var uintIpAddress = IPNetwork.ToBigInteger(ipaddress);
6,000,872✔
694
            bool parsed = IPNetwork.TryToCidr(netmask, out byte? cidr2);
6,000,872✔
695
            if (parsed == false)
6,000,872✔
696
            {
3✔
697
                if (tryParse == false)
3✔
698
                {
1✔
699
                    throw new ArgumentException("netmask");
1✔
700
                }
701

702
                ipnetwork = null;
2✔
703
                return;
2✔
704
            }
705

706
            byte cidr = (byte)cidr2;
6,000,869✔
707

708
            var ipnet = new IPNetwork(uintIpAddress, ipaddress.AddressFamily, cidr);
6,000,869✔
709
            ipnetwork = ipnet;
6,000,869✔
710

711
            return;
6,000,869✔
712
        }
6,000,875✔
713

714
        /// <summary>
715
        /// 192.168.168.100/24
716
        ///
717
        /// Network   : 192.168.168.0
718
        /// Netmask   : 255.255.255.0
719
        /// Cidr      : 24
720
        /// Start     : 192.168.168.1
721
        /// End       : 192.168.168.254
722
        /// Broadcast : 192.168.168.255.
723
        /// </summary>
724
        /// <param name="tryParse">Whether to throw exception or not during conversion.</param>
725
        /// <param name="ipaddress">A string containing an ip address to convert.</param>
726
        /// <param name="cidr">A byte representing the CIDR to be used in conversion (/24).</param>
727
        /// <param name="ipnetwork">The resulting IPNetwork.</param>
728
        private static void InternalParse(bool tryParse, string ipaddress, byte cidr, out IPNetwork ipnetwork)
729
        {
6,000,859✔
730
            if (string.IsNullOrEmpty(ipaddress))
6,000,859✔
731
            {
6✔
732
                if (tryParse == false)
6✔
733
                {
2✔
734
                    throw new ArgumentNullException("ipaddress");
2✔
735
                }
736

737
                ipnetwork = null;
4✔
738
                return;
4✔
739
            }
740

741
            bool ipaddressParsed = IPAddress.TryParse(ipaddress, out IPAddress ip);
6,000,853✔
742
            if (ipaddressParsed == false)
6,000,853✔
743
            {
38✔
744
                if (tryParse == false)
38✔
745
                {
2✔
746
                    throw new ArgumentException("ipaddress");
2✔
747
                }
748

749
                ipnetwork = null;
36✔
750
                return;
36✔
751
            }
752

753
            bool parsedNetmask = IPNetwork.TryToNetmask(cidr, ip.AddressFamily, out IPAddress mask);
6,000,815✔
754
            if (parsedNetmask == false)
6,000,815✔
755
            {
4✔
756
                if (tryParse == false)
4✔
757
                {
2✔
758
                    throw new ArgumentException("cidr");
2✔
759
                }
760

761
                ipnetwork = null;
2✔
762
                return;
2✔
763
            }
764

765
            IPNetwork.InternalParse(tryParse, ip, mask, out ipnetwork);
6,000,811✔
766
        }
6,000,853✔
767
        #endregion
768

769
        #region converters
770

771
        #region ToUint
772

773
        /// <summary>
774
        /// Convert an ipadress to decimal
775
        /// 0.0.0.0 -> 0
776
        /// 0.0.1.0 -> 256.
777
        /// </summary>
778
        /// <param name="ipaddress">A string containing an ip address to convert.</param>
779
        /// <returns>A number representing the ipaddress.</returns>
780
        public static BigInteger ToBigInteger(IPAddress ipaddress)
781
        {
6,203,704✔
782
            IPNetwork.InternalToBigInteger(false, ipaddress, out BigInteger? uintIpAddress);
6,203,704✔
783

784
            return (BigInteger)uintIpAddress;
6,203,702✔
785
        }
6,203,702✔
786

787
        /// <summary>
788
        /// Convert an ipadress to decimal
789
        /// 0.0.0.0 -> 0
790
        /// 0.0.1.0 -> 256.
791
        /// </summary>
792
        /// <param name="ipaddress">A string containing an ip address to convert.</param>
793
        /// <param name="uintIpAddress">A number representing the IPAdress.</param>
794
        /// <returns>true if ipaddress was converted successfully; otherwise, false.</returns>
795
        public static bool TryToBigInteger(IPAddress ipaddress, out BigInteger? uintIpAddress)
796
        {
6,000,947✔
797
            IPNetwork.InternalToBigInteger(true, ipaddress, out BigInteger? uintIpAddress2);
6,000,947✔
798
            bool parsed = uintIpAddress2 != null;
6,000,947✔
799
            uintIpAddress = uintIpAddress2;
6,000,947✔
800

801
            return parsed;
6,000,947✔
802
        }
6,000,947✔
803

804
#if TRAVISCI
805
        public
806
#else
807
        internal
808
#endif
809
            static void InternalToBigInteger(bool tryParse, IPAddress ipaddress, out BigInteger? uintIpAddress)
810
        {
12,204,651✔
811
            if (ipaddress == null)
12,204,651✔
812
            {
4✔
813
                if (tryParse == false)
4✔
814
                {
2✔
815
                    throw new ArgumentNullException("ipaddress");
2✔
816
                }
817

818
                uintIpAddress = null;
2✔
819
                return;
2✔
820
            }
821

822
#if NET5_0 || NETSTANDARD2_1
823
            byte[] bytes = ipaddress.AddressFamily == AddressFamily.InterNetwork ? new byte[4] : new byte[16];
824
            Span<byte> span = bytes.AsSpan();
825
            if (!ipaddress.TryWriteBytes(span, out _))
826
            {
827
                if (tryParse == false)
828
                {
829
                    throw new ArgumentException("ipaddress");
830
                }
831

832
                uintIpAddress = null;
833
                return;
834
            }
835

836
            uintIpAddress = new BigInteger(span, isUnsigned: true, isBigEndian: true);
837
#elif NET45 || NET46 || NET47 || NETSTANDARD20
838
            byte[] bytes = ipaddress.GetAddressBytes();
839
            bytes.AsSpan().Reverse();
840

841
            // add trailing 0 to make unsigned
842
            byte[] unsigned = new byte[bytes.Length + 1];
843
            Buffer.BlockCopy(bytes, 0, unsigned, 0, bytes.Length);
844
            uintIpAddress = new BigInteger(unsigned);
845
#else
846
            byte[] bytes = ipaddress.GetAddressBytes();
12,204,647✔
847
            Array.Reverse(bytes);
12,204,647✔
848

849
            // add trailing 0 to make unsigned
850
            byte[] unsigned = new byte[bytes.Length + 1];
12,204,647✔
851
            Buffer.BlockCopy(bytes, 0, unsigned, 0, bytes.Length);
12,204,647✔
852
            uintIpAddress = new BigInteger(unsigned);
12,204,647✔
853
#endif
854
        }
12,204,649✔
855

856
        /// <summary>
857
        /// Convert a cidr to BigInteger netmask.
858
        /// </summary>
859
        /// <param name="cidr">A byte representing the netmask in cidr format (/24).</param>
860
        /// <param name="family">Either IPv4 or IPv6.</param>
861
        /// <returns>A number representing the netmask exprimed in CIDR.</returns>
862
        public static BigInteger ToUint(byte cidr, AddressFamily family)
863
        {
23,304,060✔
864
            IPNetwork.InternalToBigInteger(false, cidr, family, out BigInteger? uintNetmask);
23,304,060✔
865

866
            return (BigInteger)uintNetmask;
23,304,059✔
867
        }
23,304,059✔
868

869
        /// <summary>
870
        /// Convert a cidr to uint netmask.
871
        /// </summary>
872
        /// <param name="cidr">A byte representing the netmask in cidr format (/24).</param>
873
        /// <param name="family">Either IPv4 or IPv6.</param>
874
        /// <param name="uintNetmask">A number representing the netmask.</param>
875
        /// <returns>true if cidr was converted successfully; otherwise, false.</returns>
876
        public static bool TryToUint(byte cidr, AddressFamily family, out BigInteger? uintNetmask)
877
        {
1✔
878
            IPNetwork.InternalToBigInteger(true, cidr, family, out BigInteger? uintNetmask2);
1✔
879
            bool parsed = uintNetmask2 != null;
1✔
880
            uintNetmask = uintNetmask2;
1✔
881

882
            return parsed;
1✔
883
        }
1✔
884

885
        /// <summary>
886
        /// Convert a cidr to uint netmask.
887
        /// </summary>
888
        /// <param name="tryParse">Whether to throw exception or not during conversion.</param>
889
        /// <param name="cidr">A byte representing the netmask in cidr format (/24).</param>
890
        /// <param name="family">Either IPv4 or IPv6.</param>
891
        /// <param name="uintNetmask">A number representing the netmask.</param>
892
#if TRAVISCI
893
        public
894
#else
895
        internal
896
#endif
897
            static void InternalToBigInteger(bool tryParse, byte cidr, AddressFamily family, out BigInteger? uintNetmask)
898
        {
23,304,066✔
899
            if (family == AddressFamily.InterNetwork && cidr > 32)
23,304,066✔
900
            {
2✔
901
                if (tryParse == false)
2✔
902
                {
1✔
903
                    throw new ArgumentOutOfRangeException("cidr");
1✔
904
                }
905

906
                uintNetmask = null;
1✔
907
                return;
1✔
908
            }
909

910
            if (family == AddressFamily.InterNetworkV6 && cidr > 128)
23,304,064✔
911
            {
2✔
912
                if (tryParse == false)
2✔
913
                {
1✔
914
                    throw new ArgumentOutOfRangeException("cidr");
1✔
915
                }
916

917
                uintNetmask = null;
1✔
918
                return;
1✔
919
            }
920

921
            if (family != AddressFamily.InterNetwork
23,304,062✔
922
                && family != AddressFamily.InterNetworkV6)
23,304,062✔
923
            {
2✔
924
                if (tryParse == false)
2✔
925
                {
1✔
926
                    throw new NotSupportedException(family.ToString());
1✔
927
                }
928

929
                uintNetmask = null;
1✔
930
                return;
1✔
931
            }
932

933
            if (family == AddressFamily.InterNetwork)
23,304,060✔
934
            {
23,296,847✔
935
                uintNetmask = cidr == 0 ? 0 : 0xffffffff << (32 - cidr);
23,296,847✔
936
                return;
23,296,847✔
937
            }
938

939
            var mask = new BigInteger(new byte[]
7,213✔
940
            {
7,213✔
941
                0xff, 0xff, 0xff, 0xff,
7,213✔
942
                0xff, 0xff, 0xff, 0xff,
7,213✔
943
                0xff, 0xff, 0xff, 0xff,
7,213✔
944
                0xff, 0xff, 0xff, 0xff,
7,213✔
945
                0x00,
7,213✔
946
            });
7,213✔
947

948
            BigInteger masked = cidr == 0 ? 0 : mask << (128 - cidr);
7,213✔
949
            byte[] m = masked.ToByteArray();
7,213✔
950
            byte[] bmask = new byte[17];
7,213✔
951
            int copy = m.Length > 16 ? 16 : m.Length;
7,213✔
952
            Array.Copy(m, 0, bmask, 0, copy);
7,213✔
953
            uintNetmask = new BigInteger(bmask);
7,213✔
954
        }
23,304,063✔
955

956
        #endregion
957

958
        #region ToCidr
959

960
        /// <summary>
961
        /// Convert netmask to CIDR
962
        ///  255.255.255.0 -> 24
963
        ///  255.255.0.0   -> 16
964
        ///  255.0.0.0     -> 8.
965
        /// </summary>
966
        /// <param name="tryParse">Whether to throw exception or not during conversion.</param>
967
        /// <param name="netmask">A number representing the netmask to convert.</param>
968
        /// <param name="family">Either IPv4 or IPv6.</param>
969
        /// <param name="cidr">A byte representing the netmask in cidr format (/24).</param>
970
        private static void InternalToCidr(bool tryParse, BigInteger netmask, AddressFamily family, out byte? cidr)
971
        {
6,000,934✔
972
            if (!IPNetwork.InternalValidNetmask(netmask, family))
6,000,934✔
973
            {
6✔
974
                if (tryParse == false)
6✔
975
                {
2✔
976
                    throw new ArgumentException("netmask");
2✔
977
                }
978

979
                cidr = null;
4✔
980
                return;
4✔
981
            }
982

983
            byte cidr2 = IPNetwork.BitsSet(netmask, family);
6,000,928✔
984
            cidr = cidr2;
6,000,928✔
985

986
            return;
6,000,928✔
987
        }
6,000,932✔
988

989
        /// <summary>
990
        /// Convert netmask to CIDR
991
        ///  255.255.255.0 -> 24
992
        ///  255.255.0.0   -> 16
993
        ///  255.0.0.0     -> 8.
994
        /// </summary>
995
        /// <param name="netmask">An IPAdress representing the CIDR to convert.</param>
996
        /// <returns>A byte representing the CIDR converted from the netmask.</returns>
997
        public static byte ToCidr(IPAddress netmask)
998
        {
33✔
999
            IPNetwork.InternalToCidr(false, netmask, out byte? cidr);
33✔
1000
            return (byte)cidr;
30✔
1001
        }
30✔
1002

1003
        /// <summary>
1004
        /// Convert netmask to CIDR
1005
        ///  255.255.255.0 -> 24
1006
        ///  255.255.0.0   -> 16
1007
        ///  255.0.0.0     -> 8.
1008
        /// </summary>
1009
        /// <param name="netmask">An IPAdress representing the CIDR to convert.</param>
1010
        /// <param name="cidr">A byte representing the netmask in cidr format (/24).</param>
1011
        /// <returns>true if netmask was converted successfully; otherwise, false.</returns>
1012
        public static bool TryToCidr(IPAddress netmask, out byte? cidr)
1013
        {
6,000,903✔
1014
            IPNetwork.InternalToCidr(true, netmask, out byte? cidr2);
6,000,903✔
1015
            bool parsed = cidr2 != null;
6,000,903✔
1016
            cidr = cidr2;
6,000,903✔
1017
            return parsed;
6,000,903✔
1018
        }
6,000,903✔
1019

1020
        private static void InternalToCidr(bool tryParse, IPAddress netmask, out byte? cidr)
1021
        {
6,000,936✔
1022
            if (netmask == null)
6,000,936✔
1023
            {
2✔
1024
                if (tryParse == false)
2✔
1025
                {
1✔
1026
                    throw new ArgumentNullException("netmask");
1✔
1027
                }
1028

1029
                cidr = null;
1✔
1030
                return;
1✔
1031
            }
1032

1033
            bool parsed = IPNetwork.TryToBigInteger(netmask, out BigInteger? uintNetmask2);
6,000,934✔
1034

1035
            // 20180217 lduchosal
1036
            // impossible to reach code.
1037
            // if (parsed == false) {
1038
            //     if (tryParse == false) {
1039
            //         throw new ArgumentException("netmask");
1040
            //     }
1041
            //     cidr = null;
1042
            //     return;
1043
            // }
1044
            var uintNetmask = (BigInteger)uintNetmask2;
6,000,934✔
1045

1046
            IPNetwork.InternalToCidr(tryParse, uintNetmask, netmask.AddressFamily, out byte? cidr2);
6,000,934✔
1047
            cidr = cidr2;
6,000,932✔
1048

1049
            return;
6,000,932✔
1050
        }
6,000,933✔
1051

1052
        #endregion
1053

1054
        #region ToNetmask
1055

1056
        /// <summary>
1057
        /// Convert CIDR to netmask
1058
        ///  24 -> 255.255.255.0
1059
        ///  16 -> 255.255.0.0
1060
        ///  8 -> 255.0.0.0.
1061
        /// </summary>
1062
        /// <see href="http://snipplr.com/view/15557/cidr-class-for-ipv4/"/>
1063
        /// <param name="cidr">A byte representing the netmask in cidr format (/24).</param>
1064
        /// <param name="family">Either IPv4 or IPv6.</param>
1065
        /// <returns>An IPAdress representing cidr.</returns>
1066
        public static IPAddress ToNetmask(byte cidr, AddressFamily family)
1067
        {
15✔
1068
            IPNetwork.InternalToNetmask(false, cidr, family, out IPAddress netmask);
15✔
1069

1070
            return netmask;
11✔
1071
        }
11✔
1072

1073
        /// <summary>
1074
        /// Convert CIDR to netmask
1075
        ///  24 -> 255.255.255.0
1076
        ///  16 -> 255.255.0.0
1077
        ///  8 -> 255.0.0.0.
1078
        /// </summary>
1079
        /// <see href="http://snipplr.com/view/15557/cidr-class-for-ipv4/"/>
1080
        /// <param name="cidr">A byte representing the netmask in cidr format (/24).</param>
1081
        /// <param name="family">Either IPv4 or IPv6.</param>
1082
        /// <param name="netmask">The resulting netmask.</param>
1083
        /// <returns>true if cidr was converted successfully; otherwise, false.</returns>
1084
        public static bool TryToNetmask(byte cidr, AddressFamily family, out IPAddress netmask)
1085
        {
6,000,828✔
1086
            IPNetwork.InternalToNetmask(true, cidr, family, out IPAddress netmask2);
6,000,828✔
1087
            bool parsed = netmask2 != null;
6,000,828✔
1088
            netmask = netmask2;
6,000,828✔
1089

1090
            return parsed;
6,000,828✔
1091
        }
6,000,828✔
1092

1093
#if TRAVISCI
1094
        public
1095
#else
1096
        internal
1097
#endif
1098
            static void InternalToNetmask(bool tryParse, byte cidr, AddressFamily family, out IPAddress netmask)
1099
        {
6,000,844✔
1100
            if (family != AddressFamily.InterNetwork
6,000,844✔
1101
                && family != AddressFamily.InterNetworkV6)
6,000,844✔
1102
            {
2✔
1103
                if (tryParse == false)
2✔
1104
                {
1✔
1105
                    throw new ArgumentException("family");
1✔
1106
                }
1107

1108
                netmask = null;
1✔
1109
                return;
1✔
1110
            }
1111

1112
            // 20180217 lduchosal
1113
            // impossible to reach code, byte cannot be negative :
1114
            //
1115
            // if (cidr < 0) {
1116
            //     if (tryParse == false) {
1117
            //         throw new ArgumentOutOfRangeException("cidr");
1118
            //     }
1119
            //     netmask = null;
1120
            //     return;
1121
            // }
1122
            int maxCidr = family == Sockets.AddressFamily.InterNetwork ? 32 : 128;
6,000,842✔
1123
            if (cidr > maxCidr)
6,000,842✔
1124
            {
10✔
1125
                if (tryParse == false)
10✔
1126
                {
3✔
1127
                    throw new ArgumentOutOfRangeException("cidr");
3✔
1128
                }
1129

1130
                netmask = null;
7✔
1131
                return;
7✔
1132
            }
1133

1134
            BigInteger mask = IPNetwork.ToUint(cidr, family);
6,000,832✔
1135
            var netmask2 = IPNetwork.ToIPAddress(mask, family);
6,000,832✔
1136
            netmask = netmask2;
6,000,832✔
1137

1138
            return;
6,000,832✔
1139
        }
6,000,840✔
1140

1141
        #endregion
1142

1143
        #endregion
1144

1145
        #region utils
1146

1147
        #region BitsSet
1148

1149
        /// <summary>
1150
        /// Count bits set to 1 in netmask.
1151
        /// </summary>
1152
        /// <see href="http://stackoverflow.com/questions/109023/best-algorithm-to-count-the-number-of-set-bits-in-a-32-bit-integer"/>
1153
        /// <param name="netmask">A number representing the netmask to count bits from.</param>
1154
        /// <param name="family">Either IPv4 or IPv6.</param>
1155
        /// <returns>The number of bytes set to 1.</returns>
1156
        private static byte BitsSet(BigInteger netmask, AddressFamily family)
1157
        {
6,000,936✔
1158
            string s = netmask.ToBinaryString();
6,000,936✔
1159

1160
            return (byte)s.Replace("0", string.Empty)
6,000,936✔
1161
                .ToCharArray()
6,000,936✔
1162
                .Length;
6,000,936✔
1163
        }
6,000,936✔
1164

1165
        /// <summary>
1166
        /// Count bits set to 1 in netmask.
1167
        /// </summary>
1168
        /// <param name="netmask">A number representing the netmask to count bits from.</param>
1169
        /// <returns>The number of bytes set to 1.</returns>
1170
        public static uint BitsSet(IPAddress netmask)
1171
        {
8✔
1172
            var uintNetmask = IPNetwork.ToBigInteger(netmask);
8✔
1173
            uint bits = IPNetwork.BitsSet(uintNetmask, netmask.AddressFamily);
8✔
1174

1175
            return bits;
8✔
1176
        }
8✔
1177

1178
        #endregion
1179

1180
        #region ValidNetmask
1181

1182
        /// <summary>
1183
        /// return true if netmask is a valid netmask
1184
        /// 255.255.255.0, 255.0.0.0, 255.255.240.0, ...
1185
        /// </summary>
1186
        /// <see href="http://www.actionsnip.com/snippets/tomo_atlacatl/calculate-if-a-netmask-is-valid--as2-"/>
1187
        /// <param name="netmask">A number representing the netmask to validate.</param>
1188
        /// <returns>true if netmask is a valid IP Netmask; otherwise, false.</returns>
1189
        public static bool ValidNetmask(IPAddress netmask)
1190
        {
11✔
1191
            if (netmask == null)
11✔
1192
            {
1✔
1193
                throw new ArgumentNullException("netmask");
1✔
1194
            }
1195

1196
            var uintNetmask = IPNetwork.ToBigInteger(netmask);
10✔
1197
            bool valid = IPNetwork.InternalValidNetmask(uintNetmask, netmask.AddressFamily);
10✔
1198

1199
            return valid;
10✔
1200
        }
10✔
1201

1202
#if TRAVISCI
1203
        public
1204
#else
1205
        internal
1206
#endif
1207
            static bool InternalValidNetmask(BigInteger netmask, AddressFamily family)
1208
        {
6,000,945✔
1209
            if (family != AddressFamily.InterNetwork
6,000,945✔
1210
                && family != AddressFamily.InterNetworkV6)
6,000,945✔
1211
            {
1✔
1212
                throw new ArgumentException("family");
1✔
1213
            }
1214

1215
            BigInteger mask = family == AddressFamily.InterNetwork
6,000,944✔
1216
                ? new BigInteger(0x0ffffffff)
6,000,944✔
1217
                : new BigInteger(new byte[]
6,000,944✔
1218
                {
6,000,944✔
1219
                    0xff, 0xff, 0xff, 0xff,
6,000,944✔
1220
                    0xff, 0xff, 0xff, 0xff,
6,000,944✔
1221
                    0xff, 0xff, 0xff, 0xff,
6,000,944✔
1222
                    0xff, 0xff, 0xff, 0xff,
6,000,944✔
1223
                    0x00,
6,000,944✔
1224
                });
6,000,944✔
1225

1226
            BigInteger neg = (~netmask) & mask;
6,000,944✔
1227
            bool isNetmask = ((neg + 1) & neg) == 0;
6,000,944✔
1228

1229
            return isNetmask;
6,000,944✔
1230
        }
6,000,944✔
1231

1232
        #endregion
1233

1234
        #region ToIPAddress
1235

1236
        /// <summary>
1237
        /// Transform a uint ipaddress into IPAddress object.
1238
        /// </summary>
1239
        /// <param name="ipaddress">A number representing an ip address to convert.</param>
1240
        /// <param name="family">Either IPv4 or IPv6.</param>
1241
        /// <returns>An ip adress.</returns>
1242
        public static IPAddress ToIPAddress(BigInteger ipaddress, AddressFamily family)
1243
        {
12,209,609✔
1244
            int width = family == AddressFamily.InterNetwork ? 4 : 16;
12,209,609✔
1245
            byte[] bytes = ipaddress.ToByteArray();
12,209,609✔
1246
            byte[] bytes2 = new byte[width];
12,209,609✔
1247
            int copy = bytes.Length > width ? width : bytes.Length;
12,209,609✔
1248
            Array.Copy(bytes, 0, bytes2, 0, copy);
12,209,609✔
1249
            Array.Reverse(bytes2);
12,209,609✔
1250

1251
            byte[] sized = Resize(bytes2, family);
12,209,609✔
1252
            var ip = new IPAddress(sized);
12,209,607✔
1253
            return ip;
12,209,607✔
1254
        }
12,209,607✔
1255

1256
#if TRAVISCI
1257
        public
1258
#else
1259
        internal
1260
#endif
1261
            static byte[] Resize(byte[] bytes, AddressFamily family)
1262
        {
12,209,610✔
1263
            if (family != AddressFamily.InterNetwork
12,209,610✔
1264
                && family != AddressFamily.InterNetworkV6)
12,209,610✔
1265
            {
2✔
1266
                throw new ArgumentException("family");
2✔
1267
            }
1268

1269
            int width = family == AddressFamily.InterNetwork ? 4 : 16;
12,209,608✔
1270

1271
            if (bytes.Length > width)
12,209,608✔
1272
            {
1✔
1273
                throw new ArgumentException("bytes");
1✔
1274
            }
1275

1276
            byte[] result = new byte[width];
12,209,607✔
1277
            Array.Copy(bytes, 0, result, 0, bytes.Length);
12,209,607✔
1278

1279
            return result;
12,209,607✔
1280
        }
12,209,607✔
1281

1282
        #endregion
1283

1284
        #endregion
1285

1286
        #region contains
1287

1288
        /// <summary>
1289
        /// return true if ipaddress is contained in network.
1290
        /// </summary>
1291
        /// <param name="contains">A string containing an ip address to convert.</param>
1292
        /// <returns>true if ipaddress is contained into the IP Network; otherwise, false.</returns>
1293
        public bool Contains(IPAddress contains)
1294
        {
282✔
1295
            if (contains == null)
282✔
1296
            {
2✔
1297
                throw new ArgumentNullException("ipaddress");
2✔
1298
            }
1299

1300
            if (this.AddressFamily != contains.AddressFamily)
280✔
1301
            {
1✔
1302
                return false;
1✔
1303
            }
1304

1305
            BigInteger uintNetwork = this._network;
279✔
1306
            BigInteger uintBroadcast = this._broadcast; // CreateBroadcast(ref uintNetwork, this._netmask, this._family);
279✔
1307
            var uintAddress = IPNetwork.ToBigInteger(contains);
279✔
1308

1309
            bool result = uintAddress >= uintNetwork
279✔
1310
                && uintAddress <= uintBroadcast;
279✔
1311

1312
            return result;
279✔
1313
        }
280✔
1314

1315
        [Obsolete("static Contains is deprecated, please use instance Contains.")]
1316
        public static bool Contains(IPNetwork network, IPAddress ipaddress)
1317
        {
2✔
1318
            if (network == null)
2✔
1319
            {
1✔
1320
                throw new ArgumentNullException("network");
1✔
1321
            }
1322

1323
            return network.Contains(ipaddress);
1✔
1324
        }
1✔
1325

1326
        /// <summary>
1327
        /// return true is network2 is fully contained in network.
1328
        /// </summary>
1329
        /// <param name="contains">The network to test.</param>
1330
        /// <returns>It returns the boolean value. If network2 is in IPNetwork then it returns True, otherwise returns False.</returns>
1331
        public bool Contains(IPNetwork contains)
1332
        {
264,304✔
1333
            if (contains == null)
264,304✔
1334
            {
1✔
1335
                throw new ArgumentNullException("contains");
1✔
1336
            }
1337

1338
            BigInteger uintNetwork = this._network;
264,303✔
1339
            BigInteger uintBroadcast = this._broadcast; // CreateBroadcast(ref uintNetwork, this._netmask, this._family);
264,303✔
1340

1341
            BigInteger uintFirst = contains._network;
264,303✔
1342
            BigInteger uintLast = contains._broadcast; // CreateBroadcast(ref uintFirst, network2._netmask, network2._family);
264,303✔
1343

1344
            bool result = uintFirst >= uintNetwork
264,303✔
1345
                && uintLast <= uintBroadcast;
264,303✔
1346

1347
            return result;
264,303✔
1348
        }
264,303✔
1349

1350
        [Obsolete("static Contains is deprecated, please use instance Contains.")]
1351
        public static bool Contains(IPNetwork network, IPNetwork network2)
1352
        {
2✔
1353
            if (network == null)
2✔
1354
            {
1✔
1355
                throw new ArgumentNullException("network");
1✔
1356
            }
1357

1358
            return network.Contains(network2);
1✔
1359
        }
1✔
1360

1361
        private static BigInteger CreateBroadcast(ref BigInteger network, BigInteger netmask, AddressFamily family)
1362
        {
133,911✔
1363
            int width = family == AddressFamily.InterNetwork ? 4 : 16;
133,911✔
1364
            BigInteger uintBroadcast = network + netmask.PositiveReverse(width);
133,911✔
1365

1366
            return uintBroadcast;
133,911✔
1367
        }
133,911✔
1368

1369
        #endregion
1370

1371
        #region overlap
1372

1373
        /// <summary>
1374
        /// return true is network2 overlap network.
1375
        /// </summary>
1376
        /// <param name="network2">The network to test.</param>
1377
        /// <returns>true if network2 overlaps into the IP Network; otherwise, false.</returns>
1378
        public bool Overlap(IPNetwork network2)
1379
        {
16✔
1380
            if (network2 == null)
16✔
1381
            {
2✔
1382
                throw new ArgumentNullException("network2");
2✔
1383
            }
1384

1385
            BigInteger uintNetwork = this._network;
14✔
1386
            BigInteger uintBroadcast = this._broadcast;
14✔
1387

1388
            BigInteger uintFirst = network2._network;
14✔
1389
            BigInteger uintLast = network2._broadcast;
14✔
1390

1391
            bool overlap =
14✔
1392
                (uintFirst >= uintNetwork && uintFirst <= uintBroadcast)
14✔
1393
                || (uintLast >= uintNetwork && uintLast <= uintBroadcast)
14✔
1394
                || (uintFirst <= uintNetwork && uintLast >= uintBroadcast)
14✔
1395
                || (uintFirst >= uintNetwork && uintLast <= uintBroadcast);
14✔
1396

1397
            return overlap;
14✔
1398
        }
14✔
1399

1400
        [Obsolete("static Overlap is deprecated, please use instance Overlap.")]
1401
        public static bool Overlap(IPNetwork network, IPNetwork network2)
1402
        {
2✔
1403
            if (network == null)
2✔
1404
            {
1✔
1405
                throw new ArgumentNullException("network");
1✔
1406
            }
1407

1408
            return network.Overlap(network2);
1✔
1409
        }
1✔
1410

1411
        #endregion
1412

1413
        #region ToString
1414

1415
        public override string ToString()
1416
        {
6,002,532✔
1417
            return string.Format("{0}/{1}", this.Network, this.Cidr);
6,002,532✔
1418
        }
6,002,532✔
1419

1420
        #endregion
1421

1422
        #region IANA block
1423

1424
        private static readonly Lazy<IPNetwork> _iana_ablock_reserved = new Lazy<IPNetwork>(() => IPNetwork.Parse("10.0.0.0/8"));
2✔
1425
        private static readonly Lazy<IPNetwork> _iana_bblock_reserved = new Lazy<IPNetwork>(() => IPNetwork.Parse("172.16.0.0/12"));
2✔
1426
        private static readonly Lazy<IPNetwork> _iana_cblock_reserved = new Lazy<IPNetwork>(() => IPNetwork.Parse("192.168.0.0/16"));
2✔
1427

1428
        /// <summary>
1429
        /// Gets 10.0.0.0/8.
1430
        /// </summary>
1431
        /// <returns>The IANA reserved IPNetwork 10.0.0.0/8.<returns>
1432
        public static IPNetwork IANA_ABLK_RESERVED1
1433
        {
1434
            get
1435
            {
28✔
1436
                return _iana_ablock_reserved.Value;
28✔
1437
            }
28✔
1438
        }
1439

1440
        /// <summary>
1441
        /// Gets 172.12.0.0/12.
1442
        /// </summary>
1443
        /// <returns>The IANA reserved IPNetwork 172.12.0.0/12.</returns>
1444
        public static IPNetwork IANA_BBLK_RESERVED1
1445
        {
1446
            get
1447
            {
8✔
1448
                return _iana_bblock_reserved.Value;
8✔
1449
            }
8✔
1450
        }
1451

1452
        /// <summary>
1453
        /// Gets 192.168.0.0/16.
1454
        /// </summary>
1455
        /// <returns>The IANA reserved IPNetwork 192.168.0.0/16.<returns>
1456
        public static IPNetwork IANA_CBLK_RESERVED1
1457
        {
1458
            get
1459
            {
14✔
1460
                return _iana_cblock_reserved.Value;
14✔
1461
            }
14✔
1462
        }
1463

1464
        /// <summary>
1465
        /// return true if ipaddress is contained in
1466
        /// IANA_ABLK_RESERVED1, IANA_BBLK_RESERVED1, IANA_CBLK_RESERVED1.
1467
        /// </summary>
1468
        /// <param name="ipaddress">A string containing an ip address to convert.</param>
1469
        /// <returns>true if ipaddress is a IANA reserverd IP Netowkr ; otherwise, false.</returns>
1470
        public static bool IsIANAReserved(IPAddress ipaddress)
1471
        {
5✔
1472
            if (ipaddress == null)
5✔
1473
            {
1✔
1474
                throw new ArgumentNullException("ipaddress");
1✔
1475
            }
1476

1477
            return IPNetwork.IANA_ABLK_RESERVED1.Contains(ipaddress)
4✔
1478
                || IPNetwork.IANA_BBLK_RESERVED1.Contains(ipaddress)
4✔
1479
                || IPNetwork.IANA_CBLK_RESERVED1.Contains(ipaddress);
4✔
1480
        }
4✔
1481

1482
        /// <summary>
1483
        /// return true if ipnetwork is contained in
1484
        /// IANA_ABLK_RESERVED1, IANA_BBLK_RESERVED1, IANA_CBLK_RESERVED1.
1485
        /// </summary>
1486
        /// <returns>true if the ipnetwork is a IANA reserverd IP Netowkr ; otherwise, false.</returns>
1487
        public bool IsIANAReserved()
1488
        {
6✔
1489
            return IPNetwork.IANA_ABLK_RESERVED1.Contains(this)
6✔
1490
                || IPNetwork.IANA_BBLK_RESERVED1.Contains(this)
6✔
1491
                || IPNetwork.IANA_CBLK_RESERVED1.Contains(this);
6✔
1492
        }
6✔
1493

1494
        [Obsolete("static IsIANAReserved is deprecated, please use instance IsIANAReserved.")]
1495
        public static bool IsIANAReserved(IPNetwork ipnetwork)
1496
        {
2✔
1497
            if (ipnetwork == null)
2✔
1498
            {
1✔
1499
                throw new ArgumentNullException("ipnetwork");
1✔
1500
            }
1501

1502
            return ipnetwork.IsIANAReserved();
1✔
1503
        }
1✔
1504

1505
        #endregion
1506

1507
        #region Subnet
1508

1509
        /// <summary>
1510
        /// Subnet a network into multiple nets of cidr mask
1511
        /// Subnet 192.168.0.0/24 into cidr 25 gives 192.168.0.0/25, 192.168.0.128/25
1512
        /// Subnet 10.0.0.0/8 into cidr 9 gives 10.0.0.0/9, 10.128.0.0/9.
1513
        /// </summary>
1514
        /// <param name="cidr">A byte representing the CIDR to be used to subnet the current IPNetwork.</param>
1515
        /// <returns>A IPNetworkCollection splitted by CIDR.</returns>
1516
        public IPNetworkCollection Subnet(byte cidr)
1517
        {
159✔
1518
            IPNetwork.InternalSubnet(false, this, cidr, out IPNetworkCollection ipnetworkCollection);
159✔
1519

1520
            return ipnetworkCollection;
155✔
1521
        }
155✔
1522

1523
        [Obsolete("static Subnet is deprecated, please use instance Subnet.")]
1524
        public static IPNetworkCollection Subnet(IPNetwork network, byte cidr)
1525
        {
2✔
1526
            if (network == null)
2✔
1527
            {
1✔
1528
                throw new ArgumentNullException("network");
1✔
1529
            }
1530

1531
            return network.Subnet(cidr);
1✔
1532
        }
1✔
1533

1534
        /// <summary>
1535
        /// Subnet a network into multiple nets of cidr mask
1536
        /// Subnet 192.168.0.0/24 into cidr 25 gives 192.168.0.0/25, 192.168.0.128/25
1537
        /// Subnet 10.0.0.0/8 into cidr 9 gives 10.0.0.0/9, 10.128.0.0/9.
1538
        /// </summary>
1539
        /// <param name="cidr">A byte representing the CIDR to be used to subnet the current IPNetwork.</param>
1540
        /// <param name="ipnetworkCollection">The resulting subnetted IPNetwork.</param>
1541
        /// <returns>true if network was split successfully; otherwise, false.</returns>
1542
        public bool TrySubnet(byte cidr, out IPNetworkCollection ipnetworkCollection)
1543
        {
10✔
1544
            IPNetwork.InternalSubnet(true, this, cidr, out IPNetworkCollection inc);
10✔
1545
            if (inc == null)
10✔
1546
            {
4✔
1547
                ipnetworkCollection = null;
4✔
1548
                return false;
4✔
1549
            }
1550

1551
            ipnetworkCollection = inc;
6✔
1552
            return true;
6✔
1553
        }
10✔
1554

1555
        [Obsolete("static TrySubnet is deprecated, please use instance TrySubnet.")]
1556
        public static bool TrySubnet(IPNetwork network, byte cidr, out IPNetworkCollection ipnetworkCollection)
1557
        {
2✔
1558
            if (network == null)
2✔
1559
            {
1✔
1560
                throw new ArgumentNullException("network");
1✔
1561
            }
1562

1563
            return network.TrySubnet(cidr, out ipnetworkCollection);
1✔
1564
        }
1✔
1565

1566
#if TRAVISCI
1567
        public
1568
#else
1569
        internal
1570
#endif
1571
            static void InternalSubnet(bool trySubnet, IPNetwork network, byte cidr, out IPNetworkCollection ipnetworkCollection)
1572
        {
171✔
1573
            if (network == null)
171✔
1574
            {
2✔
1575
                if (trySubnet == false)
2✔
1576
                {
1✔
1577
                    throw new ArgumentNullException("network");
1✔
1578
                }
1579

1580
                ipnetworkCollection = null;
1✔
1581
                return;
1✔
1582
            }
1583

1584
            int maxCidr = network._family == Sockets.AddressFamily.InterNetwork ? 32 : 128;
169✔
1585
            if (cidr > maxCidr)
169✔
1586
            {
4✔
1587
                if (trySubnet == false)
4✔
1588
                {
2✔
1589
                    throw new ArgumentOutOfRangeException("cidr");
2✔
1590
                }
1591

1592
                ipnetworkCollection = null;
2✔
1593
                return;
2✔
1594
            }
1595

1596
            if (cidr < network.Cidr)
165✔
1597
            {
4✔
1598
                if (trySubnet == false)
4✔
1599
                {
2✔
1600
                    throw new ArgumentException("cidr");
2✔
1601
                }
1602

1603
                ipnetworkCollection = null;
2✔
1604
                return;
2✔
1605
            }
1606

1607
            ipnetworkCollection = new IPNetworkCollection(network, cidr);
161✔
1608
            return;
161✔
1609
        }
166✔
1610

1611
        #endregion
1612

1613
        #region Supernet
1614

1615
        /// <summary>
1616
        /// Supernet two consecutive cidr equal subnet into a single one
1617
        /// 192.168.0.0/24 + 192.168.1.0/24 = 192.168.0.0/23
1618
        /// 10.1.0.0/16 + 10.0.0.0/16 = 10.0.0.0/15
1619
        /// 192.168.0.0/24 + 192.168.0.0/25 = 192.168.0.0/24.
1620
        /// </summary>
1621
        /// <param name="network2">The network to supernet with.</param>
1622
        /// <returns>A supernetted IP Network.</returns>
1623
        public IPNetwork Supernet(IPNetwork network2)
1624
        {
10✔
1625
            IPNetwork.InternalSupernet(false, this, network2, out IPNetwork supernet);
10✔
1626
            return supernet;
5✔
1627
        }
5✔
1628

1629
        [Obsolete("static Supernet is deprecated, please use instance Supernet.")]
1630
        public static IPNetwork Supernet(IPNetwork network, IPNetwork network2)
1631
        {
1✔
1632
            return network.Supernet(network2);
1✔
1633
        }
1✔
1634

1635
        /// <summary>
1636
        /// Try to supernet two consecutive cidr equal subnet into a single one
1637
        /// 192.168.0.0/24 + 192.168.1.0/24 = 192.168.0.0/23
1638
        /// 10.1.0.0/16 + 10.0.0.0/16 = 10.0.0.0/15
1639
        /// 192.168.0.0/24 + 192.168.0.0/25 = 192.168.0.0/24.
1640
        /// </summary>
1641
        /// <param name="network2">The network to supernet with.</param>
1642
        /// <param name="supernet">The resulting IPNetwork.</param>
1643
        /// <returns>true if network2 was supernetted successfully; otherwise, false.</returns>
1644
        public bool TrySupernet(IPNetwork network2, out IPNetwork supernet)
1645
        {
132,131✔
1646
            IPNetwork.InternalSupernet(true, this, network2, out IPNetwork outSupernet);
132,131✔
1647
            bool parsed = outSupernet != null;
132,131✔
1648
            supernet = outSupernet;
132,131✔
1649
            return parsed;
132,131✔
1650
        }
132,131✔
1651

1652
        [Obsolete("static TrySupernet is deprecated, please use instance TrySupernet.")]
1653
        public static bool TrySupernet(IPNetwork network, IPNetwork network2, out IPNetwork supernet)
1654
        {
3✔
1655
            if (network == null)
3✔
1656
            {
2✔
1657
                throw new ArgumentNullException("network");
2✔
1658
            }
1659

1660
            return network.TrySupernet(network2, out supernet);
1✔
1661
        }
1✔
1662

1663
#if TRAVISCI
1664
        public
1665
#else
1666
        internal
1667
#endif
1668
            static void InternalSupernet(bool trySupernet, IPNetwork network1, IPNetwork network2, out IPNetwork supernet)
1669
        {
132,143✔
1670
            if (network1 == null)
132,143✔
1671
            {
2✔
1672
                if (trySupernet == false)
2✔
1673
                {
1✔
1674
                    throw new ArgumentNullException("network1");
1✔
1675
                }
1676

1677
                supernet = null;
1✔
1678
                return;
1✔
1679
            }
1680

1681
            if (network2 == null)
132,141✔
1682
            {
3✔
1683
                if (trySupernet == false)
3✔
1684
                {
1✔
1685
                    throw new ArgumentNullException("network2");
1✔
1686
                }
1687

1688
                supernet = null;
2✔
1689
                return;
2✔
1690
            }
1691

1692
            if (network1.Contains(network2))
132,138✔
1693
            {
9✔
1694
                supernet = new IPNetwork(network1._network, network1._family, network1.Cidr);
9✔
1695
                return;
9✔
1696
            }
1697

1698
            if (network2.Contains(network1))
132,129✔
1699
            {
3✔
1700
                supernet = new IPNetwork(network2._network, network2._family, network2.Cidr);
3✔
1701
                return;
3✔
1702
            }
1703

1704
            if (network1._cidr != network2._cidr)
132,126✔
1705
            {
66,039✔
1706
                if (trySupernet == false)
66,039✔
1707
                {
1✔
1708
                    throw new ArgumentException("cidr");
1✔
1709
                }
1710

1711
                supernet = null;
66,038✔
1712
                return;
66,038✔
1713
            }
1714

1715
            IPNetwork first = (network1._network < network2._network) ? network1 : network2;
66,087✔
1716
            IPNetwork last = (network1._network > network2._network) ? network1 : network2;
66,087✔
1717

1718
            // Starting from here :
1719
            // network1 and network2 have the same cidr,
1720
            // network1 does not contain network2,
1721
            // network2 does not contain network1,
1722
            // first is the lower subnet
1723
            // last is the higher subnet
1724
            if ((first._broadcast + 1) != last._network)
66,087✔
1725
            {
10✔
1726
                if (trySupernet == false)
10✔
1727
                {
2✔
1728
                    throw new ArgumentOutOfRangeException("network");
2✔
1729
                }
1730

1731
                supernet = null;
8✔
1732
                return;
8✔
1733
            }
1734

1735
            BigInteger uintSupernet = first._network;
66,077✔
1736
            byte cidrSupernet = (byte)(first._cidr - 1);
66,077✔
1737

1738
            var networkSupernet = new IPNetwork(uintSupernet, first._family, cidrSupernet);
66,077✔
1739
            if (networkSupernet._network != first._network)
66,077✔
1740
            {
7✔
1741
                if (trySupernet == false)
7✔
1742
                {
1✔
1743
                    throw new ArgumentException("network");
1✔
1744
                }
1745

1746
                supernet = null;
6✔
1747
                return;
6✔
1748
            }
1749

1750
            supernet = networkSupernet;
66,070✔
1751
            return;
66,070✔
1752
        }
132,137✔
1753

1754
        #endregion
1755

1756
        #region GetHashCode
1757

1758
        public override int GetHashCode()
1759
        {
6,000,033✔
1760
            return this._hashCode;
6,000,033✔
1761
        }
6,000,033✔
1762

1763
        /// <summary>
1764
        /// 20221105 : ldvhcosal
1765
        /// GetHashCode uses mutable attributes. That introduce undefined behaviour on Hashtable and dictionary.
1766
        /// </summary>
1767
        /// <returns>An number representing the hashCode.</returns>
1768
        private int ComputeHashCode()
1769
        {
8,135,871✔
1770
            return string.Format(
8,135,871✔
1771
                "{0}|{1}|{2}",
8,135,871✔
1772
                this._family.GetHashCode(),
8,135,871✔
1773
                this._network.GetHashCode(),
8,135,871✔
1774
                this._cidr.GetHashCode()).GetHashCode();
8,135,871✔
1775
        }
8,135,871✔
1776

1777
        #endregion
1778

1779
        #region SupernetArray
1780

1781
        /// <summary>
1782
        /// Supernet a list of subnet
1783
        /// 192.168.0.0/24 + 192.168.1.0/24 = 192.168.0.0/23
1784
        /// 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.
1785
        /// </summary>
1786
        /// <param name="ipnetworks">A list of IPNetwork to merge into common supernets.</param>
1787
        /// <returns>The result of IPNetwork if merges succeed, the first ipnetwork otherwise.</returns>
1788
        public static IPNetwork[] Supernet(IPNetwork[] ipnetworks)
1789
        {
15✔
1790
            InternalSupernet(false, ipnetworks, out IPNetwork[] supernet);
15✔
1791
            return supernet;
14✔
1792
        }
14✔
1793

1794
        /// <summary>
1795
        /// Supernet a list of subnet
1796
        /// 192.168.0.0/24 + 192.168.1.0/24 = 192.168.0.0/23
1797
        /// 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.
1798
        /// </summary>
1799
        /// <param name="ipnetworks">A list of IPNetwork to merge into common supernets.</param>
1800
        /// <param name="supernet">The result of IPNetwork merges.</param>
1801
        /// <returns>true if ipnetworks was supernetted successfully; otherwise, false.</returns>
1802
        public static bool TrySupernet(IPNetwork[] ipnetworks, out IPNetwork[] supernet)
1803
        {
7✔
1804
            bool supernetted = InternalSupernet(true, ipnetworks, out supernet);
7✔
1805
            return supernetted;
7✔
1806
        }
7✔
1807

1808
#if TRAVISCI
1809
        public
1810
#else
1811
        internal
1812
#endif
1813
        static bool InternalSupernet(bool trySupernet, IPNetwork[] ipnetworks, out IPNetwork[] supernet)
1814
        {
22✔
1815
            if (ipnetworks == null)
22✔
1816
            {
3✔
1817
                if (trySupernet == false)
3✔
1818
                {
1✔
1819
                    throw new ArgumentNullException("ipnetworks");
1✔
1820
                }
1821

1822
                supernet = null;
2✔
1823
                return false;
2✔
1824
            }
1825

1826
            if (ipnetworks.Length <= 0)
19✔
1827
            {
1✔
1828
                supernet = new IPNetwork[0];
1✔
1829
                return true;
1✔
1830
            }
1831

1832
            var supernetted = new List<IPNetwork>();
18✔
1833
            List<IPNetwork> ipns = IPNetwork.Array2List(ipnetworks);
18✔
1834
            Stack<IPNetwork> current = IPNetwork.List2Stack(ipns);
18✔
1835
            int previousCount = 0;
18✔
1836
            int currentCount = current.Count;
18✔
1837

1838
            while (previousCount != currentCount)
83✔
1839
            {
65✔
1840
                supernetted.Clear();
65✔
1841
                while (current.Count > 1)
132,181✔
1842
                {
132,116✔
1843
                    IPNetwork ipn1 = current.Pop();
132,116✔
1844
                    IPNetwork ipn2 = current.Peek();
132,116✔
1845

1846
                    bool success = ipn1.TrySupernet(ipn2, out IPNetwork outNetwork);
132,116✔
1847
                    if (success)
132,116✔
1848
                    {
66,072✔
1849
                        current.Pop();
66,072✔
1850
                        current.Push(outNetwork);
66,072✔
1851
                    }
66,072✔
1852
                    else
1853
                    {
66,044✔
1854
                        supernetted.Add(ipn1);
66,044✔
1855
                    }
66,044✔
1856
                }
132,116✔
1857

1858
                if (current.Count == 1)
65✔
1859
                {
65✔
1860
                    supernetted.Add(current.Pop());
65✔
1861
                }
65✔
1862

1863
                previousCount = currentCount;
65✔
1864
                currentCount = supernetted.Count;
65✔
1865
                current = IPNetwork.List2Stack(supernetted);
65✔
1866
            }
65✔
1867

1868
            supernet = supernetted.ToArray();
18✔
1869
            return true;
18✔
1870
        }
21✔
1871

1872
        private static Stack<IPNetwork> List2Stack(List<IPNetwork> list)
1873
        {
83✔
1874
            var stack = new Stack<IPNetwork>();
83✔
1875
            list.ForEach(new Action<IPNetwork>(
83✔
1876
                delegate(IPNetwork ipn)
83✔
1877
                {
132,209✔
1878
                    stack.Push(ipn);
132,209✔
1879
                }));
132,292✔
1880
            return stack;
83✔
1881
        }
83✔
1882

1883
        private static List<IPNetwork> Array2List(IPNetwork[] array)
1884
        {
18✔
1885
            var ipns = new List<IPNetwork>();
18✔
1886
            ipns.AddRange(array);
18✔
1887
            IPNetwork.RemoveNull(ipns);
18✔
1888
            ipns.Sort(new Comparison<IPNetwork>(
18✔
1889
                delegate(IPNetwork ipn1, IPNetwork ipn2)
18✔
1890
                {
850,489✔
1891
                    int networkCompare = ipn1._network.CompareTo(ipn2._network);
850,489✔
1892
                    if (networkCompare == 0)
850,489✔
1893
                    {
1✔
1894
                        int cidrCompare = ipn1._cidr.CompareTo(ipn2._cidr);
1✔
1895
                        return cidrCompare;
1✔
1896
                    }
18✔
1897

18✔
1898
                    return networkCompare;
850,488✔
1899
                }));
850,507✔
1900
            ipns.Reverse();
18✔
1901

1902
            return ipns;
18✔
1903
        }
18✔
1904

1905
        private static void RemoveNull(List<IPNetwork> ipns)
1906
        {
18✔
1907
            ipns.RemoveAll(new Predicate<IPNetwork>(
18✔
1908
                delegate(IPNetwork ipn)
18✔
1909
                {
66,104✔
1910
                    if (ipn == null)
66,104✔
1911
                    {
4✔
1912
                        return true;
4✔
1913
                    }
18✔
1914

18✔
1915
                    return false;
66,100✔
1916
                }));
66,122✔
1917
        }
18✔
1918

1919
        #endregion
1920

1921
        #region WideSubnet
1922

1923
        public static IPNetwork WideSubnet(string start, string end)
1924
        {
12✔
1925
            if (string.IsNullOrEmpty(start))
12✔
1926
            {
1✔
1927
                throw new ArgumentNullException("start");
1✔
1928
            }
1929

1930
            if (string.IsNullOrEmpty(end))
11✔
1931
            {
1✔
1932
                throw new ArgumentNullException("end");
1✔
1933
            }
1934

1935
            if (!IPAddress.TryParse(start, out IPAddress startIP))
10✔
1936
            {
1✔
1937
                throw new ArgumentException("start");
1✔
1938
            }
1939

1940
            if (!IPAddress.TryParse(end, out IPAddress endIP))
9✔
1941
            {
1✔
1942
                throw new ArgumentException("end");
1✔
1943
            }
1944

1945
            if (startIP.AddressFamily != endIP.AddressFamily)
8✔
1946
            {
1✔
1947
                throw new NotSupportedException("MixedAddressFamily");
1✔
1948
            }
1949

1950
            var ipnetwork = new IPNetwork(0, startIP.AddressFamily, 0);
7✔
1951
            for (byte cidr = 32; cidr >= 0; cidr--)
226✔
1952
            {
113✔
1953
                var wideSubnet = IPNetwork.Parse(start, cidr);
113✔
1954
                if (wideSubnet.Contains(endIP))
113✔
1955
                {
7✔
1956
                    ipnetwork = wideSubnet;
7✔
1957
                    break;
7✔
1958
                }
1959
            }
106✔
1960

1961
            return ipnetwork;
7✔
1962
        }
7✔
1963

1964
        public static bool TryWideSubnet(IPNetwork[] ipnetworks, out IPNetwork ipnetwork)
1965
        {
6✔
1966
            IPNetwork.InternalWideSubnet(true, ipnetworks, out IPNetwork ipn);
6✔
1967
            if (ipn == null)
6✔
1968
            {
2✔
1969
                ipnetwork = null;
2✔
1970
                return false;
2✔
1971
            }
1972

1973
            ipnetwork = ipn;
4✔
1974

1975
            return true;
4✔
1976
        }
6✔
1977

1978
        public static IPNetwork WideSubnet(IPNetwork[] ipnetworks)
1979
        {
6✔
1980
            IPNetwork.InternalWideSubnet(false, ipnetworks, out IPNetwork ipn);
6✔
1981
            return ipn;
3✔
1982
        }
3✔
1983

1984
        internal static void InternalWideSubnet(bool tryWide, IPNetwork[] ipnetworks, out IPNetwork ipnetwork)
1985
        {
12✔
1986
            if (ipnetworks == null)
12✔
1987
            {
2✔
1988
                if (tryWide == false)
2✔
1989
                {
1✔
1990
                    throw new ArgumentNullException("ipnetworks");
1✔
1991
                }
1992

1993
                ipnetwork = null;
1✔
1994
                return;
1✔
1995
            }
1996

1997
            IPNetwork[] nnin = Array.FindAll<IPNetwork>(ipnetworks, new Predicate<IPNetwork>(
10✔
1998
                delegate(IPNetwork ipnet)
10✔
1999
                {
23✔
2000
                    return ipnet != null;
23✔
2001
                }));
33✔
2002

2003
            if (nnin.Length <= 0)
10✔
2004
            {
2✔
2005
                if (tryWide == false)
2✔
2006
                {
1✔
2007
                    throw new ArgumentException("ipnetworks");
1✔
2008
                }
2009

2010
                ipnetwork = null;
1✔
2011
                return;
1✔
2012
            }
2013

2014
            if (nnin.Length == 1)
8✔
2015
            {
1✔
2016
                IPNetwork ipn0 = nnin[0];
1✔
2017
                ipnetwork = ipn0;
1✔
2018
                return;
1✔
2019
            }
2020

2021
            Array.Sort<IPNetwork>(nnin);
7✔
2022
            IPNetwork nnin0 = nnin[0];
7✔
2023
            BigInteger uintNnin0 = nnin0._ipaddress;
7✔
2024

2025
            IPNetwork nninX = nnin[nnin.Length - 1];
7✔
2026
            IPAddress ipaddressX = nninX.Broadcast;
7✔
2027

2028
            AddressFamily family = ipnetworks[0]._family;
7✔
2029
            foreach (IPNetwork ipnx in ipnetworks)
64✔
2030
            {
22✔
2031
                if (ipnx._family != family)
22✔
2032
                {
1✔
2033
                    throw new ArgumentException("MixedAddressFamily");
1✔
2034
                }
2035
            }
21✔
2036

2037
            var ipn = new IPNetwork(0, family, 0);
6✔
2038
            for (byte cidr = nnin0._cidr; cidr >= 0; cidr--)
264✔
2039
            {
132✔
2040
                var wideSubnet = new IPNetwork(uintNnin0, family, cidr);
132✔
2041
                if (wideSubnet.Contains(ipaddressX))
132✔
2042
                {
6✔
2043
                    ipn = wideSubnet;
6✔
2044
                    break;
6✔
2045
                }
2046
            }
126✔
2047

2048
            ipnetwork = ipn;
6✔
2049
            return;
6✔
2050
        }
9✔
2051

2052
        #endregion
2053

2054
        #region Print
2055

2056
        /// <summary>
2057
        /// Print an ipnetwork in a clear representation string.
2058
        /// </summary>
2059
        /// <returns>Dump an IPNetwork representation as string.</returns>
2060
        public string Print()
2061
        {
2✔
2062
            using (var sw = new StringWriter())
2✔
2063
            {
2✔
2064
                sw.WriteLine("IPNetwork   : {0}", this.ToString());
2✔
2065
                sw.WriteLine("Network     : {0}", this.Network);
2✔
2066
                sw.WriteLine("Netmask     : {0}", this.Netmask);
2✔
2067
                sw.WriteLine("Cidr        : {0}", this.Cidr);
2✔
2068
                sw.WriteLine("Broadcast   : {0}", this.Broadcast);
2✔
2069
                sw.WriteLine("FirstUsable : {0}", this.FirstUsable);
2✔
2070
                sw.WriteLine("LastUsable  : {0}", this.LastUsable);
2✔
2071
                sw.WriteLine("Usable      : {0}", this.Usable);
2✔
2072

2073
                return sw.ToString();
2✔
2074
            }
2075
        }
2✔
2076

2077
        [Obsolete("static Print is deprecated, please use instance Print.")]
2078
        public static string Print(IPNetwork ipnetwork)
2079
        {
2✔
2080
            if (ipnetwork == null)
2✔
2081
            {
1✔
2082
                throw new ArgumentNullException("ipnetwork");
1✔
2083
            }
2084

2085
            return ipnetwork.Print();
1✔
2086
        }
1✔
2087

2088
        #endregion
2089

2090
        #region TryGuessCidr
2091

2092
        /// <summary>
2093
        /// Delegate to CidrGuess ClassFull guessing of cidr.
2094
        /// </summary>
2095
        /// <param name="ip">A string representing an IPAdress that will be used to guess the corresponding CIDR.</param>
2096
        /// <param name="cidr">The resulting CIDR as byte.</param>
2097
        /// <returns>true if cidr was guessed successfully; otherwise, false.</returns>
2098
        public static bool TryGuessCidr(string ip, out byte cidr)
2099
        {
9✔
2100
            return CidrGuess.ClassFull.TryGuessCidr(ip, out cidr);
9✔
2101
        }
9✔
2102

2103
        /// <summary>
2104
        /// Try to parse cidr. Have to be >= 0 and &lt;= 32 or 128.
2105
        /// </summary>
2106
        /// <param name="sidr">A string representing a byte CIRD (/24).</param>
2107
        /// <param name="family">Either IPv4 or IPv6.</param>
2108
        /// <param name="cidr">The resulting CIDR as byte.</param>
2109
        /// <returns>true if cidr was converted successfully; otherwise, false.</returns>
2110
        public static bool TryParseCidr(string sidr, AddressFamily family, out byte? cidr)
2111
        {
11✔
2112
            byte b = 0;
11✔
2113
            if (!byte.TryParse(sidr, out b))
11✔
2114
            {
2✔
2115
                cidr = null;
2✔
2116
                return false;
2✔
2117
            }
2118

2119
            if (!IPNetwork.TryToNetmask(b, family, out IPAddress netmask))
9✔
2120
            {
2✔
2121
                cidr = null;
2✔
2122
                return false;
2✔
2123
            }
2124

2125
            cidr = b;
7✔
2126
            return true;
7✔
2127
        }
11✔
2128

2129
        #endregion
2130

2131
        #region ListIPAddress
2132

2133
        /// <summary>
2134
        /// List all ip addresses in a subnet.
2135
        /// </summary>
2136
        /// <param name="ipnetwork">The network to list IPAdresses.</param>
2137
        /// <returns>All the IPAdresses contained in ipnetwork.</returns>
2138
        [Obsolete("static ListIPAddress is deprecated, please use instance ListIPAddress.")]
2139
        public static IPAddressCollection ListIPAddress(IPNetwork ipnetwork)
2140
        {
1✔
2141
            return ipnetwork.ListIPAddress();
1✔
2142
        }
1✔
2143

2144
        /// <summary>
2145
        /// List all ip addresses in a subnet.
2146
        /// </summary>
2147
        /// <param name="filter">Filter IPAdresses from IPNetwork.</param>
2148
        /// <returns>The filterted IPAdresses contained in ipnetwork.</returns>
2149
        public IPAddressCollection ListIPAddress(FilterEnum filter = FilterEnum.All)
2150
        {
32✔
2151
            return new IPAddressCollection(this, filter);
32✔
2152
        }
32✔
2153

2154
        #endregion
2155

2156
        #region IComparable<IPNetwork> Members
2157

2158
        public static int Compare(IPNetwork left, IPNetwork right)
2159
        {
727,396✔
2160
            // two null IPNetworks are equal
2161
            if (ReferenceEquals(left, null) && ReferenceEquals(right, null))
727,396✔
2162
            {
66,143✔
2163
                return 0;
66,143✔
2164
            }
2165

2166
            // two same IPNetworks are equal
2167
            if (ReferenceEquals(left, right))
661,253✔
2168
            {
8✔
2169
                return 0;
8✔
2170
            }
2171

2172
            // null is always sorted first
2173
            if (ReferenceEquals(left, null))
661,245✔
2174
            {
1✔
2175
                return -1;
1✔
2176
            }
2177

2178
            if (ReferenceEquals(right, null))
661,244✔
2179
            {
661,067✔
2180
                return 1;
661,067✔
2181
            }
2182

2183
            // first test family
2184
            int result = left._family.CompareTo(right._family);
177✔
2185
            if (result != 0)
177✔
2186
            {
2✔
2187
                return result;
2✔
2188
            }
2189

2190
            // second test the network
2191
            result = left._network.CompareTo(right._network);
175✔
2192
            if (result != 0)
175✔
2193
            {
44✔
2194
                return result;
44✔
2195
            }
2196

2197
            // then test the cidr
2198
            result = left._cidr.CompareTo(right._cidr);
131✔
2199
            return result;
131✔
2200
        }
727,396✔
2201

2202
        /// <summary>
2203
        /// Compare two ipnetworks.
2204
        /// </summary>
2205
        /// <param name="other">The other network to compare to.</param>
2206
        /// <returns>A signed number indicating the relative values of this instance and value..</returns>
2207
        public int CompareTo(IPNetwork other)
2208
        {
38✔
2209
            return Compare(this, other);
38✔
2210
        }
38✔
2211

2212
        /// <summary>
2213
        /// Compare two ipnetworks.
2214
        /// </summary>
2215
        /// <param name="obj">The other object to compare to.</param>
2216
        /// <returns>A signed number indicating the relative values of this instance and value..</returns>
2217
        public int CompareTo(object obj)
2218
        {
3✔
2219
            // null is at less
2220
            if (obj == null)
3✔
2221
            {
1✔
2222
                return 1;
1✔
2223
            }
2224

2225
            // convert to a proper Cidr object
2226
            var other = obj as IPNetwork;
2✔
2227

2228
            // type problem if null
2229
            if (other == null)
2✔
2230
            {
1✔
2231
                throw new ArgumentException(
1✔
2232
                    "The supplied parameter is an invalid type. Please supply an IPNetwork type.",
1✔
2233
                    "obj");
1✔
2234
            }
2235

2236
            // perform the comparision
2237
            return this.CompareTo(other);
1✔
2238
        }
2✔
2239

2240
        #endregion
2241

2242
        #region IEquatable<IPNetwork> Members
2243

2244
        /// <summary>
2245
        /// Compare two ipnetworks.
2246
        /// </summary>
2247
        /// <param name="left">An IPNetwork to compare.</param>
2248
        /// <param name="right">An other IPNetwork to compare to.</param>
2249
        /// <returns>true if obj has the same value as this instance; otherwise, false.</returns>
2250
        public static bool Equals(IPNetwork left, IPNetwork right)
2251
        {
727,352✔
2252
            return Compare(left, right) == 0;
727,352✔
2253
        }
727,352✔
2254

2255
        /// <summary>
2256
        /// Compare two ipnetworks.
2257
        /// </summary>
2258
        /// <param name="other">An IPNetwork to compare to this instance.</param>
2259
        /// <returns>true if obj has the same value as this instance; otherwise, false.</returns>
2260
        public bool Equals(IPNetwork other)
2261
        {
9✔
2262
            return Equals(this, other);
9✔
2263
        }
9✔
2264

2265
        /// <summary>
2266
        /// Compare two ipnetworks.
2267
        /// </summary>
2268
        /// <param name="obj">An object value to compare to this instance.</param>
2269
        /// <returns>true if obj has the same value as this instance; otherwise, false.</returns>
2270
        public override bool Equals(object obj)
2271
        {
134✔
2272
            return Equals(this, obj as IPNetwork);
134✔
2273
        }
134✔
2274

2275
        #endregion
2276

2277
        #region Operators
2278

2279
        /// <summary>
2280
        /// Compares two IPNetwork.
2281
        /// </summary>
2282
        /// <param name="left">left instance.</param>
2283
        /// <param name="right">Right instance.</param>
2284
        /// <returns>true if left equals right; otherwise, false.</returns>
2285
        public static bool operator ==(IPNetwork left, IPNetwork right)
2286
        {
594,906✔
2287
            return Equals(left, right);
594,906✔
2288
        }
594,906✔
2289

2290
        /// <summary>
2291
        /// Compares two IPNetwork.
2292
        /// </summary>
2293
        /// <param name="left">left instance.</param>
2294
        /// <param name="right">Right instance.</param>
2295
        /// <returns>true if left does not equals right; otherwise, false.</returns>
2296
        public static bool operator !=(IPNetwork left, IPNetwork right)
2297
        {
132,303✔
2298
            return !Equals(left, right);
132,303✔
2299
        }
132,303✔
2300

2301
        /// <summary>
2302
        /// Compares two IPNetwork.
2303
        /// </summary>
2304
        /// <param name="left">left instance.</param>
2305
        /// <param name="right">Right instance.</param>
2306
        /// <returns>true if left is less than right; otherwise, false.</returns>
2307
        public static bool operator <(IPNetwork left, IPNetwork right)
2308
        {
2✔
2309
            return Compare(left, right) < 0;
2✔
2310
        }
2✔
2311

2312
        /// <summary>
2313
        /// Compares two IPNetwork.
2314
        /// </summary>
2315
        /// <param name="left">left instance.</param>
2316
        /// <param name="right">Right instance.</param>
2317
        /// <returns>true if left is greater than right; otherwise, false.</returns>
2318
        public static bool operator >(IPNetwork left, IPNetwork right)
2319
        {
2✔
2320
            return Compare(left, right) > 0;
2✔
2321
        }
2✔
2322

2323
        #endregion
2324

2325
        #region XmlSerialization
2326

2327
        /// <summary>
2328
        /// Initializes a new instance of the <see cref="IPNetwork"/> class.
2329
        /// Created for DataContractSerialization. Better use static methods IPNetwork.Parse() to create IPNetworks.
2330
        /// </summary>
2331
        public IPNetwork()
2332
            : this(0, AddressFamily.InterNetwork, 0)
2,000,003✔
2333
        {
2,000,003✔
2334
        }
2,000,003✔
2335

2336
        #endregion
2337

2338
        #region ISerializable
2339
        internal struct IPNetworkInteral
2340
        {
2341
            public BigInteger IPAddress;
2342
            public byte Cidr;
2343
            public AddressFamily AddressFamily;
2344
        }
2345

2346
        private IPNetwork(SerializationInfo info, StreamingContext context)
4,000,005✔
2347
        {
4,000,005✔
2348
            string sipnetwork = (string)info.GetValue("IPNetwork", typeof(string));
4,000,005✔
2349
            var ipnetwork = IPNetwork.Parse(sipnetwork);
4,000,005✔
2350

2351
            this._ipaddress = ipnetwork._ipaddress;
4,000,005✔
2352
            this._cidr = ipnetwork._cidr;
4,000,005✔
2353
            this._family = ipnetwork._family;
4,000,005✔
2354
        }
4,000,005✔
2355

2356
        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
2357
        {
4,000,005✔
2358
            info.AddValue("IPNetwork", this.ToString());
4,000,005✔
2359
        }
4,000,005✔
2360

2361
        #endregion
2362

2363
        #region WildcardMask
2364

2365
        /// <summary>
2366
        /// Gets netmask Inverse
2367
        /// https://en.wikipedia.org/wiki/Wildcard_mask
2368
        ///
2369
        /// A wildcard mask is a mask of bits that indicates which parts of an IP address are available for examination.
2370
        /// In the Cisco IOS,[1] they are used in several places, for example:
2371
        ///    To indicate the size of a network or subnet for some routing protocols, such as OSPF.
2372
        ///    To indicate what IP addresses should be permitted or denied in access control lists(ACLs).
2373
        ///
2374
        /// A wildcard mask can be thought of as an inverted subnet mask.For example,
2375
        /// a subnet mask of 255.255.255.0 (binary equivalent = 11111111.11111111.11111111.00000000)
2376
        /// inverts to a wildcard mask of 0.0.0.255 (binary equivalent = 00000000.00000000.00000000.11111111).
2377
        ///
2378
        /// A wild card mask is a matching rule.[2] The rule for a wildcard mask is:
2379
        ///     0 means that the equivalent bit must match
2380
        ///     1 means that the equivalent bit does not matter
2381
        ///
2382
        /// Any wildcard bit-pattern can be masked for examination.For example, a wildcard mask of 0.0.0.254
2383
        /// (binary equivalent = 00000000.00000000.00000000.11111110) applied to IP address 10.10.10.2
2384
        /// (00001010.00001010.00001010.00000010) will match even-numbered IP addresses 10.10.10.0, 10.10.10.2,
2385
        /// 10.10.10.4, 10.10.10.6 etc.
2386
        ///
2387
        /// Same mask applied to 10.10.10.1 (00001010.00001010.00001010.00000001) will match
2388
        /// odd-numbered IP addresses 10.10.10.1, 10.10.10.3, 10.10.10.5 etc.
2389
        ///
2390
        /// A network and wildcard mask combination of 1.1.1.1 0.0.0.0 would match an interface configured
2391
        /// exactly with 1.1.1.1 only, and nothing else.
2392
        ///
2393
        /// Wildcard masks are used in situations where subnet masks may not apply.For example,
2394
        /// when two affected hosts fall in different subnets, the use of a wildcard mask will
2395
        /// group them together.
2396
        ///
2397
        /// List of wildcard masks
2398
        /// Slash Netmask Wildcard mask
2399
        /// /32   255.255.255.255    0.0.0.0
2400
        /// /31   255.255.255.254    0.0.0.1
2401
        /// /30   255.255.255.252    0.0.0.3
2402
        /// /29   255.255.255.248    0.0.0.7
2403
        /// /28   255.255.255.240    0.0.0.15
2404
        /// /27   255.255.255.224    0.0.0.31
2405
        /// /26   255.255.255.192    0.0.0.63
2406
        /// /25   255.255.255.128    0.0.0.127
2407
        /// /24   255.255.255.0      0.0.0.255
2408
        /// /23   255.255.254.0      0.0.1.255
2409
        /// /22   255.255.252.0      0.0.3.255
2410
        /// /21   255.255.248.0      0.0.7.255
2411
        /// /20   255.255.240.0      0.0.15.255
2412
        /// /19   255.255.224.0      0.0.31.255
2413
        /// /18   255.255.192.0      0.0.63.255
2414
        /// /17   255.255.128.0      0.0.127.255
2415
        /// /16   255.255.0.0        0.0.255.255
2416
        /// /15   255.254.0.0        0.1.255.255
2417
        /// /14   255.252.0.0        0.3.255.255
2418
        /// /13   255.248.0.0        0.7.255.255
2419
        /// /12   255.240.0.0        0.15.255.255
2420
        /// /11   255.224.0.0        0.31.255.255
2421
        /// /10   255.192.0.0        0.63.255.255
2422
        /// /9    255.128.0.0        0.127.255.255
2423
        /// /8    255.0.0.0          0.255.255.255
2424
        /// /7    254.0.0.0          1.255.255.255
2425
        /// /6    252.0.0.0          3.255.255.255
2426
        /// /5    248.0.0.0          7.255.255.255
2427
        /// /4    240.0.0.0          15.255.255.255
2428
        /// /3    224.0.0.0          31.255.255.255
2429
        /// /2    192.0.0.0          63.255.255.255
2430
        /// /1    128.0.0.0          127.255.255.255
2431
        /// /0    0.0.0.0            255.255.255.255.
2432
        ///
2433
        /// </summary>
2434
        public IPAddress WildcardMask
2435
        {
2436
            get
2437
            {
202✔
2438
                byte cidr = this._family == AddressFamily.InterNetwork ? (byte)32 : (byte)128;
202✔
2439
                BigInteger netmask = IPNetwork.ToUint(cidr, this._family);
202✔
2440
                BigInteger wildcardmask = netmask - this._netmask;
202✔
2441

2442
                return IPNetwork.ToIPAddress(wildcardmask, this._family);
202✔
2443
            }
202✔
2444
        }
2445
        #endregion
2446
    }
2447
}
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

© 2025 Coveralls, Inc