@@ -26,7 +26,11 @@ public IEnumerable<string> ExpandCidr(string cidr)
2626 {
2727 if ( cidr . Contains ( ":" ) ) // IPv6 CIDR
2828 {
29- return ExpandCidrIPv6 ( cidr ) ;
29+ foreach ( var ip in ExpandCidrIPv6 ( cidr ) )
30+ {
31+ yield return ip ;
32+ }
33+ yield break ;
3034 }
3135
3236 Match match = CidrRegex . Match ( cidr ) ;
@@ -71,20 +75,22 @@ public IEnumerable<string> ExpandCidr(string cidr)
7175 }
7276
7377 /// <summary>
74- /// Expand IPv6 CIDR into addresses (limited to /128 or /127 or /64 to avoid flooding)
78+ /// Expand IPv6 CIDR into addresses (limited to /128, /127, or /64 to avoid flooding)
7579 /// </summary>
7680 private IEnumerable < string > ExpandCidrIPv6 ( string cidr )
7781 {
82+ var result = new List < string > ( ) ;
83+
7884 try
7985 {
8086 string [ ] parts = cidr . Split ( '/' ) ;
8187 if ( parts . Length != 2 )
8288 {
8389 _logger . LogWarning ( "Invalid IPv6 CIDR format: {Cidr}" , cidr ) ;
84- yield break ;
90+ return result ;
8591 }
8692
87- // Check for zone index (e.g., fe80::1%3)
93+ // Handle zone index
8894 string hostPart = parts [ 0 ] ;
8995 string ? zoneIndex = null ;
9096 if ( hostPart . Contains ( '%' ) )
@@ -94,35 +100,43 @@ private IEnumerable<string> ExpandCidrIPv6(string cidr)
94100 zoneIndex = hostSplit [ 1 ] ;
95101 }
96102
97- if ( ! IPAddress . TryParse ( hostPart , out var ip ) ) yield break ;
98- if ( ip . AddressFamily != AddressFamily . InterNetworkV6 ) yield break ;
103+ if ( ! IPAddress . TryParse ( hostPart , out var ip ) || ip . AddressFamily != AddressFamily . InterNetworkV6 )
104+ return result ;
99105
100- int prefix = int . Parse ( parts [ 1 ] ) ;
106+ if ( ! int . TryParse ( parts [ 1 ] , out int prefix ) )
107+ return result ;
108+
109+ string ApplyZone ( string address ) => zoneIndex != null ? $ "{ address } %{ zoneIndex } " : address ;
101110
102111 if ( prefix == 128 )
103- yield return zoneIndex != null ? $ "{ ip } %{ zoneIndex } " : ip . ToString ( ) ;
112+ {
113+ result . Add ( ApplyZone ( ip . ToString ( ) ) ) ;
114+ }
104115 else if ( prefix == 127 )
105116 {
106117 byte [ ] bytes = ip . GetAddressBytes ( ) ;
107- yield return zoneIndex != null ? $ " { ip } % { zoneIndex } " : ip . ToString ( ) ;
118+ result . Add ( ApplyZone ( ip . ToString ( ) ) ) ;
108119
120+ // Flip last bit for second address
109121 bytes [ 15 ] |= 1 ;
110122 var ip2 = new IPAddress ( bytes ) ;
111- yield return zoneIndex != null ? $ " { ip2 } % { zoneIndex } " : ip2 . ToString ( ) ;
123+ result . Add ( ApplyZone ( ip2 . ToString ( ) ) ) ;
112124 }
113125 else if ( prefix == 64 )
114- yield return zoneIndex != null ? $ "{ ip } %{ zoneIndex } " : ip . ToString ( ) ;
126+ {
127+ result . Add ( ApplyZone ( ip . ToString ( ) ) ) ;
128+ }
115129 else
116130 {
117- _logger . LogWarning (
118- "Skipping IPv6 CIDR {Cidr} with prefix /{Prefix} to avoid massive expansion" ,
119- cidr , prefix ) ;
131+ _logger . LogWarning ( "Skipping IPv6 CIDR {Cidr} with prefix /{Prefix}" , cidr , prefix ) ;
120132 }
121133 }
122134 catch ( Exception ex )
123135 {
124136 _logger . LogWarning ( ex , "Failed to expand IPv6 CIDR: {Cidr}" , cidr ) ;
125137 }
138+
139+ return result ;
126140 }
127141
128142 public IEnumerable < string > ExpandWildcard ( string wildcard , int startRange = 1 , int endRange = 254 )
@@ -154,7 +168,13 @@ public IEnumerable<string> ExpandWildcard(string wildcard, int startRange = 1, i
154168 /// Expands a single IPv6 host into compressed (::) and full (xxxx:xxxx:....) forms.
155169 /// Handles optional zone index.
156170 /// </summary>
157- private IEnumerable < string > ExpandIPv6Host ( string host )
171+ public enum IPv6Format
172+ {
173+ Compressed ,
174+ Full
175+ }
176+
177+ private IEnumerable < string > ExpandIPv6Host ( string host , IPv6Format format = IPv6Format . Compressed )
158178 {
159179 string hostPart = host ;
160180 string ? zoneIndex = null ;
@@ -169,27 +189,25 @@ private IEnumerable<string> ExpandIPv6Host(string host)
169189 if ( ! IPAddress . TryParse ( hostPart , out var ip ) ) yield break ;
170190 if ( ip . AddressFamily != AddressFamily . InterNetworkV6 ) yield break ;
171191
172- // Compressed form
173192 string compressed = ip . ToString ( ) ;
174193
175194 // Full form (always 8 groups of 4 hex digits)
176195 string full = string . Join ( ":" , Enumerable . Range ( 0 , 8 )
177196 . Select ( i => ( ( ushort ) ( ( ip . GetAddressBytes ( ) [ i * 2 ] << 8 ) |
178- ip . GetAddressBytes ( ) [ i * 2 + 1 ] ) ) . ToString ( "x4" ) ) ) ;
197+ ip . GetAddressBytes ( ) [ i * 2 + 1 ] ) ) . ToString ( "x4" ) ) ) ;
198+
199+ string ApplyZone ( string addr ) => zoneIndex != null ? $ "{ addr } %{ zoneIndex } " : addr ;
179200
180- if ( zoneIndex != null )
201+ if ( format == IPv6Format . Compressed )
181202 {
182- yield return $ "{ compressed } %{ zoneIndex } ";
183- yield return $ "{ full } %{ zoneIndex } ";
203+ yield return ApplyZone ( compressed ) ;
184204 }
185- else
205+ else if ( format == IPv6Format . Full )
186206 {
187- yield return compressed ;
188- yield return full ;
207+ yield return ApplyZone ( full ) ;
189208 }
190209 }
191210
192-
193211 public async Task < IEnumerable < string > > ResolveHostnameAsync ( string hostname , CancellationToken cancellationToken = default )
194212 {
195213 try
0 commit comments