@@ -29,7 +29,11 @@ use std::ptr;
29
29
use std:: slice;
30
30
use std:: sync:: atomic;
31
31
32
+ use std:: net:: Ipv4Addr ;
33
+ use std:: net:: Ipv6Addr ;
32
34
use std:: net:: SocketAddr ;
35
+ use std:: net:: SocketAddrV4 ;
36
+ use std:: net:: SocketAddrV6 ;
33
37
34
38
#[ cfg( unix) ]
35
39
use std:: os:: unix:: io:: FromRawFd ;
@@ -42,6 +46,31 @@ use libc::sockaddr;
42
46
use libc:: ssize_t;
43
47
use libc:: timespec;
44
48
49
+ #[ cfg( not( windows) ) ]
50
+ use libc:: AF_INET ;
51
+ #[ cfg( windows) ]
52
+ use winapi:: shared:: ws2def:: AF_INET ;
53
+
54
+ #[ cfg( not( windows) ) ]
55
+ use libc:: AF_INET6 ;
56
+ #[ cfg( windows) ]
57
+ use winapi:: shared:: ws2def:: AF_INET6 ;
58
+
59
+ #[ cfg( not( windows) ) ]
60
+ use libc:: in_addr;
61
+ #[ cfg( windows) ]
62
+ use winapi:: shared:: inaddr:: IN_ADDR as in_addr;
63
+
64
+ #[ cfg( not( windows) ) ]
65
+ use libc:: in6_addr;
66
+ #[ cfg( windows) ]
67
+ use winapi:: shared:: in6addr:: IN6_ADDR as in6_addr;
68
+
69
+ #[ cfg( not( windows) ) ]
70
+ use libc:: sa_family_t;
71
+ #[ cfg( windows) ]
72
+ use winapi:: shared:: ws2def:: ADDRESS_FAMILY as sa_family_t;
73
+
45
74
#[ cfg( not( windows) ) ]
46
75
use libc:: sockaddr_in;
47
76
#[ cfg( windows) ]
@@ -62,15 +91,12 @@ use libc::c_int as socklen_t;
62
91
#[ cfg( not( windows) ) ]
63
92
use libc:: socklen_t;
64
93
65
- #[ cfg( not( windows) ) ]
66
- use libc:: AF_INET ;
67
94
#[ cfg( windows) ]
68
- use winapi:: shared:: ws2def:: AF_INET ;
69
-
70
- #[ cfg( not( windows) ) ]
71
- use libc:: AF_INET6 ;
95
+ use winapi:: shared:: in6addr:: in6_addr_u;
72
96
#[ cfg( windows) ]
73
- use winapi:: shared:: ws2def:: AF_INET6 ;
97
+ use winapi:: shared:: inaddr:: in_addr_S_un;
98
+ #[ cfg( windows) ]
99
+ use winapi:: shared:: ws2ipdef:: SOCKADDR_IN6_LH_u ;
74
100
75
101
use crate :: * ;
76
102
@@ -1259,54 +1285,155 @@ pub extern fn quiche_conn_send_quantum(conn: &mut Connection) -> size_t {
1259
1285
}
1260
1286
1261
1287
fn std_addr_from_c ( addr : & sockaddr , addr_len : socklen_t ) -> SocketAddr {
1262
- unsafe {
1263
- match addr. sa_family as i32 {
1264
- AF_INET => {
1265
- assert ! ( addr_len as usize == std:: mem:: size_of:: <sockaddr_in>( ) ) ;
1288
+ match addr. sa_family as i32 {
1289
+ AF_INET => {
1290
+ assert ! ( addr_len as usize == std:: mem:: size_of:: <sockaddr_in>( ) ) ;
1266
1291
1267
- SocketAddr :: V4 (
1268
- * ( addr as * const _ as * const sockaddr_in as * const _ ) ,
1269
- )
1270
- } ,
1292
+ let in4 = unsafe { * ( addr as * const _ as * const sockaddr_in ) } ;
1271
1293
1272
- AF_INET6 => {
1273
- assert ! ( addr_len as usize == std:: mem:: size_of:: <sockaddr_in6>( ) ) ;
1294
+ #[ cfg( not( windows) ) ]
1295
+ let ip_addr = Ipv4Addr :: from ( u32:: from_be ( in4. sin_addr . s_addr ) ) ;
1296
+ #[ cfg( windows) ]
1297
+ let ip_addr = {
1298
+ let ip_bytes = unsafe { in4. sin_addr . S_un . S_un_b ( ) } ;
1274
1299
1275
- SocketAddr :: V6 (
1276
- * ( addr as * const _ as * const sockaddr_in6 as * const _ ) ,
1277
- )
1278
- } ,
1300
+ Ipv4Addr :: from ( [
1301
+ ip_bytes. s_b1 ,
1302
+ ip_bytes. s_b2 ,
1303
+ ip_bytes. s_b3 ,
1304
+ ip_bytes. s_b4 ,
1305
+ ] )
1306
+ } ;
1279
1307
1280
- _ => unimplemented ! ( "unsupported address type" ) ,
1281
- }
1282
- }
1283
- }
1308
+ let port = u16:: from_be ( in4. sin_port ) ;
1284
1309
1285
- fn std_addr_to_c ( addr : & SocketAddr , out : & mut sockaddr_storage ) -> socklen_t {
1286
- unsafe {
1287
- match addr {
1288
- SocketAddr :: V4 ( addr) => {
1289
- let sa_len = std:: mem:: size_of :: < sockaddr_in > ( ) ;
1310
+ let out = SocketAddrV4 :: new ( ip_addr, port) ;
1311
+
1312
+ out. into ( )
1313
+ } ,
1290
1314
1291
- let src = addr as * const _ as * const u8 ;
1292
- let dst = out as * mut _ as * mut u8 ;
1315
+ AF_INET6 => {
1316
+ assert ! ( addr_len as usize == std :: mem :: size_of :: <sockaddr_in6> ( ) ) ;
1293
1317
1294
- std :: ptr :: copy_nonoverlapping ( src , dst , sa_len ) ;
1318
+ let in6 = unsafe { * ( addr as * const _ as * const sockaddr_in6 ) } ;
1295
1319
1296
- sa_len as socklen_t
1297
- } ,
1320
+ let ip_addr = Ipv6Addr :: from (
1321
+ #[ cfg( not( windows) ) ]
1322
+ in6. sin6_addr . s6_addr ,
1323
+ #[ cfg( windows) ]
1324
+ * unsafe { in6. sin6_addr . u . Byte ( ) } ,
1325
+ ) ;
1298
1326
1299
- SocketAddr :: V6 ( addr) => {
1300
- let sa_len = std:: mem:: size_of :: < sockaddr_in6 > ( ) ;
1327
+ let port = u16:: from_be ( in6. sin6_port ) ;
1301
1328
1302
- let src = addr as * const _ as * const u8 ;
1303
- let dst = out as * mut _ as * mut u8 ;
1329
+ #[ cfg( not( windows) ) ]
1330
+ let scope_id = in6. sin6_scope_id ;
1331
+ #[ cfg( windows) ]
1332
+ let scope_id = unsafe { * in6. u . sin6_scope_id ( ) } ;
1304
1333
1305
- std:: ptr:: copy_nonoverlapping ( src, dst, sa_len) ;
1334
+ let out =
1335
+ SocketAddrV6 :: new ( ip_addr, port, in6. sin6_flowinfo , scope_id) ;
1306
1336
1307
- sa_len as socklen_t
1308
- } ,
1309
- }
1337
+ out. into ( )
1338
+ } ,
1339
+
1340
+ _ => unimplemented ! ( "unsupported address type" ) ,
1341
+ }
1342
+ }
1343
+
1344
+ fn std_addr_to_c ( addr : & SocketAddr , out : & mut sockaddr_storage ) -> socklen_t {
1345
+ let sin_port = addr. port ( ) . to_be ( ) ;
1346
+
1347
+ match addr {
1348
+ SocketAddr :: V4 ( addr) => unsafe {
1349
+ let sa_len = std:: mem:: size_of :: < sockaddr_in > ( ) ;
1350
+ let out_in = out as * mut _ as * mut sockaddr_in ;
1351
+
1352
+ let s_addr = u32:: from_ne_bytes ( addr. ip ( ) . octets ( ) ) ;
1353
+
1354
+ #[ cfg( not( windows) ) ]
1355
+ let sin_addr = in_addr { s_addr } ;
1356
+ #[ cfg( windows) ]
1357
+ let sin_addr = {
1358
+ let mut s_un = std:: mem:: zeroed :: < in_addr_S_un > ( ) ;
1359
+ * s_un. S_addr_mut ( ) = s_addr;
1360
+ in_addr { S_un : s_un }
1361
+ } ;
1362
+
1363
+ * out_in = sockaddr_in {
1364
+ sin_family : AF_INET as sa_family_t ,
1365
+
1366
+ sin_addr,
1367
+
1368
+ #[ cfg( any(
1369
+ target_os = "macos" ,
1370
+ target_os = "ios" ,
1371
+ target_os = "watchos" ,
1372
+ target_os = "freebsd" ,
1373
+ target_os = "dragonfly" ,
1374
+ target_os = "openbsd" ,
1375
+ target_os = "netbsd"
1376
+ ) ) ]
1377
+ sin_len : sa_len as u8 ,
1378
+
1379
+ sin_port,
1380
+
1381
+ sin_zero : std:: mem:: zeroed ( ) ,
1382
+ } ;
1383
+
1384
+ sa_len as socklen_t
1385
+ } ,
1386
+
1387
+ SocketAddr :: V6 ( addr) => unsafe {
1388
+ let sa_len = std:: mem:: size_of :: < sockaddr_in6 > ( ) ;
1389
+ let out_in6 = out as * mut _ as * mut sockaddr_in6 ;
1390
+
1391
+ #[ cfg( not( windows) ) ]
1392
+ let sin6_addr = in6_addr {
1393
+ s6_addr : addr. ip ( ) . octets ( ) ,
1394
+ } ;
1395
+ #[ cfg( windows) ]
1396
+ let sin6_addr = {
1397
+ let mut u = std:: mem:: zeroed :: < in6_addr_u > ( ) ;
1398
+ * u. Byte_mut ( ) = addr. ip ( ) . octets ( ) ;
1399
+ in6_addr { u }
1400
+ } ;
1401
+
1402
+ #[ cfg( windows) ]
1403
+ let u = {
1404
+ let mut u = std:: mem:: zeroed :: < SOCKADDR_IN6_LH_u > ( ) ;
1405
+ * u. sin6_scope_id_mut ( ) = addr. scope_id ( ) ;
1406
+ u
1407
+ } ;
1408
+
1409
+ * out_in6 = sockaddr_in6 {
1410
+ sin6_family : AF_INET6 as sa_family_t ,
1411
+
1412
+ sin6_addr,
1413
+
1414
+ #[ cfg( any(
1415
+ target_os = "macos" ,
1416
+ target_os = "ios" ,
1417
+ target_os = "watchos" ,
1418
+ target_os = "freebsd" ,
1419
+ target_os = "dragonfly" ,
1420
+ target_os = "openbsd" ,
1421
+ target_os = "netbsd"
1422
+ ) ) ]
1423
+ sin6_len : sa_len as u8 ,
1424
+
1425
+ sin6_port : sin_port,
1426
+
1427
+ sin6_flowinfo : addr. flowinfo ( ) ,
1428
+
1429
+ #[ cfg( not( windows) ) ]
1430
+ sin6_scope_id : addr. scope_id ( ) ,
1431
+ #[ cfg( windows) ]
1432
+ u,
1433
+ } ;
1434
+
1435
+ sa_len as socklen_t
1436
+ } ,
1310
1437
}
1311
1438
}
1312
1439
@@ -1323,3 +1450,108 @@ fn std_time_to_c(_time: &std::time::Instant, out: &mut timespec) {
1323
1450
out. tv_sec = 0 ;
1324
1451
out. tv_nsec = 0 ;
1325
1452
}
1453
+
1454
+ #[ cfg( test) ]
1455
+ mod tests {
1456
+ use super :: * ;
1457
+
1458
+ #[ cfg( windows) ]
1459
+ use winapi:: um:: ws2tcpip:: inet_ntop;
1460
+
1461
+ #[ test]
1462
+ fn addr_v4 ( ) {
1463
+ let addr = "127.0.0.1:8080" . parse ( ) . unwrap ( ) ;
1464
+
1465
+ let mut out: sockaddr_storage = unsafe { std:: mem:: zeroed ( ) } ;
1466
+
1467
+ assert_eq ! (
1468
+ std_addr_to_c( & addr, & mut out) ,
1469
+ std:: mem:: size_of:: <sockaddr_in>( ) as socklen_t
1470
+ ) ;
1471
+
1472
+ let s = std:: ffi:: CString :: new ( "ddd.ddd.ddd.ddd" ) . unwrap ( ) ;
1473
+
1474
+ let s = unsafe {
1475
+ let in_addr = & out as * const _ as * const sockaddr_in ;
1476
+ assert_eq ! ( u16 :: from_be( ( * in_addr) . sin_port) , addr. port( ) ) ;
1477
+
1478
+ let dst = s. into_raw ( ) ;
1479
+
1480
+ inet_ntop (
1481
+ AF_INET ,
1482
+ & ( ( * in_addr) . sin_addr ) as * const _ as * const c_void ,
1483
+ dst,
1484
+ 16 ,
1485
+ ) ;
1486
+
1487
+ std:: ffi:: CString :: from_raw ( dst) . into_string ( ) . unwrap ( )
1488
+ } ;
1489
+
1490
+ assert_eq ! ( s, "127.0.0.1" ) ;
1491
+
1492
+ let addr = unsafe {
1493
+ std_addr_from_c (
1494
+ & * ( & out as * const _ as * const sockaddr ) ,
1495
+ std:: mem:: size_of :: < sockaddr_in > ( ) as socklen_t ,
1496
+ )
1497
+ } ;
1498
+
1499
+ assert_eq ! ( addr, "127.0.0.1:8080" . parse( ) . unwrap( ) ) ;
1500
+ }
1501
+
1502
+ #[ test]
1503
+ fn addr_v6 ( ) {
1504
+ let addr = "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8080"
1505
+ . parse ( )
1506
+ . unwrap ( ) ;
1507
+
1508
+ let mut out: sockaddr_storage = unsafe { std:: mem:: zeroed ( ) } ;
1509
+
1510
+ assert_eq ! (
1511
+ std_addr_to_c( & addr, & mut out) ,
1512
+ std:: mem:: size_of:: <sockaddr_in6>( ) as socklen_t
1513
+ ) ;
1514
+
1515
+ let s = std:: ffi:: CString :: new ( "dddd:dddd:dddd:dddd:dddd:dddd:dddd:dddd" )
1516
+ . unwrap ( ) ;
1517
+
1518
+ let s = unsafe {
1519
+ let in6_addr = & out as * const _ as * const sockaddr_in6 ;
1520
+ assert_eq ! ( u16 :: from_be( ( * in6_addr) . sin6_port) , addr. port( ) ) ;
1521
+
1522
+ let dst = s. into_raw ( ) ;
1523
+
1524
+ inet_ntop (
1525
+ AF_INET6 ,
1526
+ & ( ( * in6_addr) . sin6_addr ) as * const _ as * const c_void ,
1527
+ dst,
1528
+ 45 ,
1529
+ ) ;
1530
+
1531
+ std:: ffi:: CString :: from_raw ( dst) . into_string ( ) . unwrap ( )
1532
+ } ;
1533
+
1534
+ assert_eq ! ( s, "2001:db8:85a3::8a2e:370:7334" ) ;
1535
+
1536
+ let addr = unsafe {
1537
+ std_addr_from_c (
1538
+ & * ( & out as * const _ as * const sockaddr ) ,
1539
+ std:: mem:: size_of :: < sockaddr_in6 > ( ) as socklen_t ,
1540
+ )
1541
+ } ;
1542
+
1543
+ assert_eq ! (
1544
+ addr,
1545
+ "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8080"
1546
+ . parse( )
1547
+ . unwrap( )
1548
+ ) ;
1549
+ }
1550
+
1551
+ #[ cfg( not( windows) ) ]
1552
+ extern {
1553
+ fn inet_ntop (
1554
+ af : c_int , src : * const c_void , dst : * mut c_char , size : socklen_t ,
1555
+ ) -> * mut c_char ;
1556
+ }
1557
+ }
0 commit comments