9
9
// except according to those terms.
10
10
11
11
use fs:: File ;
12
- use io:: { Error , Result , Read } ;
12
+ use io:: { Error , Read , self } ;
13
13
use iter:: Iterator ;
14
14
use net:: { Ipv4Addr , SocketAddr , SocketAddrV4 } ;
15
15
use str:: FromStr ;
16
16
use string:: { String , ToString } ;
17
17
use sys:: syscall:: EINVAL ;
18
18
use time:: { self , Duration } ;
19
19
use vec:: { IntoIter , Vec } ;
20
+ use convert:: { TryFrom , TryInto } ;
20
21
21
22
use self :: dns:: { Dns , DnsQuery } ;
22
23
@@ -29,7 +30,13 @@ mod dns;
29
30
mod tcp;
30
31
mod udp;
31
32
32
- pub struct LookupHost ( IntoIter < SocketAddr > ) ;
33
+ pub struct LookupHost ( IntoIter < SocketAddr > , u16 ) ;
34
+
35
+ impl LookupHost {
36
+ pub fn port ( & self ) -> u16 {
37
+ self . 1
38
+ }
39
+ }
33
40
34
41
impl Iterator for LookupHost {
35
42
type Item = SocketAddr ;
@@ -38,65 +45,93 @@ impl Iterator for LookupHost {
38
45
}
39
46
}
40
47
41
- pub fn lookup_host ( host : & str ) -> Result < LookupHost > {
42
- let mut ip_string = String :: new ( ) ;
43
- File :: open ( "/etc/net/ip" ) ?. read_to_string ( & mut ip_string) ?;
44
- let ip: Vec < u8 > = ip_string. trim ( ) . split ( '.' ) . map ( |part| part. parse :: < u8 > ( )
45
- . unwrap_or ( 0 ) ) . collect ( ) ;
46
-
47
- let mut dns_string = String :: new ( ) ;
48
- File :: open ( "/etc/net/dns" ) ?. read_to_string ( & mut dns_string) ?;
49
- let dns: Vec < u8 > = dns_string. trim ( ) . split ( '.' ) . map ( |part| part. parse :: < u8 > ( )
50
- . unwrap_or ( 0 ) ) . collect ( ) ;
51
-
52
- if ip. len ( ) == 4 && dns. len ( ) == 4 {
53
- let time = time:: SystemTime :: now ( ) . duration_since ( time:: UNIX_EPOCH ) . unwrap ( ) ;
54
- let tid = ( time. subsec_nanos ( ) >> 16 ) as u16 ;
55
-
56
- let packet = Dns {
57
- transaction_id : tid,
58
- flags : 0x0100 ,
59
- queries : vec ! [ DnsQuery {
60
- name: host. to_string( ) ,
61
- q_type: 0x0001 ,
62
- q_class: 0x0001 ,
63
- } ] ,
64
- answers : vec ! [ ]
65
- } ;
66
-
67
- let packet_data = packet. compile ( ) ;
68
-
69
- let my_ip = Ipv4Addr :: new ( ip[ 0 ] , ip[ 1 ] , ip[ 2 ] , ip[ 3 ] ) ;
70
- let dns_ip = Ipv4Addr :: new ( dns[ 0 ] , dns[ 1 ] , dns[ 2 ] , dns[ 3 ] ) ;
71
- let socket = UdpSocket :: bind ( & SocketAddr :: V4 ( SocketAddrV4 :: new ( my_ip, 0 ) ) ) ?;
72
- socket. set_read_timeout ( Some ( Duration :: new ( 5 , 0 ) ) ) ?;
73
- socket. set_write_timeout ( Some ( Duration :: new ( 5 , 0 ) ) ) ?;
74
- socket. connect ( & SocketAddr :: V4 ( SocketAddrV4 :: new ( dns_ip, 53 ) ) ) ?;
75
- socket. send ( & packet_data) ?;
76
-
77
- let mut buf = [ 0 ; 65536 ] ;
78
- let count = socket. recv ( & mut buf) ?;
79
-
80
- match Dns :: parse ( & buf[ .. count] ) {
81
- Ok ( response) => {
82
- let mut addrs = vec ! [ ] ;
83
- for answer in response. answers . iter ( ) {
84
- if answer. a_type == 0x0001 && answer. a_class == 0x0001
85
- && answer. data . len ( ) == 4
86
- {
87
- let answer_ip = Ipv4Addr :: new ( answer. data [ 0 ] ,
88
- answer. data [ 1 ] ,
89
- answer. data [ 2 ] ,
90
- answer. data [ 3 ] ) ;
91
- addrs. push ( SocketAddr :: V4 ( SocketAddrV4 :: new ( answer_ip, 0 ) ) ) ;
92
- }
48
+ impl < ' a > TryFrom < & ' a str > for LookupHost {
49
+ type Error = io:: Error ;
50
+
51
+ fn try_from ( s : & str ) -> io:: Result < LookupHost > {
52
+ macro_rules! try_opt {
53
+ ( $e: expr, $msg: expr) => (
54
+ match $e {
55
+ Some ( r) => r,
56
+ None => return Err ( io:: Error :: new( io:: ErrorKind :: InvalidInput ,
57
+ $msg) ) ,
93
58
}
94
- Ok ( LookupHost ( addrs. into_iter ( ) ) )
95
- } ,
96
- Err ( _err) => Err ( Error :: from_raw_os_error ( EINVAL ) )
59
+ )
60
+ }
61
+
62
+ // split the string by ':' and convert the second part to u16
63
+ let mut parts_iter = s. rsplitn ( 2 , ':' ) ;
64
+ let port_str = try_opt ! ( parts_iter. next( ) , "invalid socket address" ) ;
65
+ let host = try_opt ! ( parts_iter. next( ) , "invalid socket address" ) ;
66
+ let port: u16 = try_opt ! ( port_str. parse( ) . ok( ) , "invalid port value" ) ;
67
+
68
+ ( host, port) . try_into ( )
69
+ }
70
+ }
71
+
72
+ impl < ' a > TryFrom < ( & ' a str , u16 ) > for LookupHost {
73
+ type Error = io:: Error ;
74
+
75
+ fn try_from ( ( host, port) : ( & ' a str , u16 ) ) -> io:: Result < LookupHost > {
76
+ let mut ip_string = String :: new ( ) ;
77
+ File :: open ( "/etc/net/ip" ) ?. read_to_string ( & mut ip_string) ?;
78
+ let ip: Vec < u8 > = ip_string. trim ( ) . split ( '.' ) . map ( |part| part. parse :: < u8 > ( )
79
+ . unwrap_or ( 0 ) ) . collect ( ) ;
80
+
81
+ let mut dns_string = String :: new ( ) ;
82
+ File :: open ( "/etc/net/dns" ) ?. read_to_string ( & mut dns_string) ?;
83
+ let dns: Vec < u8 > = dns_string. trim ( ) . split ( '.' ) . map ( |part| part. parse :: < u8 > ( )
84
+ . unwrap_or ( 0 ) ) . collect ( ) ;
85
+
86
+ if ip. len ( ) == 4 && dns. len ( ) == 4 {
87
+ let time = time:: SystemTime :: now ( ) . duration_since ( time:: UNIX_EPOCH ) . unwrap ( ) ;
88
+ let tid = ( time. subsec_nanos ( ) >> 16 ) as u16 ;
89
+
90
+ let packet = Dns {
91
+ transaction_id : tid,
92
+ flags : 0x0100 ,
93
+ queries : vec ! [ DnsQuery {
94
+ name: host. to_string( ) ,
95
+ q_type: 0x0001 ,
96
+ q_class: 0x0001 ,
97
+ } ] ,
98
+ answers : vec ! [ ]
99
+ } ;
100
+
101
+ let packet_data = packet. compile ( ) ;
102
+
103
+ let my_ip = Ipv4Addr :: new ( ip[ 0 ] , ip[ 1 ] , ip[ 2 ] , ip[ 3 ] ) ;
104
+ let dns_ip = Ipv4Addr :: new ( dns[ 0 ] , dns[ 1 ] , dns[ 2 ] , dns[ 3 ] ) ;
105
+ let socket = UdpSocket :: bind ( Ok ( & SocketAddr :: V4 ( SocketAddrV4 :: new ( my_ip, 0 ) ) ) ) ?;
106
+ socket. set_read_timeout ( Some ( Duration :: new ( 5 , 0 ) ) ) ?;
107
+ socket. set_write_timeout ( Some ( Duration :: new ( 5 , 0 ) ) ) ?;
108
+ socket. connect ( Ok ( & SocketAddr :: V4 ( SocketAddrV4 :: new ( dns_ip, 53 ) ) ) ) ?;
109
+ socket. send ( & packet_data) ?;
110
+
111
+ let mut buf = [ 0 ; 65536 ] ;
112
+ let count = socket. recv ( & mut buf) ?;
113
+
114
+ match Dns :: parse ( & buf[ .. count] ) {
115
+ Ok ( response) => {
116
+ let mut addrs = vec ! [ ] ;
117
+ for answer in response. answers . iter ( ) {
118
+ if answer. a_type == 0x0001 && answer. a_class == 0x0001
119
+ && answer. data . len ( ) == 4
120
+ {
121
+ let answer_ip = Ipv4Addr :: new ( answer. data [ 0 ] ,
122
+ answer. data [ 1 ] ,
123
+ answer. data [ 2 ] ,
124
+ answer. data [ 3 ] ) ;
125
+ addrs. push ( SocketAddr :: V4 ( SocketAddrV4 :: new ( answer_ip, 0 ) ) ) ;
126
+ }
127
+ }
128
+ Ok ( LookupHost ( addrs. into_iter ( ) , port) )
129
+ } ,
130
+ Err ( _err) => Err ( Error :: from_raw_os_error ( EINVAL ) )
131
+ }
132
+ } else {
133
+ Err ( Error :: from_raw_os_error ( EINVAL ) )
97
134
}
98
- } else {
99
- Err ( Error :: from_raw_os_error ( EINVAL ) )
100
135
}
101
136
}
102
137
0 commit comments