@@ -160,33 +160,136 @@ impl RecvSource {
160
160
address,
161
161
port,
162
162
} => {
163
- let address = address
164
- . map ( |x| {
165
- for s in ( x, 0 ) . to_socket_addrs ( ) . unwrap ( ) {
166
- if let SocketAddr :: V4 ( sv4) = s {
167
- return * sv4. ip ( ) ;
163
+ // Handle address resolution - match C behavior more closely
164
+ let address = address. map ( |x| {
165
+ // First try to parse as direct IP address
166
+ if let Ok ( ip) = x. parse :: < Ipv4Addr > ( ) {
167
+ return ip;
168
+ }
169
+
170
+ // Handle localhost specifically
171
+ if x == "localhost" {
172
+ return Ipv4Addr :: LOCALHOST ;
173
+ }
174
+
175
+ // Try DNS resolution with more lenient approach
176
+ match ( x, 0 ) . to_socket_addrs ( ) {
177
+ Ok ( addrs) => {
178
+ for s in addrs {
179
+ match s {
180
+ SocketAddr :: V4 ( sv4) => return * sv4. ip ( ) ,
181
+ SocketAddr :: V6 ( sv6) => {
182
+ // Convert IPv6 localhost to IPv4
183
+ if sv6. ip ( ) . is_loopback ( ) {
184
+ return Ipv4Addr :: LOCALHOST ;
185
+ }
186
+ // Try IPv4-mapped IPv6
187
+ if let Some ( ipv4) = sv6. ip ( ) . to_ipv4_mapped ( ) {
188
+ return ipv4;
189
+ }
190
+ }
191
+ }
168
192
}
193
+ // If we get here, no suitable address was found
194
+ fatal ! ( cause = ExitCause :: Failure ; "Could not resolve udp address to IPv4" )
195
+ } ,
196
+ Err ( _) => {
197
+ fatal ! ( cause = ExitCause :: Failure ; "Could not resolve udp address" )
169
198
}
170
- fatal ! ( cause = ExitCause :: Failure ; "Could not resolve udp address" )
171
- } )
172
- . unwrap_or ( Ipv4Addr :: UNSPECIFIED ) ;
199
+ }
200
+ } ) . unwrap_or ( Ipv4Addr :: UNSPECIFIED ) ;
173
201
202
+ // Handle source resolution - don't try to resolve hostnames with ports
174
203
let source = source. map ( |x| {
175
- for s in ( x, 0 ) . to_socket_addrs ( ) . unwrap ( ) {
176
- if let SocketAddr :: V4 ( sv4) = s {
177
- return * sv4. ip ( ) ;
204
+ // Check if this looks like hostname:port format (which is invalid for source)
205
+ if x. contains ( ':' ) {
206
+ info ! (
207
+ "Warning: Source '{}' contains port - this should be hostname only\n " ,
208
+ x
209
+ ) ;
210
+ // Try to extract just the hostname part
211
+ if let Some ( hostname) = x. split ( ':' ) . next ( ) {
212
+ info ! ( "Extracting hostname '{}' from '{}'\n " , hostname, x) ;
213
+ return resolve_hostname_to_ipv4 ( hostname) ;
178
214
}
179
215
}
180
- fatal ! ( cause = ExitCause :: Failure ; "Could not resolve udp source" )
216
+
217
+ resolve_hostname_to_ipv4 ( x)
181
218
} ) ;
182
219
220
+ // Helper function to resolve hostname to IPv4
221
+ fn resolve_hostname_to_ipv4 ( hostname : & str ) -> Ipv4Addr {
222
+ // First try to parse as direct IP address
223
+ if let Ok ( ip) = hostname. parse :: < Ipv4Addr > ( ) {
224
+ info ! ( "Source address: {}\n " , ip) ;
225
+ return ip;
226
+ }
227
+
228
+ // Handle localhost specifically
229
+ if hostname == "localhost" {
230
+ info ! ( "Source address: {}\n " , Ipv4Addr :: LOCALHOST ) ;
231
+ return Ipv4Addr :: LOCALHOST ;
232
+ }
233
+
234
+ // Try DNS resolution
235
+ match ( hostname, 0 ) . to_socket_addrs ( ) {
236
+ Ok ( addrs) => {
237
+ for s in addrs {
238
+ info ! ( "Resolved address: {}\n " , s) ;
239
+ match s {
240
+ SocketAddr :: V4 ( sv4) => {
241
+ info ! ( "Source address: {}\n " , sv4. ip( ) ) ;
242
+ return * sv4. ip ( ) ;
243
+ }
244
+ SocketAddr :: V6 ( sv6) => {
245
+ // Convert IPv6 localhost to IPv4
246
+ if sv6. ip ( ) . is_loopback ( ) {
247
+ info ! (
248
+ "Source address: {} (converted from IPv6)\n " ,
249
+ Ipv4Addr :: LOCALHOST
250
+ ) ;
251
+ return Ipv4Addr :: LOCALHOST ;
252
+ }
253
+ // Try IPv4-mapped IPv6
254
+ if let Some ( ipv4) = sv6. ip ( ) . to_ipv4_mapped ( ) {
255
+ info ! (
256
+ "Source address: {} (converted from IPv6)\n " ,
257
+ ipv4
258
+ ) ;
259
+ return ipv4;
260
+ }
261
+ }
262
+ }
263
+ }
264
+ // If we get here, no suitable address was found
265
+ info ! (
266
+ "Warning: Only IPv6 addresses found for {}, but IPv4 required\n " ,
267
+ hostname
268
+ ) ;
269
+ fatal ! ( cause = ExitCause :: Failure ; "Could not resolve udp source to IPv4" )
270
+ }
271
+ Err ( e) => {
272
+ info ! ( "DNS resolution failed for {}: {}\n " , hostname, e) ;
273
+ fatal ! ( cause = ExitCause :: Failure ; "Could not resolve udp source" )
274
+ }
275
+ }
276
+ }
277
+
278
+ info ! (
279
+ "Source: {}\n " ,
280
+ source
281
+ . map( |s| s. to_string( ) )
282
+ . unwrap_or_else( || "None" . to_string( ) )
283
+ ) ;
284
+ info ! ( "Source port: {}\n " , port) ;
285
+
183
286
let socket = Socket :: new ( Domain :: IPV4 , Type :: DGRAM , None ) . unwrap_or_else (
184
287
|_| fatal ! ( cause = ExitCause :: Failure ; "Socket creation error" ) ,
185
288
) ;
186
289
187
290
if address. is_multicast ( ) {
188
291
socket. set_reuse_address ( true ) . unwrap_or_else ( |_| {
189
- info ! ( "Cannot not set reuse address\n " ) ;
292
+ info ! ( "Cannot set reuse address\n " ) ;
190
293
} ) ;
191
294
}
192
295
0 commit comments