/// <summary> /// Parses string /// </summary> /// <param name="str">String representation in IP or IP/CIDR form</param> /// <param name="val">IP prefix</param> /// <returns><c>true</c> when <paramref name="str"/> parses successfuly; <c>false</c> otherwise</returns> public static bool TryParse(string str, out IPPrefix val) { try { val = new IPPrefix(str); return(true); } catch (ArgumentException) { val = null; return(false); } }
/// <summary> /// Constructs an object from wg-quick stream /// </summary> /// <param name="reader">Input stream</param> public Interface(TextReader reader) { var parserState = ParserState.NotInASection; Peers = new List <Peer>(); Peer peer = null; for (; ;) { var line = reader.ReadLine(); if (line == null) { break; } int index = line.IndexOf("#"); if (index >= 0) { line = line.Substring(0, index); } line = line.Trim(); if (line.Length == 0) { continue; } var lineLower = line.ToLowerInvariant(); if (lineLower == "[interface]") { if (peer != null) { Peers.Add(peer); } parserState = ParserState.InInterfaceSection; continue; } if (lineLower == "[peer]") { if (peer != null) { Peers.Add(peer); } peer = new Peer(); parserState = ParserState.InPeerSection; continue; } if (parserState == ParserState.NotInASection) { throw new ArgumentException("Line must occur in a section: " + line); } index = line.IndexOf('='); if (index < 0) { throw new ArgumentException("Config key is missing an equals separator: " + line); } var key = lineLower.Substring(0, index).TrimEnd(); var val = line.Substring(index + 1, line.Length - (index + 1)).TrimStart(); if (val.Length == 0) { throw new ArgumentException("Key must have a value: " + line); } if (parserState == ParserState.InInterfaceSection) { switch (key) { case "privatekey": PrivateKey = new Key(val); break; case "listenport": ListenPort = ushort.Parse(val); break; case "mtu": MTU = ushort.Parse(val); if (MTU < 576 || MTU > 65535) { throw new ArgumentException("Invalid MTU: " + line); } break; case "address": var addresses = SplitList(val); Addresses = new List <IPPrefix>(addresses.Length); for (var i = 0; i < addresses.Length; ++i) { Addresses.Add(IPPrefix.Parse(addresses[i])); } break; case "dns": addresses = SplitList(val); var DNS = new List <IPAddress>(); var DNSSearch = new List <string>(); foreach (var a in addresses) { if (IPAddress.TryParse(a, out var address)) { DNS.Add(address); } else { DNSSearch.Add(a); } } break; case "preup": PreUp = val; break; case "postup": PostUp = val; break; case "predown": PreDown = val; break; case "postdown": PostDown = val; break; case "table": switch (val) { case "off": TableOff = true; break; case "auto": case "main": TableOff = false; break; default: uint.Parse(val); TableOff = false; break; } break; default: throw new ArgumentException("Invalid key for [Interface] section: " + key); } } else if (parserState == ParserState.InPeerSection) { switch (key) { case "publickey": peer.PublicKey = new Key(val); break; case "presharedkey": peer.PresharedKey = new Key(val); break; case "allowedips": var addresses = SplitList(val); peer.AllowedIPs = new List <IPPrefix>(addresses.Length); for (var i = 0; i < addresses.Length; ++i) { peer.AllowedIPs.Add(IPPrefix.Parse(addresses[i])); } break; case "persistentkeepalive": peer.PersistentKeepalive = val == "off" ? (ushort)0 : ushort.Parse(val); break; case "endpoint": // TODO: Implement! //peer.Endpoint = ... break; default: throw new ArgumentException("Invalid key for [Peer] section: " + key); } } } if (peer != null) { Peers.Add(peer); } if (PrivateKey == null) { throw new ArgumentException("An interface must have a private key"); } foreach (var p in Peers) { if (p.PublicKey == null) { throw new ArgumentException("All peers must have public keys"); } } }