-
Notifications
You must be signed in to change notification settings - Fork 149
Expand file tree
/
Copy pathResolve.swift
More file actions
106 lines (85 loc) · 2.74 KB
/
Copy pathResolve.swift
File metadata and controls
106 lines (85 loc) · 2.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/*
This source file is part of the Swift System open source project
Copyright (c) 2021 - 2025 Apple Inc. and the Swift System project authors
Licensed under Apache License v2.0 with Runtime Library Exception
See https://swift.org/LICENSE.txt for license information
*/
import ArgumentParser
import SystemSockets
struct Resolve: ParsableCommand {
static let configuration = CommandConfiguration(
abstract: "Resolve a hostname to IP addresses using getaddrinfo"
)
@Argument(help: "The hostname to resolve")
var hostname: String
@Option(name: .shortAndLong, help: "Service name or port number")
var service: String?
@Flag(name: .long, help: "Show only IPv4 addresses")
var ipv4Only: Bool = false
@Flag(name: .long, help: "Show only IPv6 addresses")
var ipv6Only: Bool = false
@available(System 99, *)
func run() throws {
let family: SocketDescriptor.Domain?
if ipv4Only {
family = .ipv4
} else if ipv6Only {
family = .ipv6
} else {
family = nil
}
let hints = SocketAddress.ResolutionHints(family: family)
print("Resolving \(hostname)...")
let addresses = try SocketAddress.resolve(
hostname: hostname,
service: service,
hints: hints
)
if addresses.isEmpty {
print("No addresses found")
return
}
print("Found \(addresses.count) address(es):\n")
for (index, info) in addresses.enumerated() {
print("[\(index + 1)] Family: \(familyName(info.family))")
print(" Type: \(typeName(info.socketType))")
print(" Protocol: \(protocolName(info.protocol))")
if let ipv4 = info.address.ipv4 {
print(" Address: \(ipv4.addressString):\(ipv4.port)")
} else if let ipv6 = info.address.ipv6 {
print(" Address: [\(ipv6.addressString)]:\(ipv6.port)")
}
if let canonName = info.canonicalName {
print(" Canonical: \(canonName)")
}
print()
}
}
@available(System 99, *)
private func familyName(_ domain: SocketDescriptor.Domain) -> String {
switch domain {
case .ipv4: return "IPv4"
case .ipv6: return "IPv6"
case .local: return "Unix"
default: return "Unknown (\(domain.rawValue))"
}
}
@available(System 99, *)
private func typeName(_ type: SocketDescriptor.ConnectionType) -> String {
switch type {
case .stream: return "Stream (TCP)"
case .datagram: return "Datagram (UDP)"
case .raw: return "Raw"
default: return "Unknown (\(type.rawValue))"
}
}
@available(System 99, *)
private func protocolName(_ proto: SocketDescriptor.ProtocolID) -> String {
switch proto {
case .tcp: return "TCP"
case .udp: return "UDP"
case .ip: return "IP"
default: return "Unknown (\(proto.rawValue))"
}
}
}