1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*!
Common traits for all libraries.
*/

use crate::{BorrowedPacket, DataLink, LibraryVersion, Error, InterfaceDescription, Stats};
use std::iter::IntoIterator;
use std::sync::Arc;


///Trait for structures representing an opened interface (or network card or network device)
///
/// Interfaces are opened using a concrete library - check the Library trait.
pub trait DynamicInterface<'a>: Send + Sync{

    ///Sends a raw packet.
    fn send(&self, packet: &[u8]) -> Result<(), Error>;

    ///Receives a raw packet.
    fn receive<'b>(&'b mut self) -> Result<BorrowedPacket<'b>, Error>;

    ///Flushes a queue
    fn flush(&self);

    ///Provides information about the underlying technology used for this connection.
    fn data_link(&self) -> DataLink;

    ///Provides transmission statistics
    fn stats(&self) -> Result<Stats, Error>;

    ///Breaks previously started loops.
    fn break_loop(&  self);

    /**
    Runs infinite loop and passes received packets via callback.

    Exits when the break_loop() function is called or on error.
    */
    fn loop_infinite_dyn(&self, callback: & dyn FnMut(&BorrowedPacket)) -> Result<(), Error>;

    //TODO
    //loop
    //breakloop
    //bpf filters
    //receive/send with timeout

}

/**
    Contains static part of the interface trait.

    Template functions cannot be used for dynamic dispatch (&dyn) and it was necessary to split the
    interface trait into two parts - static and dynamic, depending how user uses the trait.
    StaticInterface contains only the part of trait that cannot be used in the dynamic way.
*/
pub trait StaticInterface<'a>: DynamicInterface<'a> {

    /**
    Runs infinite loop and passes received packets via callback.

    Exits when the break_loop() function is called or on error.
    */
    fn loop_infinite<F>(& self, callback: F) -> Result<(), Error> where F: FnMut(&BorrowedPacket);

}

/// Trait for structures representing opened packet capture libraries.
///
/// There are several libraries that can be used among different platforms.
/// For example pcap.so, wpcap.dll or pfring.so.
/// This trait provides a consistent interface to all of them.
pub trait Library: Send+Sync{

    //const DEFAULT_PATHS: &'static [&'static str];

    ///Opens this library by searching for most common paths and names fro the given platform
    fn open_default_paths() -> Result<Self, Error> where Self: Sized {
        Self::open_paths(Self::default_paths().iter().map(|s|*s))
    }

    ///Returns list of default paths to the library on the given platform.
    fn default_paths() -> &'static[&'static str] where Self: Sized;

    ///Opens library searching in the list of provided paths.
    fn open_paths<'b, T>(paths: T) -> Result<Self, Error> where Self: Sized, T:IntoIterator<Item=&'b str>{
        let mut err = Error::NoPathsProvided;
        for path in paths.into_iter(){
            match Self::open(path) {
                Err(e) => err = e,
                Ok(lib) => return Ok(lib)
            }
        }
        Err(err)
    }

    ///Opens library by checking the provided path to it.
    fn open(path: &str) -> Result<Self, Error> where Self: Sized;

    ///Opens interface (network card or network device) with the provided name.
    ///
    /// You can obtain names of available devices by calling the all_interfaces() function.
    fn open_interface<'a>(&'a self, name: &str) -> Result<Box<dyn DynamicInterface<'a>+'a>, Error>;

    fn open_interface_arc<'a>(&'a self, name: &str) -> Result<Arc<DynamicInterface<'a> + 'a>, Error>;

    /**
    Obtains list of available network interfaces.

    Each of returned interface names can be further used to open interfaces.

    **Note:** each library may support different set of interfaces.
    This is because different libraries support different network interface types and some of them
    add to the list virtual interfaces (such as pcap "any" interface or pfring "zc:eth0").
    The same function called with pcap library will return different set of interfaces than run with pfring.
    However in both cases the returned interface list will be supported by currently used library.

    # Example

    ```no_run
    extern crate rawsock;
    use rawsock::open_best_library;
    use rawsock::traits::Library;

    fn main(){
        let lib = open_best_library().expect("Could not open any library.");
        let interfs = lib.all_interfaces().expect("Could not obtain interface list");
        for interf in &interfs{
            println!("Found interface: {}", &interf.name);
        }
        let interf = lib.open_interface(&interfs.first().unwrap().name)
            .expect("Could not open interface");
        // do something with the interface
    }
    ```

    */
    fn all_interfaces(&self) -> Result<Vec<InterfaceDescription>, Error>;

    ///Returns library version
    fn version(&self) -> LibraryVersion;
}