rust_rsm/net_ext/unix/
rawsocket.rs

1#![allow(non_camel_case_types)]
2#![allow(non_snake_case)]
3#![allow(non_upper_case_globals)]
4#![allow(unused_variables)]
5#![allow(dead_code)]
6
7use super::super::*;
8use libc;
9use std::os::raw::{c_int,c_void};
10use std::net::{UdpSocket,SocketAddr,SocketAddrV6,SocketAddrV4};
11use mio::net::UdpSocket as mio_udpsocket;
12#[cfg(unix)]
13use std::os::unix::io::{AsRawFd,RawFd};
14use std::io::{self,Error, IoSliceMut,IoSlice};
15use std::mem;
16
17#[repr(C)]
18#[derive(Clone,Copy)]
19pub union sockaddr_t {
20     pub v4: libc::sockaddr_in,
21     pub v6: libc::sockaddr_in6,
22}
23        
24impl sockaddr_t {
25    pub fn as_ptr(&self) -> *const libc::sockaddr {
26        self as *const _ as *const libc::sockaddr
27    }
28
29    pub fn from_socket_addr(addr:&SocketAddr)->(Self,libc::socklen_t){
30        match addr {
31            SocketAddr::V4(ipv4)=> {
32                let sin_addr = libc::in_addr {
33                    s_addr: u32::from_ne_bytes(ipv4.ip().octets()),
34                };
35                let sockaddr = libc::sockaddr_in{
36                sin_family:libc::AF_INET as libc::sa_family_t,
37                sin_port:ipv4.port().to_be(),
38                sin_addr:sin_addr,
39                sin_zero:[0;8],
40                };
41                return (Self{v4:sockaddr},mem::size_of::<libc::sockaddr_in>() as libc::socklen_t)
42            },
43            SocketAddr::V6(ipv6)=> {
44                let sockaddr = libc::sockaddr_in6 {
45                    sin6_family:libc::AF_INET6 as libc::sa_family_t,
46                    sin6_port:ipv6.port().to_be(),
47                    sin6_flowinfo:ipv6.flowinfo(),
48                    sin6_addr:libc::in6_addr {
49                        s6_addr: ipv6.ip().octets(),
50                    },
51                    sin6_scope_id:ipv6.scope_id(),
52                };
53                return (Self{v6:sockaddr},mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t)
54            },
55        }
56        
57    }
58}
59
60pub unsafe fn to_socket_addr(
61    sock_addr: *const sockaddr_t,
62) -> io::Result<SocketAddr> {
63    if sock_addr==std::ptr::null() {
64        return Err(io::ErrorKind::InvalidInput.into())
65    }
66    match (*sock_addr).v4.sin_family as libc::c_int {
67        libc::AF_INET => {
68            // AF_INET,采用sockaddr_in存储.
69            let addr: &libc::sockaddr_in = &*(sock_addr as *const libc::sockaddr_in);
70            let ip = Ipv4Addr::from(addr.sin_addr.s_addr.to_ne_bytes());
71            let port = u16::from_be(addr.sin_port);
72            Ok(SocketAddr::V4(SocketAddrV4::new(ip, port)))
73        }
74        libc::AF_INET6 => {
75            // AF_INET,采用sockaddr_in6存储
76            let addr: &libc::sockaddr_in6 = &*(sock_addr as *const libc::sockaddr_in6);
77            let ip = Ipv6Addr::from(addr.sin6_addr.s6_addr);
78            let port = u16::from_be(addr.sin6_port);
79            Ok(SocketAddr::V6(SocketAddrV6::new(
80                ip,
81                port,
82                addr.sin6_flowinfo,
83                addr.sin6_scope_id,
84            )))
85        }
86        _ => Err(io::ErrorKind::InvalidInput.into()),
87    }
88}
89
90///设置socket接收缓冲区大小,以字节计算
91pub fn set_socket_recvbuf(socket:RawFdType,buf_size:i32)->i32 {
92    return  unsafe { 
93        libc::setsockopt(socket as c_int, libc::SOL_SOCKET,
94        libc::SO_RCVBUF,&(buf_size as c_int) as *const _ as *const c_void,std::mem::size_of::<i32>() as libc::socklen_t) 
95    };
96}
97
98///设置socket发送缓冲区大小,以字节计算
99pub fn set_socket_sendbuf(socket:RawFdType,buf_size:i32)->i32 {
100    return unsafe {
101        libc::setsockopt(socket as c_int, libc::SOL_SOCKET,
102        libc::SO_SNDBUF,&(buf_size as c_int) as *const _ as *const c_void,std::mem::size_of::<i32>() as libc::socklen_t)
103    };
104}
105
106///设置socket reuse addr参数,1=使用,0-不使用
107pub fn set_socket_reuse_addr(socket:RawFdType,is_reuse:i32)->i32 {
108    return unsafe {
109        libc::setsockopt(socket as c_int, libc::SOL_SOCKET,
110        libc::SO_REUSEADDR,&(is_reuse as c_int) as *const _ as *const c_void,std::mem::size_of::<i32>() as libc::socklen_t)
111    };
112}
113
114///设置socketreuse port参数,1=使用,0-不使用
115pub fn set_socket_reuse_port(socket:RawFdType,is_reuse:i32)->i32 {
116    return unsafe {
117        libc::setsockopt(socket as c_int, libc::SOL_SOCKET,
118        libc::SO_REUSEPORT,&(is_reuse as c_int) as *const _ as *const c_void,std::mem::size_of::<i32>() as libc::socklen_t)
119    };
120}
121///获得一个mio udp_socket的raw socket句柄
122pub fn get_raw_socket(socket:&mio_udpsocket)->RawFdType {
123    return socket.as_raw_fd();
124}
125
126///send_udp_msg,使用raw_fd作为入参,发送Message
127pub fn send_udp_msg(fd:RawFdType,buf:&[u8],addr:&SocketAddr)->io::Result<usize> {
128      
129    unsafe {
130        let (sockaddr,len) = sockaddr_t::from_socket_addr(addr);  
131        let res= libc::sendto(fd as libc::c_int,buf.as_ptr() as  *const c_void,buf.len() as libc::size_t,0,
132            sockaddr.as_ptr(),len) as usize;
133
134            if res>0 {
135                return Ok(res as usize)
136            } else {
137                return Err(Error::last_os_error())
138            }
139    }
140}
141
142///wait_for_single_fd_read,等待一个文件的读事件
143/// fd:原始文件句柄,timeout_msec,超时毫秒数
144pub fn wait_for_single_fd_read(fd:RawFdType,timeout_msec:i32)->Result<(),errcode::RESULT> {
145    let mut fds = libc::pollfd{
146        fd:fd as libc::c_int,
147        events:libc::POLLIN,
148        revents:0,
149    };
150    match unsafe { libc::poll(&mut fds as *mut libc::pollfd,1 as libc::nfds_t,timeout_msec as libc::c_int) } {
151        0=>Err(errcode::ERROR_TIME_OUT),
152        1=>Ok(()),
153        _=>Err(errcode::ERROR_OS_CALL_FAILED),
154    }
155}
156
157//对Windows/Linux原生网络接口的封装
158//从而支持原生Socket接口的跨平台
159pub fn create_rawsocket(is_l2_socket:bool)->RawFdType {
160    let sock_type=if is_l2_socket {libc::SOCK_RAW} else {libc::SOCK_DGRAM};
161    
162    return unsafe { libc::socket(libc::AF_PACKET, sock_type, i32::from((libc::ETH_P_ALL as u16).to_be())) }
163}
164
165///根据network name获得if_index
166pub fn get_netif_index_by_name(name: &str) -> Result<i32,errcode::RESULT> {
167    if name.len() > libc::IFNAMSIZ {
168        return Err(errcode::ERROR_INVALID_PARAM);
169    }
170    let mut buf = [0u8; libc::IFNAMSIZ];
171        buf[..name.len()].copy_from_slice(name.as_bytes());
172    let idx = unsafe { libc::if_nametoindex(buf.as_ptr() as *const libc::c_char) };
173    if idx == 0 {
174        return Err(errcode::ERROR_NOT_FOUND);
175    }
176
177    Ok(idx as i32)
178}
179
180///绑定指定index的接口,一般用于AF_PACKET类型的Socket
181pub fn bind_by_index(fd:RawFdType,ifindex: i32) -> errcode::RESULT {
182    unsafe {
183        let mut ss: libc::sockaddr_storage = std::mem::zeroed();
184        let sll: *mut libc::sockaddr_ll = &mut ss as *mut libc::sockaddr_storage as *mut libc::sockaddr_ll;
185        (*sll).sll_family = libc::AF_PACKET as u16;
186        (*sll).sll_protocol = (libc::ETH_P_ALL as u16).to_be();
187        (*sll).sll_ifindex = ifindex;
188
189        let sa = (&ss as *const libc::sockaddr_storage) as *const libc::sockaddr;
190        let res = libc::bind(fd, sa, std::mem::size_of::<libc::sockaddr_ll>() as u32);
191        if res == -1 {
192            return errcode::ERROR_BIND_SOCKET;
193        }
194        let ignore_pkt:i32 = 1;
195        const PACKET_IGNORE_OUTGOING:i32=23;
196        libc::setsockopt(fd,libc::SOL_PACKET,PACKET_IGNORE_OUTGOING,
197              &ignore_pkt as *const i32 as *const libc::c_void,std::mem::size_of::<i32>().try_into().unwrap());
198    }
199
200    errcode::RESULT_SUCCESS
201}
202
203pub fn bind(fd:RawFdType,addr:&SocketAddr)->errcode::RESULT {
204    let (os_addr,len)=sockaddr_t::from_socket_addr(addr);
205
206    let res = unsafe { libc::bind(fd,std::ptr::addr_of!(os_addr) as *const libc::sockaddr, len) };
207    if res!=0 {
208        println!("bind socket addr={},os_err={}",addr,std::io::Error::last_os_error());
209        return errcode::ERROR_BIND_SOCKET
210    }
211    return errcode::RESULT_SUCCESS
212
213}
214pub fn listen(fd:RawFdType,back_log:i32)->errcode::RESULT {
215
216    let res = unsafe { libc::listen(fd,back_log) };
217    if res!=0 {
218        return errcode::ERROR_BIND_SOCKET
219    }
220    return errcode::RESULT_SUCCESS
221
222}
223
224pub fn accept(fd:RawFdType)->Result<(RawFdType,SocketAddr),errcode::RESULT> {
225    let mut sock_addr = unsafe { mem::zeroed::<sockaddr_t>() };
226    let mut len=std::mem::size_of::<sockaddr_t>() as u32;
227    let res = unsafe { libc::accept(fd,std::ptr::addr_of_mut!(sock_addr) as *mut libc::sockaddr,&mut len as * mut u32) };
228    if res<0 {
229        println!("[rawsocket]accept connection error,ret={},os_err={}",res,std::io::Error::last_os_error());
230        return Err(errcode::ERROR_OS_CALL_FAILED)
231    }
232    let addr=match unsafe { to_socket_addr(std::ptr::addr_of!(sock_addr)) } {
233        Err(_)=>return Err(errcode::ERROR_INVALID_IPADDR),
234        Ok(a)=>a,
235    };
236    return Ok((res as RawFdType,addr))
237
238}
239
240pub fn connect(fd:RawFdType,dst:&SocketAddr)->errcode::RESULT {
241    let (addr,len)=sockaddr_t::from_socket_addr(dst);
242    let ret = unsafe {
243        libc::connect(fd, std::ptr::addr_of!(addr) as *const libc::sockaddr, len)
244    };
245
246    if ret==0 {
247        return errcode::RESULT_SUCCESS
248    }
249    return errcode::ERROR_OS_CALL_FAILED
250}
251
252///设置网卡的混杂模式
253pub fn set_promisc_mode(fd:RawFdType,if_idx: i32, state: bool) ->errcode::RESULT {
254    let packet_membership = if state {
255        libc::PACKET_ADD_MEMBERSHIP
256    } else {
257        libc::PACKET_DROP_MEMBERSHIP
258    };
259
260    unsafe {
261        let mut mreq: libc::packet_mreq = std::mem::zeroed();
262
263        mreq.mr_ifindex = if_idx;
264        mreq.mr_type = libc::PACKET_MR_PROMISC as u16;
265
266        let res = libc::setsockopt(fd, libc::SOL_PACKET, packet_membership, 
267            (&mreq as *const libc::packet_mreq) as *const libc::c_void, std::mem::size_of::<libc::packet_mreq>() as u32);
268        if res == -1 {
269            return errcode::ERROR_OS_CALL_FAILED;
270        }
271    }
272
273    errcode::RESULT_SUCCESS
274}
275
276///read_fd,从文件句柄中读取一段数据
277pub fn read_fd(fd: RawFd, buf: &mut [u8],flags:i32) -> Result<usize,errcode::RESULT> {
278    let rv = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut libc::c_void, buf.len()) };
279    if rv < 0 {
280        return Err(errcode::ERROR_RECV_MSG);
281    }
282
283    Ok(rv as usize)
284}
285
286///write_fd,向文件句柄中写入一段数据
287pub fn write_fd(fd: RawFd, buf: &[u8],flags:i32) -> Result<usize,errcode::RESULT> {
288    let rv = unsafe { libc::write(fd, buf.as_ptr() as *const libc::c_void, buf.len().try_into().unwrap()) };
289    if rv < 0 {
290        //println!("send packet error:{} ",Error::last_os_error());
291        return Err(errcode::ERROR_RECV_MSG);
292    }
293
294    Ok(rv as usize)
295}
296
297pub fn send_to(fd: RawFdType, buf: &[u8],flags:i32,dst:&SocketAddr) -> Result<usize,errcode::RESULT> {
298    let (addr,len)=sockaddr_t::from_socket_addr(dst);
299    let rv = unsafe { 
300        libc::sendto(fd, buf.as_ptr() as *const libc::c_void, buf.len(), flags,
301        std::ptr::addr_of!(addr) as *const libc::sockaddr, len)
302    };
303    if rv < 0 {
304        return Err(errcode::ERROR_SEND_MSG);
305    }
306
307    Ok(rv as usize)
308}
309
310///read_fd_vector,从文件中批量读取一批数据
311#[cfg(unix)]
312pub fn read_fd_vector(fd: RawFd, bufs: &mut [IoSliceMut]) -> io::Result<usize> {
313    let rv = unsafe { libc::readv(fd, bufs.as_mut_ptr() as *const libc::iovec, bufs.len() as i32) };
314    if rv < 0 {
315        return Err(Error::last_os_error());
316    }
317
318    Ok(rv as usize)
319}
320
321///write_fd_vector,向文件中批量写入一批数据
322pub fn write_fd_vertor(fd: RawFd, bufs: &[IoSlice]) -> io::Result<usize> {
323    let rv = unsafe { libc::writev(fd, bufs.as_ptr() as *const libc::iovec, bufs.len() as i32) };
324    if rv < 0 {
325        return Err(Error::last_os_error());
326    }
327
328    Ok(rv as usize)
329}
330
331    /// set_non_blocking 设置文件系统为Non-blocking模式.
332    pub fn set_non_blocking(fd:RawFd) -> io::Result<()> {
333        unsafe {
334            let mut res = libc::fcntl(fd, libc::F_GETFL);
335            if res != -1 {
336                res = libc::fcntl(fd, libc::F_SETFL, res | libc::O_NONBLOCK);
337            }
338            if res == -1 {
339                return Err(Error::last_os_error());
340            }
341        }
342        Ok(())
343    }
344
345
346///close_fd,关闭文件句柄
347pub fn close_fd(fd:RawFdType) {
348    unsafe {
349    libc::close(fd);
350    }
351}
352
353///recv_from,接收Socket消息,返回大小和对端地址
354pub fn recv_from(fd: RawFd, buf: &mut [u8]) -> io::Result<(usize,SocketAddr)> {
355    //println!("begin recv {} msg,content={}",bufs_count,bufs[0].to_string());
356    unsafe { 
357    let mut addr=mem::zeroed::<sockaddr_t>();
358    let mut addr_len = mem::size_of::<sockaddr_t>() as u32;
359    let rv = 
360        libc::recvfrom(fd, buf.as_mut_ptr() as *mut libc::c_void, 
361            buf.len(),0,&mut addr as *mut _ as *mut libc::sockaddr, &mut addr_len as *mut u32);
362    
363    if rv < 0 {
364        let err = Error::last_os_error();
365        //println!("recv msg error:{}-{},content={:?}",rv,err,bufs);
366        return Err(err);
367    }
368    let sockaddr = match to_socket_addr(&addr as *const sockaddr_t) {
369        Ok(a)=>a,
370        Err(_)=>return Err(Error::last_os_error()),
371    };
372    Ok((rv as usize,sockaddr))
373}
374}
375
376
377//pub type iovec = libc::iovec;
378
379#[repr(C)]
380#[derive(Copy,Clone)]
381pub struct iovec {
382    pub iov_base: *mut u8, 
383    pub iov_len: usize,   
384}
385impl iovec {
386    pub fn from_raw_parts(buf_ptr:*mut u8,len:usize)->iovec {
387        return Self{
388            iov_base:buf_ptr,
389            iov_len:len,
390        }
391    }
392
393    pub fn from_slice(buf:&mut[u8])->iovec {
394        return Self{
395            iov_base:buf.as_mut_ptr(),
396            iov_len:buf.len(),
397        }
398    }
399    pub fn to_slice(&mut self)->&[u8] {
400        let p = unsafe { std::slice::from_raw_parts_mut(self.iov_base, self.iov_len) };
401        return p
402    }
403}
404
405///批量发送接收Socket消息,send_mmsg/recv_mmsg,采用Linux兼容格式,Windows适配Linux格式
406/// 
407#[derive(Debug)]
408#[repr(C)]
409pub struct msg_hdr_t {
410    pub msg_name: *mut sockaddr_t,
411    pub msg_namelen: u32,
412    pub msg_iov: *mut iovec,
413    pub msg_iovlen: usize,
414    pub msg_control: *mut u8,
415    pub msg_control_len: usize,
416    pub msg_flags: i32,
417}
418#[derive(Debug)]
419#[repr(C)]
420pub struct mmsg_hdr_t {
421    pub msg_hdr: msg_hdr_t,
422    pub msg_len: u32,
423}
424
425impl mmsg_hdr_t {
426    ///创建一个为recvmmsg/sendmmsg使用的mmsghdr头部
427    /// capacity为最大消息数量,buffs缓冲区
428   
429    pub fn new(capacity:usize, buffs:&mut [iovec],addr:&mut sockaddr_t)->Self {        
430
431        //let hdr = 
432        return mmsg_hdr_t{
433            msg_hdr:msg_hdr_t {
434                msg_name: addr as * mut sockaddr_t,
435                msg_namelen: std::mem::size_of::<sockaddr_t>() as u32,
436                msg_iov: buffs.as_mut_ptr(),
437                msg_iovlen:capacity,
438                msg_control:std::ptr::null_mut(),
439                msg_control_len:0,
440                msg_flags:0
441            },
442            msg_len:0,
443        }
444    }
445
446    pub fn get_nth_buf_len(&self,idx:usize)->usize {
447        if idx>=self.msg_hdr.msg_iovlen {
448            return 0;
449        }
450        let buf= unsafe {
451            &*((self.msg_hdr.msg_iov as usize + mem::size_of::<iovec>()*idx) as *const iovec)
452        };
453        return buf.iov_len;
454        
455    }
456
457    pub fn to_string(&self)->String {
458        unsafe {
459            let mut content = Vec::with_capacity(64);
460            std::ptr::copy((*self.msg_hdr.msg_iov).iov_base, content.as_mut_ptr(), 32);
461            content.set_len(32);
462            format!("msg_len={},msg_name={:?},msg_namelen={},msg_iov={:?},msg_iov_len={},msg_control:{:?},msg_control_len={},
463            content={:?}",
464            self.msg_len,self.msg_hdr.msg_name,self.msg_hdr.msg_namelen,self.msg_hdr.msg_iov,
465            self.msg_hdr.msg_iovlen,self.msg_hdr.msg_control,self.msg_hdr.msg_control_len,
466            content.as_slice())
467            }
468    }
469}
470
471///recv_from_mmsg,从Socket批量接收一批报文,成功则返回接收的报文数量
472pub fn recv_from_mmsg(fd: RawFd, bufs: &mut [mmsg_hdr_t],bufs_count:u32) -> io::Result<usize> {
473    //println!("begin recv {} msg,content={}",bufs_count,bufs[0].to_string());
474    let rv = unsafe { 
475        libc::recvmmsg(fd, bufs.as_mut_ptr() as *mut mmsg_hdr_t as *mut u8 as *mut libc::mmsghdr, 
476            bufs_count,0,std::ptr::null_mut() as *mut libc::timespec) 
477    };
478    if rv < 0 {
479        let err = Error::last_os_error();
480        //println!("recv msg error:{}-{},content={:?}",rv,err,bufs);
481        return Err(err);
482    }
483 
484    Ok(rv as usize)
485}
486
487///send_mmsg,从Socket批量发送一批报文,类型由mmsg_hdr_t决定
488pub fn send_mmsg(fd: RawFd, bufs: &mut mmsg_hdr_t,bufs_count:u32) -> io::Result<usize> {
489    let rv = unsafe { libc::sendmmsg(fd, bufs as *mut mmsg_hdr_t as *mut u8 as *mut libc::mmsghdr, 
490        bufs_count,0) };
491    if rv < 0 {
492        return Err(Error::last_os_error());
493    }
494
495    Ok(rv as usize)
496}