aboutsummaryrefslogtreecommitdiff
path: root/.config/awesome/quarrel/native/src/net/mod.rs
blob: c9d617ca5f70df2f9e394183111c6abd07ee98d3 (plain)
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
// This is an attempt to port the iwgetid and iwlib code

mod wireless;
use std::{
    ffi::{
        c_char,
        c_int,
        c_uchar,
        c_void,
    },
    mem::size_of,
    os::fd::RawFd,
    str,
};

use mlua::prelude::*;
use nix::{
    ioctl_read_bad,
    libc::IF_NAMESIZE,
    sys::socket::{
        socket as open_socket,
        AddressFamily,
        SockFlag,
        SockType,
    },
    unistd::close
};
use wireless::{
    IfConf,
    IfConfData,
    IwPoint,
    IwReq,
    IwReqData,
    IwReqName,
    IW_ESSID_MAX_SIZE,
    SIOCGIFCONF,
    SIOCGIWESSID,
};

ioctl_read_bad!(ioctl_get_interfaces, SIOCGIFCONF, IfConf);
ioctl_read_bad!(ioctl_get_essid, SIOCGIWESSID, IwReq);

pub fn get_first_essid(_: &Lua, _: ()) -> LuaResult<String> {
    type Buffer = [c_char; 1024];
    let mut buffer: Buffer = [0; 1024];

    let mut if_conf = IfConf {
        ifc_len: size_of::<Buffer>() as c_int,
        data: IfConfData {
            ifc_buf: buffer.as_mut_ptr(),
        },
    };

    let mut if_req;
    let socket = get_first_socket().map_err(LuaError::external)?;

    unsafe {
        ioctl_get_interfaces(socket, &mut if_conf).map_err(LuaError::external)?;
        if_req = if_conf.data.ifc_req;
    }

    for _ in 0..if_conf.ifc_len / size_of::<IfConf>() as c_int {
        if let Ok(essid) = get_essid(socket, unsafe { *if_req }.ifr_name) {
            close(socket).map_err(LuaError::external)?;
            return Ok(essid);
        };

        unsafe { if_req = if_req.add(1) };
    }

    close(socket).map_err(LuaError::external)?;
    Err(LuaError::external("couldn't find any valid interfaces"))
}

fn get_essid(socket: RawFd, if_name: [c_char; IF_NAMESIZE]) -> LuaResult<String> {
    let mut essid: [c_uchar; (IW_ESSID_MAX_SIZE + 1) as usize] =
        [0; (IW_ESSID_MAX_SIZE + 1) as usize];
    let mut wrq = IwReq {
        ifr_ifrn: IwReqName { ifrn_name: if_name },
        u: IwReqData {
            essid: IwPoint {
                pointer: essid.as_mut_ptr().cast::<c_void>(),
                length: IW_ESSID_MAX_SIZE + 1,
                flags: 0,
            },
        },
    };

    unsafe {
        ioctl_get_essid(socket, &mut wrq).map_err(LuaError::external)?;
    }

    Ok(str::from_utf8(essid.as_slice())
        .map_err(LuaError::external)?
        .to_owned())
}

fn get_first_socket() -> LuaResult<RawFd> {
    let families = [
        AddressFamily::Inet,
        AddressFamily::Ipx,
        AddressFamily::Ax25,
        AddressFamily::AppleTalk,
    ];

    for family in families {
        if let Ok(socket) = open_socket(family, SockType::Datagram, SockFlag::empty(), None) {
            return Ok(socket);
        }
    }

    Err(LuaError::external("couldn't get a valid kernel socket"))
}