@@ -5,6 +5,8 @@ use std::{fmt, hash, mem, net, ptr};
5
5
use std:: ffi:: OsStr ;
6
6
use std:: path:: Path ;
7
7
use std:: os:: unix:: ffi:: OsStrExt ;
8
+ #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
9
+ use :: sys:: socket:: addr:: netlink:: NetlinkAddr ;
8
10
9
11
// TODO: uncomment out IpAddr functions: rust-lang/rfcs#988
10
12
@@ -14,12 +16,24 @@ use std::os::unix::ffi::OsStrExt;
14
16
*
15
17
*/
16
18
19
+ #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
20
+ #[ derive( Debug , Copy , Clone ) ]
21
+ #[ repr( C ) ]
22
+ pub struct sockaddr_nl {
23
+ pub nl_family : sa_family_t ,
24
+ nl_pad : libc:: c_ushort ,
25
+ pub nl_pid : u32 ,
26
+ pub nl_groups : u32
27
+ }
28
+
17
29
#[ repr( i32 ) ]
18
30
#[ derive( Copy , Clone , PartialEq , Eq , Debug , Hash ) ]
19
31
pub enum AddressFamily {
20
32
Unix = consts:: AF_UNIX ,
21
33
Inet = consts:: AF_INET ,
22
34
Inet6 = consts:: AF_INET6 ,
35
+ #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
36
+ Netlink = consts:: AF_NETLINK ,
23
37
}
24
38
25
39
#[ derive( Copy ) ]
@@ -449,7 +463,9 @@ impl fmt::Display for UnixAddr {
449
463
#[ derive( Copy ) ]
450
464
pub enum SockAddr {
451
465
Inet ( InetAddr ) ,
452
- Unix ( UnixAddr )
466
+ Unix ( UnixAddr ) ,
467
+ #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
468
+ Netlink ( NetlinkAddr )
453
469
}
454
470
455
471
impl SockAddr {
@@ -461,11 +477,18 @@ impl SockAddr {
461
477
Ok ( SockAddr :: Unix ( try!( UnixAddr :: new ( path) ) ) )
462
478
}
463
479
480
+ #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
481
+ pub fn new_netlink ( pid : u32 , groups : u32 ) -> SockAddr {
482
+ SockAddr :: Netlink ( NetlinkAddr :: new ( pid, groups) )
483
+ }
484
+
464
485
pub fn family ( & self ) -> AddressFamily {
465
486
match * self {
466
487
SockAddr :: Inet ( InetAddr :: V4 ( ..) ) => AddressFamily :: Inet ,
467
488
SockAddr :: Inet ( InetAddr :: V6 ( ..) ) => AddressFamily :: Inet6 ,
468
489
SockAddr :: Unix ( ..) => AddressFamily :: Unix ,
490
+ #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
491
+ SockAddr :: Netlink ( ..) => AddressFamily :: Netlink ,
469
492
}
470
493
}
471
494
@@ -478,6 +501,8 @@ impl SockAddr {
478
501
SockAddr :: Inet ( InetAddr :: V4 ( ref addr) ) => ( mem:: transmute ( addr) , mem:: size_of :: < libc:: sockaddr_in > ( ) as libc:: socklen_t ) ,
479
502
SockAddr :: Inet ( InetAddr :: V6 ( ref addr) ) => ( mem:: transmute ( addr) , mem:: size_of :: < libc:: sockaddr_in6 > ( ) as libc:: socklen_t ) ,
480
503
SockAddr :: Unix ( UnixAddr ( ref addr, len) ) => ( mem:: transmute ( addr) , ( len + mem:: size_of :: < libc:: sa_family_t > ( ) ) as libc:: socklen_t ) ,
504
+ #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
505
+ SockAddr :: Netlink ( NetlinkAddr ( ref sa) ) => ( mem:: transmute ( sa) , mem:: size_of :: < sockaddr_nl > ( ) as libc:: socklen_t ) ,
481
506
}
482
507
}
483
508
}
@@ -491,6 +516,10 @@ impl PartialEq for SockAddr {
491
516
( SockAddr :: Unix ( ref a) , SockAddr :: Unix ( ref b) ) => {
492
517
a == b
493
518
}
519
+ #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
520
+ ( SockAddr :: Netlink ( ref a) , SockAddr :: Netlink ( ref b) ) => {
521
+ a == b
522
+ }
494
523
_ => false ,
495
524
}
496
525
}
@@ -504,6 +533,8 @@ impl hash::Hash for SockAddr {
504
533
match * self {
505
534
SockAddr :: Inet ( ref a) => a. hash ( s) ,
506
535
SockAddr :: Unix ( ref a) => a. hash ( s) ,
536
+ #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
537
+ SockAddr :: Netlink ( ref a) => a. hash ( s) ,
507
538
}
508
539
}
509
540
}
@@ -519,6 +550,64 @@ impl fmt::Display for SockAddr {
519
550
match * self {
520
551
SockAddr :: Inet ( ref inet) => inet. fmt ( f) ,
521
552
SockAddr :: Unix ( ref unix) => unix. fmt ( f) ,
553
+ #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
554
+ SockAddr :: Netlink ( ref nl) => nl. fmt ( f) ,
555
+ }
556
+ }
557
+ }
558
+
559
+ #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
560
+ pub mod netlink {
561
+ use :: sys:: socket:: addr:: { AddressFamily , sockaddr_nl} ;
562
+ use libc:: sa_family_t;
563
+ use std:: { fmt, hash} ;
564
+
565
+ #[ derive( Copy ) ]
566
+ pub struct NetlinkAddr ( pub sockaddr_nl ) ;
567
+
568
+ impl NetlinkAddr {
569
+ pub fn new ( pid : u32 , groups : u32 ) -> NetlinkAddr {
570
+ NetlinkAddr ( sockaddr_nl {
571
+ nl_family : AddressFamily :: Netlink as sa_family_t ,
572
+ nl_pad : 0 ,
573
+ nl_pid : pid,
574
+ nl_groups : groups,
575
+ } )
576
+ }
577
+
578
+ pub fn pid ( & self ) -> u32 {
579
+ self . 0 . nl_pid
580
+ }
581
+
582
+ pub fn groups ( & self ) -> u32 {
583
+ self . 0 . nl_groups
584
+ }
585
+ }
586
+
587
+ impl PartialEq for NetlinkAddr {
588
+ fn eq ( & self , other : & NetlinkAddr ) -> bool {
589
+ self . 0 . nl_pid == other. 0 . nl_pid && self . 0 . nl_groups == self . 0 . nl_groups
590
+ }
591
+ }
592
+
593
+ impl Eq for NetlinkAddr {
594
+ }
595
+
596
+ impl hash:: Hash for NetlinkAddr {
597
+ fn hash < H : hash:: Hasher > ( & self , s : & mut H ) {
598
+ ( self . 0 . nl_family , self . 0 . nl_pid , self . 0 . nl_groups ) . hash ( s)
599
+ }
600
+ }
601
+
602
+ impl Clone for NetlinkAddr {
603
+ fn clone ( & self ) -> NetlinkAddr {
604
+ * self
605
+ }
606
+ }
607
+
608
+ impl fmt:: Display for NetlinkAddr {
609
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
610
+ write ! ( f, "pid: {} groups: {}" , self . pid( ) , self . groups( ) )
522
611
}
523
612
}
524
613
}
0 commit comments