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

lduchosal / ipnetwork / 960

15 May 2026 07:18AM UTC coverage: 0.0% (-94.1%) from 94.053%
960

Pull #411

appveyor

web-flow
Merge ef6b054ce into 4cec191ae
Pull Request #411: Bump MSTest.TestFramework from 4.2.2 to 4.2.3

0 of 2438 relevant lines covered (0.0%)

0.0 hits per line

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

0.0
/src/ConsoleApplication/Program.cs
1
// <copyright file="Program.cs" company="IPNetwork">
2
// Copyright (c) IPNetwork. All rights reserved.
3
// </copyright>
4

5
namespace System.Net;
6

7
using Gnu.Getopt;
8
using System.Collections.Generic;
9
using System.Diagnostics.CodeAnalysis;
10

11
/// <summary>
12
/// Console app for IPNetwork.
13
/// </summary>
14
public static class Program
15
{
16
    private const string GroupPrint = "Print options";
17
    private const string GroupOutput = "Output options";
18
    private const string GroupParse = "Parse options";
19
    private const string GroupActions = "Actions";
20
    private const string ArgNameNetwork = "network";
21

22
    private static readonly Dictionary<int, ArgParsed> Args = [];
×
23

24
    private static readonly ArgParsed[] ArgsList =
×
25
    [
×
26
        // Print options
×
27
        new ArgParsed('i', GroupPrint, ArgNameNetwork, (ac, _) => { ac.IPNetwork = true; }),
×
28
        new ArgParsed('n', GroupPrint, "network address", (ac, _) => { ac.Network = true; }),
×
29
        new ArgParsed('m', GroupPrint, "netmask", (ac, _) => { ac.Netmask = true; }),
×
30
        new ArgParsed('c', GroupPrint, "cidr", (ac, _) => { ac.Cidr = true; }),
×
31
        new ArgParsed('b', GroupPrint, "broadcast", (ac, _) => { ac.Broadcast = true; }),
×
32
        new ArgParsed('f', GroupPrint, "first usable ip address", (ac, _) => { ac.FirstUsable = true; }),
×
33
        new ArgParsed('l', GroupPrint, "last usable ip address", (ac, _) => { ac.LastUsable = true; }),
×
34
        new ArgParsed('u', GroupPrint, "number of usable ip addresses", (ac, _) => { ac.Usable = true; }),
×
35
        new ArgParsed('t', GroupPrint, "total number of ip addresses", (ac, _) => { ac.Total = true; }),
×
36

×
37
        // Output options
×
38
        new ArgParsed('j', GroupOutput, "JSON output", (ac, _) => { ac.Json = true; }),
×
39

×
40
        // Parse options
×
41
        new ArgParsed('D', GroupParse, "IPv4 only - use default cidr (ClassA/8, ClassB/16, ClassC/24)",
×
42
            (ac, _) => { ac.CidrParse = CidrParse.Default; }),
×
43
        new ArgParsed('d', GroupParse, "use cidr if not provided (default /32)", (ac, arg) =>
×
44
        {
×
45
            if (!IPNetwork2.TryParseCidr(arg, Sockets.AddressFamily.InterNetwork, out byte? cidr))
×
46
            {
×
47
                ac.ParseErrors.Add(string.Format("Invalid cidr {0}", cidr));
×
48
                ac.Action = Action.Usage;
×
49
                return;
×
50
            }
×
51

×
52
            ac.CidrParse = CidrParse.Value;
×
53
            ac.CidrParsed = (byte)cidr;
×
54
        }, argName: "cidr"),
×
55

×
56
        // Actions
×
57
        new ArgParsed('h', GroupActions, "help message",
×
58
            (ac, _) => { ac.Action = Action.Usage; },
×
59
            example: "ipnetwork -h"),
×
60
        new ArgParsed('s', GroupActions, "split network into cidr subnets", (ac, arg) =>
×
61
        {
×
62
            if (!IPNetwork2.TryParseCidr(arg, Sockets.AddressFamily.InterNetwork, out byte? cidr))
×
63
            {
×
64
                ac.ParseErrors.Add(string.Format("Invalid cidr {0}", cidr));
×
65
                ac.Action = Action.Usage;
×
66
                return;
×
67
            }
×
68

×
69
            ac.Action = Action.Subnet;
×
70
            ac.SubnetCidr = (byte)cidr;
×
71
        }, argName: "cidr", example: "ipnetwork -s 24 10.0.0.0/8"),
×
72
        new ArgParsed('w', GroupActions, "supernet networks into smallest possible subnets",
×
73
            (ac, _) => { ac.Action = Action.Supernet; },
×
74
            example: "ipnetwork -w 10.0.0.0/24 10.0.1.0/24"),
×
75
        new ArgParsed('W', GroupActions, "supernet networks into one single subnet",
×
76
            (ac, _) => { ac.Action = Action.WideSupernet; },
×
77
            example: "ipnetwork -W 10.0.0.0/24 10.0.10.0/24"),
×
78
        new ArgParsed('x', GroupActions, "list all ip addresses in networks",
×
79
            (ac, _) => { ac.Action = Action.ListIPAddress; },
×
80
            example: "ipnetwork -x 10.0.0.0/30"),
×
81
        new ArgParsed('C', GroupActions, "network contain networks", (ac, arg) =>
×
82
        {
×
83
            if (!TryParseIPNetwork(arg, ac.CidrParse, ac.CidrParsed, out IPNetwork2? ipnetwork))
×
84
            {
×
85
                ac.ParseErrors.Add($"Unable to parse ipnetwork {arg}");
×
86
                ac.Action = Action.Usage;
×
87
                return;
×
88
            }
×
89

×
90
            ac.Action = Action.ContainNetwork;
×
91
            ac.ContainNetwork = ipnetwork;
×
92
        }, argName: ArgNameNetwork, example: "ipnetwork -C 10.0.0.0/8 10.0.1.0/24"),
×
93
        new ArgParsed('o', GroupActions, "network overlap networks", (ac, arg) =>
×
94
        {
×
95
            if (!TryParseIPNetwork(arg, ac.CidrParse, ac.CidrParsed, out IPNetwork2? ipnetwork))
×
96
            {
×
97
                ac.ParseErrors.Add(string.Format("Unable to parse ipnetwork {0}", arg));
×
98
                ac.Action = Action.Usage;
×
99
                return;
×
100
            }
×
101

×
102
            ac.Action = Action.OverlapNetwork;
×
103
            ac.OverlapNetwork = ipnetwork;
×
104
        }, argName: ArgNameNetwork, example: "ipnetwork -o 10.0.0.0/8 192.168.0.0/16"),
×
105
        new ArgParsed('S', GroupActions, "subtract network from networks", (ac, arg) =>
×
106
        {
×
107
            if (!TryParseIPNetwork(arg, ac.CidrParse, ac.CidrParsed, out IPNetwork2? ipnetwork))
×
108
            {
×
109
                ac.ParseErrors.Add(string.Format("Unable to parse ipnetwork {0}", arg));
×
110
                ac.Action = Action.Usage;
×
111
                return;
×
112
            }
×
113

×
114
            ac.Action = Action.SubtractNetwork;
×
115
            ac.SubtractNetwork = ipnetwork;
×
116
        }, argName: ArgNameNetwork, example: "ipnetwork -S 10.0.1.0/24 10.0.0.0/23"),
×
117

×
118
        // Hidden
×
119
        new ArgParsed('?', (_, _) => { }),
×
120
    ];
×
121

122
    /// <summary>
123
    /// Program entry point.
124
    /// </summary>
125
    /// <param name="args">program arguments.</param>
126
    public static void Main(string[] args)
127
    {
×
128
        ProgramContext ac = ParseArgs(args);
×
129
        ActionOutput output = ActionComputer.Compute(ac, ArgsList);
×
130
        IFormatter formatter = ac.Json ? new JsonFormatter(Console.Out) : new TextFormatter(Console.Out);
×
131
        formatter.Write(output, ac);
×
132
    }
×
133

134
    static Program()
135
    {
×
136
        foreach (ArgParsed ap in ArgsList)
×
137
        {
×
138
            Args.Add(ap.Arg, ap);
×
139
        }
×
140
    }
×
141

142
    private static ProgramContext ParseArgs(string[] args)
143
    {
×
144
        int c;
145
        var g = new Getopt("ipnetwork", args, "jinmcbfltud:Dhs:wWxC:o:S:");
×
146
        var ac = new ProgramContext();
×
147

148
        while ((c = g.getopt()) != -1)
×
149
        {
×
150
            string? optArg = g.Optarg;
×
151
            Args[c].Run(ac, optArg ?? string.Empty);
×
152
        }
×
153

154
        var ipnetworks = new List<string>();
×
155
        for (int i = g.Optind; i < args.Length; i++)
×
156
        {
×
157
            if (!string.IsNullOrEmpty(args[i]))
×
158
            {
×
159
                ipnetworks.Add(args[i]);
×
160
            }
×
161
        }
×
162

163
        ac.NetworksString = ipnetworks.ToArray();
×
164
        ParseIPNetworks(ac);
×
165

166
        if (ac.Networks.Length == 0 && ac.Action != Action.Usage)
×
167
        {
×
168
            ac.ParseErrors.Add("Provide at least one ipnetwork");
×
169
            ac.Action = Action.Usage;
×
170
        }
×
171

172
        if (ac.Action == Action.Supernet
×
173
            && ipnetworks.Count < 2)
×
174
        {
×
175
            ac.ParseErrors.Add("Supernet action required at least two ipnetworks");
×
176
            ac.Action = Action.Usage;
×
177
        }
×
178

179
        if (ac.Action == Action.WideSupernet
×
180
            && ipnetworks.Count < 2)
×
181
        {
×
182
            ac.ParseErrors.Add("WideSupernet action required at least two ipnetworks");
×
183
            ac.Action = Action.Usage;
×
184
        }
×
185

186
        if (PrintNoValue(ac))
×
187
        {
×
188
            PrintAll(ac);
×
189
        }
×
190

191
        if (g.Optind == 0)
×
192
        {
×
193
            PrintAll(ac);
×
194
        }
×
195

196
        return ac;
×
197
    }
×
198

199
    private static void ParseIPNetworks(ProgramContext ac)
200
    {
×
201
        var ipnetworks = new List<IPNetwork2>();
×
202
        foreach (string ips in ac.NetworksString)
×
203
        {
×
204
            if (!TryParseIPNetwork(ips, ac.CidrParse, ac.CidrParsed, out IPNetwork2? ipnetwork))
×
205
            {
×
206
                ac.ParseErrors.Add(string.Format("Unable to parse ipnetwork {0}", ips));
×
207
                continue;
×
208
            }
209

210
            ipnetworks.Add(ipnetwork);
×
211
        }
×
212

213
        ac.Networks = ipnetworks.ToArray();
×
214
    }
×
215

216
    private static bool TryParseIPNetwork(string ip, CidrParse cidrParse, byte cidr, [NotNullWhen(true)] out IPNetwork2? ipn)
217
    {
×
218
        IPNetwork2? ipnetwork = null;
×
219
        switch (cidrParse)
×
220
        {
221
            case CidrParse.Default when !IPNetwork2.TryParse(ip, out ipnetwork):
×
222
                ipn = null;
×
223
                return false;
×
224
            case CidrParse.Value:
225
            {
×
226
                if (!IPNetwork2.TryParse(ip, cidr, out ipnetwork)
×
227
                    && !IPNetwork2.TryParse(ip, out ipnetwork))
×
228
                {
×
229
                    ipn = null;
×
230
                    return false;
×
231
                }
232

233
                break;
×
234
            }
235
        }
236

237
        if (ipnetwork is null)
×
238
        {
×
239
            ipn = null;
×
240
            return false;
×
241
        }
242

243
        ipn = ipnetwork;
×
244
        return true;
×
245
    }
×
246

247
    private static bool PrintNoValue(ProgramContext ac)
248
    {
×
249
        ArgumentNullException.ThrowIfNull(ac);
×
250

251
        return ac is { IPNetwork: false, Network: false }
×
252
               && !ac.Netmask
×
253
               && !ac.Cidr
×
254
               && !ac.Broadcast
×
255
               && !ac.FirstUsable
×
256
               && !ac.LastUsable
×
257
               && !ac.Total
×
258
               && !ac.Usable;
×
259
    }
×
260

261
    private static void PrintAll(ProgramContext ac)
262
    {
×
263
        ArgumentNullException.ThrowIfNull(ac);
×
264

265
        ac.IPNetwork = true;
×
266
        ac.Network = true;
×
267
        ac.Netmask = true;
×
268
        ac.Cidr = true;
×
269
        ac.Broadcast = true;
×
270
        ac.FirstUsable = true;
×
271
        ac.LastUsable = true;
×
272
        ac.Usable = true;
×
273
        ac.Total = true;
×
274
    }
×
275

276
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc