network-infra-utility 0.2.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +21 -0
  3. data/CHANGELOG.md +31 -4
  4. data/Gemfile +2 -0
  5. data/Gemfile.lock +70 -0
  6. data/Rakefile +1 -1
  7. data/bin/dns-query +834 -0
  8. data/bin/geo-doc +135 -0
  9. data/bin/geo-get +1 -1
  10. data/document/ASNum/346/250/241/345/235/227/345/212/237/350/203/275/350/257/264/346/230/216.md +242 -0
  11. data/document/DNSQuery/345/267/245/345/205/267/344/275/277/347/224/250/346/226/271/346/263/225.md +248 -0
  12. data/document/Geo/345/221/275/344/273/244/345/267/245/345/205/267/344/275/277/347/224/250/346/226/271/346/263/225.md +441 -0
  13. data/document/IP/346/250/241/345/235/227/345/212/237/350/203/275/350/257/264/346/230/216.md +297 -0
  14. data/document/MAC/346/250/241/345/235/227/345/212/237/350/203/275/350/257/264/346/230/216.md +296 -0
  15. data/document/SSH/350/277/236/346/216/245/345/256/242/346/210/267/347/253/257/344/275/277/347/224/250/346/226/271/346/263/225.md +764 -0
  16. data/network-infra-utility.gemspec +4 -2
  17. data/network.rb +3 -1
  18. data/service/geodb/GeoAPI.md +1 -0
  19. data/service/geodb/geodb.rb +278 -1
  20. data/service/ssh/README.md +942 -0
  21. data/service/ssh/bin/ssh-client +198 -0
  22. data/service/ssh/design/SSH/350/277/236/346/216/245/345/256/242/346/210/267/347/253/257/345/212/237/350/203/275/351/234/200/346/261/202/346/226/207/346/241/243.md +292 -0
  23. data/service/ssh/design/SSH/350/277/236/346/216/245/345/256/242/346/210/267/347/253/257/350/257/246/347/273/206/350/256/276/350/256/241/346/226/207/346/241/243.md +1521 -0
  24. data/service/ssh/design/SSH/350/277/236/346/216/245/345/256/242/346/210/267/347/253/257/350/275/257/344/273/266/350/256/276/350/256/241/346/226/207/346/241/243.md +2493 -0
  25. data/service/ssh/ext/ssh_core/bin/ssh_core.cmd +28 -0
  26. data/service/ssh/ext/ssh_core/config/sys.config +0 -0
  27. data/service/ssh/ext/ssh_core/config/vm.args +0 -0
  28. data/service/ssh/ext/ssh_core/local_deps/jsx/CHECKSUM +1 -0
  29. data/service/ssh/ext/ssh_core/local_deps/jsx/LICENSE +21 -0
  30. data/service/ssh/ext/ssh_core/local_deps/jsx/README.md +696 -0
  31. data/service/ssh/ext/ssh_core/local_deps/jsx/VERSION +1 -0
  32. data/service/ssh/ext/ssh_core/local_deps/jsx/contents.tar.gz +0 -0
  33. data/service/ssh/ext/ssh_core/local_deps/jsx/metadata.config +15 -0
  34. data/service/ssh/ext/ssh_core/local_deps/jsx/rebar.config +17 -0
  35. data/service/ssh/ext/ssh_core/local_deps/jsx/rebar.lock +1 -0
  36. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx.app.src +10 -0
  37. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx.erl +506 -0
  38. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_config.erl +393 -0
  39. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_config.hrl +18 -0
  40. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_consult.erl +81 -0
  41. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_decoder.erl +1909 -0
  42. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_encoder.erl +116 -0
  43. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_parser.erl +1214 -0
  44. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_to_json.erl +408 -0
  45. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_to_term.erl +389 -0
  46. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_verify.erl +121 -0
  47. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx.erl +506 -0
  48. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_config.erl +393 -0
  49. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_config.hrl +18 -0
  50. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_consult.erl +81 -0
  51. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_decoder.erl +1909 -0
  52. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_encoder.erl +116 -0
  53. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_parser.erl +1214 -0
  54. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_to_json.erl +408 -0
  55. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_to_term.erl +389 -0
  56. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_verify.erl +121 -0
  57. data/service/ssh/ext/ssh_core/rebar.config +24 -0
  58. data/service/ssh/ext/ssh_core/rebar.lock +1 -0
  59. data/service/ssh/ext/ssh_core/src/ssh_auth_engine.erl +156 -0
  60. data/service/ssh/ext/ssh_core/src/ssh_channel_stm.erl +232 -0
  61. data/service/ssh/ext/ssh_core/src/ssh_codec.erl +83 -0
  62. data/service/ssh/ext/ssh_core/src/ssh_conn_sup.erl +48 -0
  63. data/service/ssh/ext/ssh_core/src/ssh_conn_worker.erl +535 -0
  64. data/service/ssh/ext/ssh_core/src/ssh_core.app.src +36 -0
  65. data/service/ssh/ext/ssh_core/src/ssh_core_app.erl +11 -0
  66. data/service/ssh/ext/ssh_core/src/ssh_core_sup.erl +46 -0
  67. data/service/ssh/ext/ssh_core/src/ssh_infra_sup.erl +104 -0
  68. data/service/ssh/ext/ssh_core/src/ssh_ipc.hrl +80 -0
  69. data/service/ssh/ext/ssh_core/src/ssh_ipc_coalesce.erl +94 -0
  70. data/service/ssh/ext/ssh_core/src/ssh_ipc_gateway.erl +467 -0
  71. data/service/ssh/ext/ssh_core/src/ssh_ipc_proto.erl +95 -0
  72. data/service/ssh/ext/ssh_core/src/ssh_jump_chain.erl +101 -0
  73. data/service/ssh/ext/ssh_core/src/ssh_keepalive_mgr.erl +222 -0
  74. data/service/ssh/ext/ssh_core/src/ssh_known_hosts_proxy.erl +67 -0
  75. data/service/ssh/ext/ssh_core/src/ssh_port_fwd.erl +225 -0
  76. data/service/ssh/ext/ssh_core/src/ssh_sftp_session.erl +250 -0
  77. data/service/ssh/ext/ssh_core/src/ssh_sftp_sup.erl +62 -0
  78. data/service/ssh/ext/ssh_core_rs/Cargo.lock +2345 -0
  79. data/service/ssh/ext/ssh_core_rs/Cargo.toml +30 -0
  80. data/service/ssh/ext/ssh_core_rs/bin/ssh_core_rs +34 -0
  81. data/service/ssh/ext/ssh_core_rs/bin/ssh_core_rs.cmd +40 -0
  82. data/service/ssh/ext/ssh_core_rs/src/channel.rs +296 -0
  83. data/service/ssh/ext/ssh_core_rs/src/coalesce.rs +143 -0
  84. data/service/ssh/ext/ssh_core_rs/src/codec.rs +71 -0
  85. data/service/ssh/ext/ssh_core_rs/src/conn.rs +628 -0
  86. data/service/ssh/ext/ssh_core_rs/src/gateway.rs +389 -0
  87. data/service/ssh/ext/ssh_core_rs/src/handler.rs +293 -0
  88. data/service/ssh/ext/ssh_core_rs/src/keepalive.rs +194 -0
  89. data/service/ssh/ext/ssh_core_rs/src/main.rs +351 -0
  90. data/service/ssh/ext/ssh_core_rs/src/portfwd.rs +378 -0
  91. data/service/ssh/ext/ssh_core_rs/src/proto.rs +198 -0
  92. data/service/ssh/ext/ssh_core_rs/src/sftp.rs +294 -0
  93. data/service/ssh/lib/network_infra_utility/ssh/automation/macro_engine.rb +213 -0
  94. data/service/ssh/lib/network_infra_utility/ssh/client.rb +257 -0
  95. data/service/ssh/lib/network_infra_utility/ssh/config/schema.rb +90 -0
  96. data/service/ssh/lib/network_infra_utility/ssh/config/settings.rb +103 -0
  97. data/service/ssh/lib/network_infra_utility/ssh/config/store.rb +90 -0
  98. data/service/ssh/lib/network_infra_utility/ssh/ipc/coalesce.rb +83 -0
  99. data/service/ssh/lib/network_infra_utility/ssh/ipc/errors.rb +36 -0
  100. data/service/ssh/lib/network_infra_utility/ssh/ipc/router.rb +212 -0
  101. data/service/ssh/lib/network_infra_utility/ssh/ipc/transport.rb +81 -0
  102. data/service/ssh/lib/network_infra_utility/ssh/security/host_key.rb +211 -0
  103. data/service/ssh/lib/network_infra_utility/ssh/security/vault.rb +211 -0
  104. data/service/ssh/lib/network_infra_utility/ssh/session/history.rb +56 -0
  105. data/service/ssh/lib/network_infra_utility/ssh/session/manager.rb +92 -0
  106. data/service/ssh/lib/network_infra_utility/ssh/session/session.rb +109 -0
  107. data/service/ssh/lib/network_infra_utility/ssh/session/tree.rb +95 -0
  108. data/service/ssh/lib/network_infra_utility/ssh/terminal/ansi_parser.rb +435 -0
  109. data/service/ssh/lib/network_infra_utility/ssh/terminal/buffer.rb +78 -0
  110. data/service/ssh/lib/network_infra_utility/ssh/terminal/emulator.rb +159 -0
  111. data/service/ssh/lib/network_infra_utility/ssh/terminal/logger.rb +195 -0
  112. data/service/ssh/lib/network_infra_utility/ssh/terminal/screen.rb +212 -0
  113. data/service/ssh/lib/network_infra_utility/ssh/terminal/theme.rb +127 -0
  114. data/service/ssh/lib/network_infra_utility/ssh/version.rb +7 -0
  115. data/service/ssh/lib/network_infra_utility/ssh.rb +44 -0
  116. data/support/basic/as_num.rb +221 -0
  117. data/support/basic/mac_address.rb +281 -0
  118. data/version.rb +1 -1
  119. metadata +138 -1
@@ -0,0 +1,221 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ =begin
5
+ << 16位AS号(2字节,传统)>>
6
+
7
+ | 类型 | 范围 | 说明 |
8
+ | --------- | ----------------- | --------------------------- |
9
+ | **公有AS号** | **1 – 64511** | 全球互联网可路由,需向RIR(区域互联网注册机构)申请 |
10
+ | **私有AS号** | **64512 – 65534** | 仅用于内部网络,不可通告到公网 |
11
+ | **保留** | 0, 23456, 65535 | AS 0 保留、AS_TRANS、文档保留 |
12
+
13
+ << 32位AS号(4字节,RFC 4893/6793)>>
14
+
15
+ | 类型 | 范围 | 说明 |
16
+ | --------- | --------------------------------- | ------------- |
17
+ | **公有AS号** | **65536 – 4,199,999,999** | 全球可路由(约42亿个) |
18
+ | **私有AS号** | **4,200,000,000 – 4,294,967,294** | 内部使用(约9500万个) |
19
+ | **保留** | 4,294,967,295 | 保留(相当于32位全1) |
20
+
21
+ << 两种记法 >>
22
+
23
+ | 记法 | 示例 | 说明 |
24
+ | --------- | ------------ | -------------------------- |
25
+ | **asplain** | `4259840001` | 纯十进制整数,32 位 AS 常用此记法 |
26
+ | **asdot** | `1.10` | 高16位.低16位,两段各 0 – 65535 |
27
+
28
+ 转换关系:plain = high * 65536 + low;asdot = "high.low"
29
+ 例:1.10 → 65546;65546 → "1.10"
30
+ =end
31
+
32
+ # AS 号工具。
33
+ #
34
+ # 用法:
35
+ # as = ASNum.new("1.10") # asdot 记法
36
+ # ASNum.new("65546") # asplain 记法
37
+ # ASNum.new(65546) # Integer 记法
38
+ #
39
+ # as.to_i # → 65546
40
+ # as.to_plain # → "65546"
41
+ # as.to_dot # → "1.10"
42
+ # as.to_s # → "1.10"(asdot 优先)或 "65546"(16位时纯数字)
43
+ #
44
+ # as.public? # → true / false
45
+ # as.private? # → true / false
46
+ # as.reserved? # → true / false
47
+ # as.type # → :public / :private / :reserved
48
+ #
49
+ # as.as2? # → 是否落在 16 位传统范围 (0 – 65535)
50
+ # as.as4? # → 是否为 32 位扩展号 (≥ 65536)
51
+ #
52
+ # ASNum === ASNum # → Comparable 排序
53
+
54
+ class ASNum
55
+ include Comparable
56
+
57
+ attr_reader :number, :high, :low
58
+
59
+ # AS 号范围常量
60
+ AS2_MAX = 65535
61
+ AS4_MAX = 4_294_967_295
62
+ # 16 位
63
+ PUB_16_MIN = 1
64
+ PUB_16_MAX = 64_511
65
+ PRIV_16_MIN = 64_512
66
+ PRIV_16_MAX = 65_534
67
+ # 32 位
68
+ PUB_32_MIN = 65_536
69
+ PUB_32_MAX = 4_199_999_999
70
+ PRIV_32_MIN = 4_200_000_000
71
+ PRIV_32_MAX = 4_294_967_294
72
+ # 特殊保留
73
+ RESERVED_16 = [0, 23_456, 65_535].freeze
74
+ RESERVED_32 = 4_294_967_295
75
+
76
+ # 从 String(asplain 或 asdot)或 Integer 构造。
77
+ #
78
+ # asplain 示例:"65546" / 65546
79
+ # asdot 示例:"1.10"(高16位.低16位)
80
+ def initialize(arg)
81
+ @number = parse(arg)
82
+ @high = @number >> 16
83
+ @low = @number & 0xFFFF
84
+ raise ArgumentError, "AS number out of range: #{arg}" unless valid_range?
85
+ end
86
+
87
+ # ---- 格式输出 ----
88
+
89
+ # 十进制整数。
90
+ def to_i
91
+ @number
92
+ end
93
+
94
+ # asplain 字符串(纯十进制)。
95
+ def to_plain
96
+ @number.to_s
97
+ end
98
+
99
+ # asdot 字符串(高16位.低16位)。16 位范围内无点。
100
+ def to_dot
101
+ @number <= AS2_MAX ? @number.to_s : "#{@high}.#{@low}"
102
+ end
103
+
104
+ # 默认字符串:asdot 优先(16 位时回退为纯数字)。
105
+ def to_s
106
+ to_dot
107
+ end
108
+
109
+ alias inspect to_dot
110
+
111
+ # ---- 类型判定 ----
112
+
113
+ # 公有 AS 号。先排除保留号,再查范围,避免 AS_TRANS(23456) 同时命中。
114
+ def public?
115
+ !reserved? &&
116
+ ((PUB_16_MIN..PUB_16_MAX).include?(@number) ||
117
+ (PUB_32_MIN..PUB_32_MAX).include?(@number))
118
+ end
119
+
120
+ def private?
121
+ !reserved? &&
122
+ ((PRIV_16_MIN..PRIV_16_MAX).include?(@number) ||
123
+ (PRIV_32_MIN..PRIV_32_MAX).include?(@number))
124
+ end
125
+
126
+ def reserved?
127
+ RESERVED_16.include?(@number) || @number == RESERVED_32
128
+ end
129
+
130
+ # 一次性返回类型符号。
131
+ def type
132
+ return :public if public?
133
+ return :private if private?
134
+ return :reserved if reserved?
135
+ :unknown
136
+ end
137
+
138
+ # ---- 位宽判定 ----
139
+
140
+ # 是否为 16 位传统 AS 号(0 – 65535)。
141
+ def as2?
142
+ @number <= AS2_MAX
143
+ end
144
+
145
+ # 是否为 32 位扩展 AS 号(≥ 65536)。
146
+ def as4?
147
+ @number > AS2_MAX
148
+ end
149
+
150
+ # ---- 保留别名,兼容原接口 ----
151
+
152
+ alias is_public_as? public?
153
+ alias is_private_as? private?
154
+ alias is_reserved_as? reserved?
155
+
156
+ # ---- Comparable ----
157
+
158
+ def <=>(other)
159
+ @number <=> other.number
160
+ end
161
+
162
+ # hash 与 eql? 使 ASNum 可作 Hash key
163
+ def hash
164
+ @number.hash
165
+ end
166
+
167
+ def eql?(other)
168
+ other.is_a?(ASNum) && @number == other.number
169
+ end
170
+
171
+ private
172
+
173
+ # 解析输入为 32 位整数。
174
+ def parse(arg)
175
+ case arg
176
+ when Integer
177
+ arg
178
+ when String
179
+ parse_string(arg)
180
+ else
181
+ raise ArgumentError, "Cannot parse AS number from #{arg.class}"
182
+ end
183
+ end
184
+
185
+ # 解析字符串:支持 asplain 和 asdot 两种记法。
186
+ def parse_string(str)
187
+ str = str.strip
188
+ if str.include?(".")
189
+ parse_asdot(str)
190
+ else
191
+ parse_asplain(str)
192
+ end
193
+ end
194
+
195
+ # asplain:纯十进制整数串
196
+ def parse_asplain(str)
197
+ unless str.match?(/\A\d+\z/)
198
+ raise ArgumentError, "Invalid AS number: #{str}"
199
+ end
200
+ str.to_i
201
+ end
202
+
203
+ # asdot:高16位.低16位,两段各 0 – 65535
204
+ def parse_asdot(str)
205
+ unless str.match?(/\A\d+\.\d+\z/)
206
+ raise ArgumentError, "Invalid AS number: #{str}"
207
+ end
208
+ high, low = str.split(".")
209
+ high_int = high.to_i
210
+ low_int = low.to_i
211
+ unless (0..AS2_MAX).include?(high_int) && (0..AS2_MAX).include?(low_int)
212
+ raise ArgumentError, "AS dot segment out of range (0-65535): #{str}"
213
+ end
214
+ high_int * 65536 + low_int
215
+ end
216
+
217
+ # 校验数值在 0 – 2^32-1 内
218
+ def valid_range?
219
+ (0..AS4_MAX).include?(@number)
220
+ end
221
+ end
@@ -0,0 +1,281 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ =begin # MD
5
+ << MAC 地址格式 >>
6
+
7
+ | 分隔符 | 分组数 | 示例 | 说明 |
8
+ | ----- | ----- | ----------------------- | --------------- |
9
+ | - | 6 | 00-1A-2B-3C-4D-5E | Windows 常用 |
10
+ | : | 6 | 00:1A:2B:3C:4D:5E | Linux/Cisco 常用 |
11
+ | . | 3 | 001A.2B3C.4D5E | Cisco 点分格式 |
12
+ | - | 3 | 001A-2B3C-4D5E | 部分设备 3 段横杠 |
13
+ | 无 | - | 001A2B3C4D5E | 无分隔符 |
14
+
15
+ << 特殊位 >>
16
+
17
+ | 位 | 位置 | 说明 |
18
+ | ------------- | ----------------- | ----------------------------- |
19
+ | I/G 位 | 首字节 bit0 | 0=单播/个体, 1=组播 |
20
+ | U/L 位 | 首字节 bit1 | 0=全球分配(OUI), 1=本地分配 |
21
+
22
+ << EUI-64 >>
23
+
24
+ MAC 地址 → EUI-64:在 OUI(前3字节)和 NIC(后3字节)之间插入 FF:FE
25
+ 例:00-1A-2B-3C-4D-5E → 00:1A:2B:FF:FE:3C:4D:5E
26
+ IPv6 SLAAC 接口标识符需翻转 U/L 位
27
+ =end
28
+
29
+ # MAC 地址工具。
30
+ #
31
+ # 用法:
32
+ # mac = MACAddress.new("00:1A:2B:3C:4D:5E")
33
+ # mac = MAC.address("001A.2B3C.4D5E")
34
+ # mac = MAC.address("001A-2B3C-4D5E")
35
+ # mac = MAC.address(0x001A2B3C4D5E)
36
+ # mac = MAC.address([0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E])
37
+ #
38
+ # mac.to_s # → "00-1a-2b-3c-4d-5e"
39
+ # mac.to_hex(":", 6) # → "00:1a:2b:3c:4d:5e"
40
+ # mac.to_hex(".", 3) # → "001a.2b3c.4d5e"
41
+ # mac.oui # → "00-1a-2b"
42
+ # mac.multicast? # → false
43
+ # mac.locally_administered? # → false
44
+ # mac.to_eui64_s # → "00:1a:2b:ff:fe:3c:4d:5e"
45
+
46
+ class MacAddress
47
+ include Comparable
48
+
49
+ attr_reader :numbers, :number
50
+
51
+ MAC_MAX = 0xFFFFFFFFFFFF
52
+
53
+ # 从 String(带分隔符或无分隔符)、Array 或 Integer 构造。
54
+ #
55
+ # 字符串示例:
56
+ # "00-1A-2B-3C-4D-5E" 6 组(- / : 分隔)
57
+ # "001A.2B3C.4D5E" 3 组(. 分隔,Cisco 点分格式)
58
+ # "001A-2B3C-4D5E" 3 组(- 分隔,部分设备写法)
59
+ # "001A2B3C4D5E" 无分隔符
60
+ #
61
+ # 数组示例:
62
+ # ["00", "1A", "2B", "3C", "4D", "5E"] 6 段字符串
63
+ # ["001A", "2B3C", "4D5E"] 3 段字符串
64
+ # [0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E] 6 段整数
65
+ #
66
+ # 整数示例:
67
+ # 0x001A2B3C4D5E
68
+ def initialize(arg)
69
+ case arg
70
+ when String
71
+ sequence = detect_and_split(arg)
72
+ build_from_sequence(sequence)
73
+ when Array
74
+ build_from_sequence(arg)
75
+ when Integer
76
+ raise ArgumentError, "MAC out of range: #{arg}" unless (0..MAC_MAX).include?(arg)
77
+ @number = arg
78
+ @numbers = (0..5).map { |i| (arg >> ((5 - i) * 8)) & 0xFF }
79
+ else
80
+ raise ArgumentError, "Cannot parse MAC from #{arg.class}"
81
+ end
82
+ end
83
+
84
+ # ---- 输出格式 ----
85
+
86
+ def to_a
87
+ @numbers
88
+ end
89
+
90
+ # 带分隔符的十六进制串。groups 控制分组(6/3/2/1),separator 控制分隔符。
91
+ # to_hex("-", 6) → "00-1a-2b-3c-4d-5e"
92
+ # to_hex(":", 6) → "00:1a:2b:3c:4d:5e"
93
+ # to_hex(".", 3) → "001a.2b3c.4d5e"
94
+ # to_hex("", 1) → "001a2b3c4d5e"
95
+ def to_hex(separator = "-", groups = 6)
96
+ unless [1, 2, 3, 6].include?(groups)
97
+ raise ArgumentError, "Invalid groups: #{groups} (must be 1, 2, 3, or 6)"
98
+ end
99
+ slice_size = 6 / groups
100
+ @numbers.each_slice(slice_size).map do |slice|
101
+ slice.map { |n| "%02x" % n }.join
102
+ end.join(separator)
103
+ end
104
+
105
+ def to_s
106
+ to_hex("-", 6)
107
+ end
108
+
109
+ alias inspect to_s
110
+
111
+ def to_upcase(separator = "-", groups = 6)
112
+ to_hex(separator, groups).upcase
113
+ end
114
+
115
+ def to_downcase(separator = "-", groups = 6)
116
+ to_hex(separator, groups).downcase
117
+ end
118
+
119
+ # ---- 属性判定 ----
120
+
121
+ # I/G 位:首字节 bit0。0=单播,1=组播。
122
+ def multicast?
123
+ @numbers[0] & 0x01 != 0
124
+ end
125
+
126
+ alias group? multicast?
127
+
128
+ # U/L 位:首字节 bit1。1=本地分配,0=全球分配(OUI)。
129
+ def locally_administered?
130
+ @numbers[0] & 0x02 != 0
131
+ end
132
+
133
+ def universally_administered?
134
+ !locally_administered?
135
+ end
136
+
137
+ # 全 1 广播地址。
138
+ def broadcast?
139
+ @number == MAC_MAX
140
+ end
141
+
142
+ # 全 0 空地址。
143
+ def zero?
144
+ @number == 0
145
+ end
146
+
147
+ # OUI:前 3 字节组织唯一标识符。
148
+ def oui
149
+ @numbers[0..2].map { |n| "%02x" % n }.join("-")
150
+ end
151
+
152
+ # NIC:后 3 字节网卡标识。
153
+ def nic
154
+ @numbers[3..5].map { |n| "%02x" % n }.join("-")
155
+ end
156
+
157
+ # ---- EUI-64 / IPv6 SLAAC ----
158
+
159
+ # 转为 EUI-64 标识符(OUI 和 NIC 之间插入 FF:FE),返回 8 字节整数数组。
160
+ # MacAddress.new("00-1A-2B-3C-4D-5E").to_eui64
161
+ # → [0x00, 0x1A, 0x2B, 0xFF, 0xFE, 0x3C, 0x4D, 0x5E]
162
+ def to_eui64
163
+ @numbers[0..2] + [0xFF, 0xFE] + @numbers[3..5]
164
+ end
165
+
166
+ # EUI-64 格式字符串(默认冒号分隔)。
167
+ def to_eui64_s(separator = ":")
168
+ to_eui64.map { |n| "%02x" % n }.join(separator)
169
+ end
170
+
171
+ # 转为 IPv6 SLAAC 接口标识符(EUI-64 且 U/L 位翻转),返回 8 字节整数数组。
172
+ def to_interface_id
173
+ eui64 = to_eui64
174
+ eui64[0] ^= 0x02
175
+ eui64
176
+ end
177
+
178
+ def to_interface_id_s(separator = ":")
179
+ to_interface_id.map { |n| "%02x" % n }.join(separator)
180
+ end
181
+
182
+ # ---- Comparable ----
183
+
184
+ def <=>(other)
185
+ @number <=> other.number
186
+ end
187
+
188
+ def hash
189
+ @number.hash
190
+ end
191
+
192
+ def eql?(other)
193
+ other.is_a?(MacAddress) && @number == other.number
194
+ end
195
+
196
+ # ---- 兼容原接口 ----
197
+
198
+ # 原版 writing 方法:groups 控制分组数,splitter 控制分隔符。
199
+ def writing(groups = 3, splitter = "-")
200
+ groups = 6 if groups >= 6
201
+ to_hex(splitter, groups)
202
+ end
203
+
204
+ # ---- 类方法 ----
205
+
206
+ # 有效性检查,不抛异常。
207
+ def self.valid?(arg)
208
+ new(arg)
209
+ true
210
+ rescue ArgumentError
211
+ false
212
+ end
213
+
214
+ private
215
+
216
+ # 从字符串自动检测分隔符并拆分为段数组。
217
+ def detect_and_split(str)
218
+ str = str.strip
219
+ if str.match?(/[:.\-]/)
220
+ str.split(/[:.\-]/)
221
+ elsif str.match?(/\A[0-9a-fA-F]{12}\z/)
222
+ str.scan(/../)
223
+ else
224
+ raise ArgumentError, "Invalid MAC format: #{str}"
225
+ end
226
+ end
227
+
228
+ # 从段数组构建 @numbers(固定 6 字节整数)和 @number。
229
+ # 支持 3 段(每段 2 字节)和 6 段(每段 1 字节)。
230
+ def build_from_sequence(seq)
231
+ case seq.size
232
+ when 3
233
+ @numbers = seq.flat_map { |seg| split_two_byte_segment(seg) }
234
+ when 6
235
+ @numbers = seq.map { |seg| parse_segment(seg, 1) }
236
+ else
237
+ raise ArgumentError, "MAC segment count error: #{seq.size} (expected 3 or 6)"
238
+ end
239
+ compute_number
240
+ end
241
+
242
+ # 解析单段为指定字节数的整数,含范围校验。
243
+ def parse_segment(seg, bytes)
244
+ val = if seg.is_a?(String)
245
+ raise ArgumentError, "Invalid hex segment: #{seg}" unless seg.match?(/\A[0-9a-fA-F]+\z/)
246
+ seg.to_i(16)
247
+ else
248
+ seg.to_i
249
+ end
250
+ max = (1 << (bytes * 8)) - 1
251
+ unless (0..max).include?(val)
252
+ raise ArgumentError, "MAC segment out of range (0-#{max}): #{seg}"
253
+ end
254
+ val
255
+ end
256
+
257
+ # 解析 2 字节段,拆为高/低两个单字节。
258
+ def split_two_byte_segment(seg)
259
+ val = parse_segment(seg, 2)
260
+ [(val >> 8) & 0xFF, val & 0xFF]
261
+ end
262
+
263
+ def compute_number
264
+ @number = @numbers.map.with_index { |n, i| n << ((5 - i) * 8) }.sum
265
+ end
266
+ end
267
+
268
+ # MAC 统一入口模块。
269
+ #
270
+ # 用法:
271
+ # MAC.address("00:1A:2B:3C:4D:5E")
272
+ # MAC.address("001A.2B3C.4D5E")
273
+ # MAC.address(0x001A2B3C4D5E)
274
+ # MAC.address([0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E])
275
+ module MAC
276
+ module_function
277
+
278
+ def address(arg, _ = "-")
279
+ MacAddress.new(arg)
280
+ end
281
+ end
data/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NetworkInfraUtility
4
- VERSION = "0.2.0"
4
+ VERSION = "0.5.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: network-infra-utility
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt
@@ -51,12 +51,41 @@ dependencies:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
53
  version: '6.0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: thor
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.3'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.3'
68
+ - !ruby/object:Gem::Dependency
69
+ name: json
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '2.6'
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '2.6'
54
82
  description: 这是`gem:network-utility`的AIGC重编码版,提供了基于工具、服务、文档、兼容支持的多种网络应用基础设施。
55
83
  email:
56
84
  - matthrewchains@gmail.com
57
85
  - 18995691365@189.cn
58
86
  executables:
59
87
  - geo-api
88
+ - geo-doc
60
89
  - geo-get
61
90
  - geo-load
62
91
  extensions: []
@@ -69,23 +98,130 @@ files:
69
98
  - CHANGELOG.md
70
99
  - CODE_OF_CONDUCT.md
71
100
  - Gemfile
101
+ - Gemfile.lock
72
102
  - LICENSE.txt
73
103
  - README.md
74
104
  - Rakefile
75
105
  - bin/console
106
+ - bin/dns-query
76
107
  - bin/geo-api
108
+ - bin/geo-doc
77
109
  - bin/geo-get
78
110
  - bin/geo-load
79
111
  - bin/setup
112
+ - document/ASNum模块功能说明.md
113
+ - document/DNSQuery工具使用方法.md
114
+ - document/Geo命令工具使用方法.md
115
+ - document/IP模块功能说明.md
116
+ - document/MAC模块功能说明.md
117
+ - document/SSH连接客户端使用方法.md
80
118
  - network-infra-utility.gemspec
81
119
  - network.rb
82
120
  - service/geodb/GeoAPI.md
83
121
  - service/geodb/api.rb
84
122
  - service/geodb/config.ru
85
123
  - service/geodb/geodb.rb
124
+ - service/ssh/README.md
125
+ - service/ssh/bin/ssh-client
126
+ - service/ssh/design/SSH连接客户端功能需求文档.md
127
+ - service/ssh/design/SSH连接客户端详细设计文档.md
128
+ - service/ssh/design/SSH连接客户端软件设计文档.md
129
+ - service/ssh/ext/ssh_core/bin/ssh_core.cmd
130
+ - service/ssh/ext/ssh_core/config/sys.config
131
+ - service/ssh/ext/ssh_core/config/vm.args
132
+ - service/ssh/ext/ssh_core/local_deps/jsx/CHECKSUM
133
+ - service/ssh/ext/ssh_core/local_deps/jsx/LICENSE
134
+ - service/ssh/ext/ssh_core/local_deps/jsx/README.md
135
+ - service/ssh/ext/ssh_core/local_deps/jsx/VERSION
136
+ - service/ssh/ext/ssh_core/local_deps/jsx/contents.tar.gz
137
+ - service/ssh/ext/ssh_core/local_deps/jsx/metadata.config
138
+ - service/ssh/ext/ssh_core/local_deps/jsx/rebar.config
139
+ - service/ssh/ext/ssh_core/local_deps/jsx/rebar.lock
140
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/jsx.app.src
141
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/jsx.erl
142
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_config.erl
143
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_config.hrl
144
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_consult.erl
145
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_decoder.erl
146
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_encoder.erl
147
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_parser.erl
148
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_to_json.erl
149
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_to_term.erl
150
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_verify.erl
151
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx.erl
152
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_config.erl
153
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_config.hrl
154
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_consult.erl
155
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_decoder.erl
156
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_encoder.erl
157
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_parser.erl
158
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_to_json.erl
159
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_to_term.erl
160
+ - service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_verify.erl
161
+ - service/ssh/ext/ssh_core/rebar.config
162
+ - service/ssh/ext/ssh_core/rebar.lock
163
+ - service/ssh/ext/ssh_core/src/ssh_auth_engine.erl
164
+ - service/ssh/ext/ssh_core/src/ssh_channel_stm.erl
165
+ - service/ssh/ext/ssh_core/src/ssh_codec.erl
166
+ - service/ssh/ext/ssh_core/src/ssh_conn_sup.erl
167
+ - service/ssh/ext/ssh_core/src/ssh_conn_worker.erl
168
+ - service/ssh/ext/ssh_core/src/ssh_core.app.src
169
+ - service/ssh/ext/ssh_core/src/ssh_core_app.erl
170
+ - service/ssh/ext/ssh_core/src/ssh_core_sup.erl
171
+ - service/ssh/ext/ssh_core/src/ssh_infra_sup.erl
172
+ - service/ssh/ext/ssh_core/src/ssh_ipc.hrl
173
+ - service/ssh/ext/ssh_core/src/ssh_ipc_coalesce.erl
174
+ - service/ssh/ext/ssh_core/src/ssh_ipc_gateway.erl
175
+ - service/ssh/ext/ssh_core/src/ssh_ipc_proto.erl
176
+ - service/ssh/ext/ssh_core/src/ssh_jump_chain.erl
177
+ - service/ssh/ext/ssh_core/src/ssh_keepalive_mgr.erl
178
+ - service/ssh/ext/ssh_core/src/ssh_known_hosts_proxy.erl
179
+ - service/ssh/ext/ssh_core/src/ssh_port_fwd.erl
180
+ - service/ssh/ext/ssh_core/src/ssh_sftp_session.erl
181
+ - service/ssh/ext/ssh_core/src/ssh_sftp_sup.erl
182
+ - service/ssh/ext/ssh_core_rs/Cargo.lock
183
+ - service/ssh/ext/ssh_core_rs/Cargo.toml
184
+ - service/ssh/ext/ssh_core_rs/bin/ssh_core_rs
185
+ - service/ssh/ext/ssh_core_rs/bin/ssh_core_rs.cmd
186
+ - service/ssh/ext/ssh_core_rs/src/channel.rs
187
+ - service/ssh/ext/ssh_core_rs/src/coalesce.rs
188
+ - service/ssh/ext/ssh_core_rs/src/codec.rs
189
+ - service/ssh/ext/ssh_core_rs/src/conn.rs
190
+ - service/ssh/ext/ssh_core_rs/src/gateway.rs
191
+ - service/ssh/ext/ssh_core_rs/src/handler.rs
192
+ - service/ssh/ext/ssh_core_rs/src/keepalive.rs
193
+ - service/ssh/ext/ssh_core_rs/src/main.rs
194
+ - service/ssh/ext/ssh_core_rs/src/portfwd.rs
195
+ - service/ssh/ext/ssh_core_rs/src/proto.rs
196
+ - service/ssh/ext/ssh_core_rs/src/sftp.rs
197
+ - service/ssh/lib/network_infra_utility/ssh.rb
198
+ - service/ssh/lib/network_infra_utility/ssh/automation/macro_engine.rb
199
+ - service/ssh/lib/network_infra_utility/ssh/client.rb
200
+ - service/ssh/lib/network_infra_utility/ssh/config/schema.rb
201
+ - service/ssh/lib/network_infra_utility/ssh/config/settings.rb
202
+ - service/ssh/lib/network_infra_utility/ssh/config/store.rb
203
+ - service/ssh/lib/network_infra_utility/ssh/ipc/coalesce.rb
204
+ - service/ssh/lib/network_infra_utility/ssh/ipc/errors.rb
205
+ - service/ssh/lib/network_infra_utility/ssh/ipc/router.rb
206
+ - service/ssh/lib/network_infra_utility/ssh/ipc/transport.rb
207
+ - service/ssh/lib/network_infra_utility/ssh/security/host_key.rb
208
+ - service/ssh/lib/network_infra_utility/ssh/security/vault.rb
209
+ - service/ssh/lib/network_infra_utility/ssh/session/history.rb
210
+ - service/ssh/lib/network_infra_utility/ssh/session/manager.rb
211
+ - service/ssh/lib/network_infra_utility/ssh/session/session.rb
212
+ - service/ssh/lib/network_infra_utility/ssh/session/tree.rb
213
+ - service/ssh/lib/network_infra_utility/ssh/terminal/ansi_parser.rb
214
+ - service/ssh/lib/network_infra_utility/ssh/terminal/buffer.rb
215
+ - service/ssh/lib/network_infra_utility/ssh/terminal/emulator.rb
216
+ - service/ssh/lib/network_infra_utility/ssh/terminal/logger.rb
217
+ - service/ssh/lib/network_infra_utility/ssh/terminal/screen.rb
218
+ - service/ssh/lib/network_infra_utility/ssh/terminal/theme.rb
219
+ - service/ssh/lib/network_infra_utility/ssh/version.rb
220
+ - support/basic/as_num.rb
86
221
  - support/basic/ip.rb
87
222
  - support/basic/ipv4_address.rb
88
223
  - support/basic/ipv6_address.rb
224
+ - support/basic/mac_address.rb
89
225
  - version.rb
90
226
  homepage: https://github.com/ChenMeng1365/network-infra-utility
91
227
  licenses:
@@ -98,6 +234,7 @@ rdoc_options: []
98
234
  require_paths:
99
235
  - document
100
236
  - service
237
+ - service/ssh/lib
101
238
  - support
102
239
  - tool
103
240
  - "."