99// except according to those terms.
1010
1111use fs:: File ;
12- use io:: { Error , Result , Read } ;
12+ use io:: { Error , Read , self } ;
1313use iter:: Iterator ;
1414use net:: { Ipv4Addr , SocketAddr , SocketAddrV4 } ;
1515use str:: FromStr ;
1616use string:: { String , ToString } ;
1717use sys:: syscall:: EINVAL ;
1818use time:: { self , Duration } ;
1919use vec:: { IntoIter , Vec } ;
20+ use convert:: { TryFrom , TryInto } ;
2021
2122use self :: dns:: { Dns , DnsQuery } ;
2223
@@ -29,7 +30,13 @@ mod dns;
2930mod tcp;
3031mod udp;
3132
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+ }
3340
3441impl Iterator for LookupHost {
3542 type Item = SocketAddr ;
@@ -38,65 +45,93 @@ impl Iterator for LookupHost {
3845 }
3946}
4047
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) ) ,
9358 }
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 ) )
97134 }
98- } else {
99- Err ( Error :: from_raw_os_error ( EINVAL ) )
100135 }
101136}
102137
0 commit comments