{-# LANGUAGE CPP #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
module System.Linux.Netlink.GeNetlink.NL80211
( NL80211Socket
, NL80211Packet
, makeNL80211Socket
, joinMulticastByName
, queryOne
, query
, getInterfaceList
, getScanResults
, getConnectedWifi
, getWifiAttributes
, getPacket
, getFd
, getMulticastGroups
)
where
#if MIN_VERSION_base(4,8,0)
#else
import Control.Applicative ((<$>))
#endif
import Data.Bits ((.|.))
import Data.ByteString.Char8 (unpack)
import Data.List (intercalate)
import Data.Maybe (mapMaybe)
import Data.Serialize.Get (runGet, getWord32host)
import Data.Serialize.Put (runPut, putWord32host)
import Data.Word (Word32, Word16, Word8)
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS (length)
import qualified Data.Map as M (empty, lookup, fromList, member, toList)
import System.Posix.Types (Fd)
import System.Linux.Netlink.Helpers (indent)
import System.Linux.Netlink.Constants
import System.Linux.Netlink.GeNetlink
import System.Linux.Netlink.GeNetlink.Control hiding (getMulticastGroups)
import qualified System.Linux.Netlink.GeNetlink.Control as C
import System.Linux.Netlink.GeNetlink.NL80211.Constants
import System.Linux.Netlink.GeNetlink.NL80211.StaInfo
import System.Linux.Netlink.GeNetlink.NL80211.WifiEI
import System.Linux.Netlink hiding (makeSocket, queryOne, query, recvOne, getPacket)
import qualified System.Linux.Netlink as I (queryOne, query, recvOne)
data NL80211Socket = NLS NetlinkSocket Word16
data NoData80211 = NoData80211 deriving (NoData80211 -> NoData80211 -> Bool
(NoData80211 -> NoData80211 -> Bool)
-> (NoData80211 -> NoData80211 -> Bool) -> Eq NoData80211
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: NoData80211 -> NoData80211 -> Bool
== :: NoData80211 -> NoData80211 -> Bool
$c/= :: NoData80211 -> NoData80211 -> Bool
/= :: NoData80211 -> NoData80211 -> Bool
Eq, Int -> NoData80211 -> ShowS
[NoData80211] -> ShowS
NoData80211 -> String
(Int -> NoData80211 -> ShowS)
-> (NoData80211 -> String)
-> ([NoData80211] -> ShowS)
-> Show NoData80211
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> NoData80211 -> ShowS
showsPrec :: Int -> NoData80211 -> ShowS
$cshow :: NoData80211 -> String
show :: NoData80211 -> String
$cshowList :: [NoData80211] -> ShowS
showList :: [NoData80211] -> ShowS
Show)
instance Convertable NoData80211 where
getPut :: NoData80211 -> Put
getPut NoData80211
_ = () -> Put
forall a. a -> PutM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
getGet :: MessageType -> Get NoData80211
getGet MessageType
_ = NoData80211 -> Get NoData80211
forall a. a -> Get a
forall (m :: * -> *) a. Monad m => a -> m a
return NoData80211
NoData80211
type NL80211Packet = GenlPacket NoData80211
instance Show NL80211Packet where
showList :: [NL80211Packet] -> ShowS
showList [NL80211Packet]
xs = ((String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"===\n" ([String] -> String)
-> ([NL80211Packet] -> [String]) -> [NL80211Packet] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (NL80211Packet -> String) -> [NL80211Packet] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map NL80211Packet -> String
forall a. Show a => a -> String
show ([NL80211Packet] -> String) -> [NL80211Packet] -> String
forall a b. (a -> b) -> a -> b
$[NL80211Packet]
xs) String -> ShowS
forall a. [a] -> [a] -> [a]
++)
show :: NL80211Packet -> String
show (Packet Header
_ GenlData NoData80211
cus Attributes
attrs) =
String
"NL80211Packet: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ GenlData NoData80211 -> String
showNL80211Command GenlData NoData80211
cus String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"\n" String -> ShowS
forall a. [a] -> [a] -> [a]
++
String
"Attrs: \n" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ((Int, ByteString) -> String) -> [(Int, ByteString)] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Int, ByteString) -> String
showNL80211Attr (Attributes -> [(Int, ByteString)]
forall k a. Map k a -> [(k, a)]
M.toList Attributes
attrs) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"\n"
show NL80211Packet
p = NL80211Packet -> String
forall a. Show a => Packet a -> String
showPacket NL80211Packet
p
showNL80211Command :: (GenlData NoData80211) -> String
showNL80211Command :: GenlData NoData80211 -> String
showNL80211Command (GenlData (GenlHeader Word8
cmd Word8
_) NoData80211
_ ) =
Word8 -> String
forall a. (Num a, Show a, Eq a) => a -> String
showNL80211Commands Word8
cmd
showNL80211Attr :: (Int, ByteString) -> String
showNL80211Attr :: (Int, ByteString) -> String
showNL80211Attr (Int
i, ByteString
v)
| Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
forall a. Num a => a
eNL80211_ATTR_STA_INFO = ByteString -> String
showStaInfo ByteString
v
| Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
forall a. Num a => a
eNL80211_ATTR_RESP_IE = ByteString -> String
showWifiEid ByteString
v
| Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
forall a. Num a => a
eNL80211_ATTR_BSS = ByteString -> String
showAttrBss ByteString
v
| Bool
otherwise = (Int -> String) -> (Int, ByteString) -> String
showAttr Int -> String
forall a. (Num a, Show a, Eq a) => a -> String
showNL80211Attrs (Int
i, ByteString
v)
showStaInfo :: ByteString -> String
showStaInfo :: ByteString -> String
showStaInfo ByteString
bs = let attrs :: Attributes
attrs = Either String Attributes -> Attributes
forall a b. Show a => Either a b -> b
getRight (Either String Attributes -> Attributes)
-> Either String Attributes -> Attributes
forall a b. (a -> b) -> a -> b
$ Get Attributes -> ByteString -> Either String Attributes
forall a. Get a -> ByteString -> Either String a
runGet Get Attributes
getAttributes ByteString
bs in
String
"NL80211_ATTR_STA_INFO: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show (ByteString -> Int
BS.length ByteString
bs) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"\n" String -> ShowS
forall a. [a] -> [a] -> [a]
++
(ShowS
indent ShowS -> (Attributes -> String) -> Attributes -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StaInfo -> String
forall a. Show a => a -> String
show (StaInfo -> String)
-> (Attributes -> StaInfo) -> Attributes -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Attributes -> StaInfo
staInfoFromAttributes (Attributes -> String) -> Attributes -> String
forall a b. (a -> b) -> a -> b
$ Attributes
attrs)
showAttrBss :: ByteString -> String
showAttrBss :: ByteString -> String
showAttrBss ByteString
bs = let attrs :: Attributes
attrs = Either String Attributes -> Attributes
forall a b. Show a => Either a b -> b
getRight (Either String Attributes -> Attributes)
-> Either String Attributes -> Attributes
forall a b. (a -> b) -> a -> b
$ Get Attributes -> ByteString -> Either String Attributes
forall a. Get a -> ByteString -> Either String a
runGet Get Attributes
getAttributes ByteString
bs in
String
"NL80211_ATTR_BSS: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show (ByteString -> Int
BS.length ByteString
bs) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"\n" String -> ShowS
forall a. [a] -> [a] -> [a]
++
(ShowS
indent ShowS
-> ([(Int, ByteString)] -> String) -> [(Int, ByteString)] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Int, ByteString) -> String) -> [(Int, ByteString)] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Int, ByteString) -> String
showBssAttr ([(Int, ByteString)] -> String) -> [(Int, ByteString)] -> String
forall a b. (a -> b) -> a -> b
$ Attributes -> [(Int, ByteString)]
forall k a. Map k a -> [(k, a)]
M.toList Attributes
attrs)
showBssAttr :: (Int, ByteString) -> String
showBssAttr :: (Int, ByteString) -> String
showBssAttr (Int
i, ByteString
v)
| Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
forall a. Num a => a
eNL80211_BSS_INFORMATION_ELEMENTS = String
"NL80211_BSS_INFORMATION_ELEMENTS " String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
showWifiEid ByteString
v
| Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
forall a. Num a => a
eNL80211_BSS_BEACON_IES = String
"NL80211_BSS_BEACON_IES " String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
showWifiEid ByteString
v
| Bool
otherwise = (Int -> String) -> (Int, ByteString) -> String
showAttr Int -> String
forall a. (Num a, Show a, Eq a) => a -> String
showNL80211Bss (Int
i, ByteString
v)
getFd :: NL80211Socket -> Fd
getFd :: NL80211Socket -> Fd
getFd (NLS NetlinkSocket
s Word16
_) = NetlinkSocket -> Fd
getNetlinkFd NetlinkSocket
s
getRight :: Show a => Either a b -> b
getRight :: forall a b. Show a => Either a b -> b
getRight (Right b
x) = b
x
getRight (Left a
err) = String -> b
forall a. HasCallStack => String -> a
error (String -> b) -> String -> b
forall a b. (a -> b) -> a -> b
$a -> String
forall a. Show a => a -> String
show a
err
makeNL80211Socket :: IO NL80211Socket
makeNL80211Socket :: IO NL80211Socket
makeNL80211Socket = do
sock <- IO NetlinkSocket
makeSocket
fid <- getFamilyId sock "nl80211"
return $NLS sock fid
joinMulticastByName :: NL80211Socket -> String -> IO ()
joinMulticastByName :: NL80211Socket -> String -> IO ()
joinMulticastByName (NLS NetlinkSocket
sock Word16
_) String
name = do
(_, m) <- NetlinkSocket -> String -> IO (Word16, [CtrlAttrMcastGroup])
getFamilyWithMulticasts NetlinkSocket
sock String
"nl80211"
let gid = String -> [CtrlAttrMcastGroup] -> Maybe Word32
getMulticast String
name [CtrlAttrMcastGroup]
m
case gid of
Maybe Word32
Nothing -> String -> IO ()
forall a. HasCallStack => String -> a
error (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$String
"Could not find \"" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"\" multicast group"
Just Word32
x -> NetlinkSocket -> Word32 -> IO ()
joinMulticastGroup NetlinkSocket
sock Word32
x
getMulticastGroups :: NL80211Socket -> IO [String]
getMulticastGroups :: NL80211Socket -> IO [String]
getMulticastGroups (NLS NetlinkSocket
sock Word16
fid) =
(CtrlAttrMcastGroup -> String) -> [CtrlAttrMcastGroup] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map CtrlAttrMcastGroup -> String
grpName ([CtrlAttrMcastGroup] -> [String])
-> IO [CtrlAttrMcastGroup] -> IO [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NetlinkSocket -> Word16 -> IO [CtrlAttrMcastGroup]
C.getMulticastGroups NetlinkSocket
sock Word16
fid
getRequestPacket :: Word16 -> Word8 -> Bool -> Attributes -> NL80211Packet
getRequestPacket :: Word16 -> Word8 -> Bool -> Attributes -> NL80211Packet
getRequestPacket Word16
fid Word8
cmd Bool
dump Attributes
attrs =
let header :: Header
header = MessageType -> Word16 -> Word32 -> Word32 -> Header
Header (Word16 -> MessageType
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
fid) Word16
flags Word32
0 Word32
0
geheader :: GenlHeader
geheader = Word8 -> Word8 -> GenlHeader
GenlHeader Word8
cmd Word8
0 in
Header -> GenlData NoData80211 -> Attributes -> NL80211Packet
forall a. Header -> a -> Attributes -> Packet a
Packet Header
header (GenlHeader -> NoData80211 -> GenlData NoData80211
forall a. GenlHeader -> a -> GenlData a
GenlData GenlHeader
geheader NoData80211
NoData80211) Attributes
attrs
where flags :: Word16
flags = if Bool
dump then Word16
forall a. (Num a, Bits a) => a
fNLM_F_REQUEST Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.|. Word16
forall a. (Num a, Bits a) => a
fNLM_F_MATCH Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.|. Word16
forall a. (Num a, Bits a) => a
fNLM_F_ROOT else Word16
forall a. (Num a, Bits a) => a
fNLM_F_REQUEST
queryOne :: NL80211Socket -> Word8 -> Bool -> Attributes -> IO NL80211Packet
queryOne :: NL80211Socket -> Word8 -> Bool -> Attributes -> IO NL80211Packet
queryOne (NLS NetlinkSocket
sock Word16
fid) Word8
cmd Bool
dump Attributes
attrs = NetlinkSocket -> NL80211Packet -> IO NL80211Packet
forall a.
(Convertable a, Eq a, Show a) =>
NetlinkSocket -> Packet a -> IO (Packet a)
I.queryOne NetlinkSocket
sock NL80211Packet
packet
where packet :: NL80211Packet
packet = Word16 -> Word8 -> Bool -> Attributes -> NL80211Packet
getRequestPacket Word16
fid Word8
cmd Bool
dump Attributes
attrs
query :: NL80211Socket -> Word8 -> Bool -> Attributes -> IO [NL80211Packet]
query :: NL80211Socket -> Word8 -> Bool -> Attributes -> IO [NL80211Packet]
query (NLS NetlinkSocket
sock Word16
fid) Word8
cmd Bool
dump Attributes
attrs = NetlinkSocket -> NL80211Packet -> IO [NL80211Packet]
forall a.
(Convertable a, Eq a, Show a) =>
NetlinkSocket -> Packet a -> IO [Packet a]
I.query NetlinkSocket
sock NL80211Packet
packet
where packet :: NL80211Packet
packet = Word16 -> Word8 -> Bool -> Attributes -> NL80211Packet
getRequestPacket Word16
fid Word8
cmd Bool
dump Attributes
attrs
parseInterface :: (ByteString, ByteString) -> (String, Word32)
parseInterface :: (ByteString, ByteString) -> (String, Word32)
parseInterface (ByteString
name, ByteString
ifindex) =
(ShowS
forall a. HasCallStack => [a] -> [a]
init ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ByteString -> String
unpack ByteString
name, Either String Word32 -> Word32
forall a b. Show a => Either a b -> b
getRight (Either String Word32 -> Word32) -> Either String Word32 -> Word32
forall a b. (a -> b) -> a -> b
$Get Word32 -> ByteString -> Either String Word32
forall a. Get a -> ByteString -> Either String a
runGet Get Word32
getWord32host ByteString
ifindex)
getInterfaceList :: NL80211Socket -> IO [(String, Word32)]
getInterfaceList :: NL80211Socket -> IO [(String, Word32)]
getInterfaceList NL80211Socket
sock = do
interfaces <- NL80211Socket -> Word8 -> Bool -> Attributes -> IO [NL80211Packet]
query NL80211Socket
sock Word8
forall a. Num a => a
eNL80211_CMD_GET_INTERFACE Bool
True Attributes
forall k a. Map k a
M.empty
return $ mapMaybe (fmap parseInterface . toTuple) interfaces
where toTuple :: NL80211Packet -> Maybe (ByteString, ByteString)
toTuple :: NL80211Packet -> Maybe (ByteString, ByteString)
toTuple (Packet Header
_ GenlData NoData80211
_ Attributes
attrs) = do
name <- Int -> Attributes -> Maybe ByteString
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Int
forall a. Num a => a
eNL80211_ATTR_IFNAME Attributes
attrs
findex <- M.lookup eNL80211_ATTR_IFINDEX attrs
return (name, findex)
toTuple x :: NL80211Packet
x@(ErrorMsg{}) =
String -> Maybe (ByteString, ByteString)
forall a. HasCallStack => String -> a
error (String
"Something happend while getting the interfaceList: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ NL80211Packet -> String
forall a. Show a => a -> String
show NL80211Packet
x)
toTuple (DoneMsg Header
_) = Maybe (ByteString, ByteString)
forall a. Maybe a
Nothing
getScanResults
:: NL80211Socket
-> Word32
-> IO [NL80211Packet]
getScanResults :: NL80211Socket -> Word32 -> IO [NL80211Packet]
getScanResults NL80211Socket
sock Word32
ifindex = NL80211Socket -> Word8 -> Bool -> Attributes -> IO [NL80211Packet]
query NL80211Socket
sock Word8
forall a. Num a => a
eNL80211_CMD_GET_SCAN Bool
True Attributes
attrs
where attrs :: Attributes
attrs = [(Int, ByteString)] -> Attributes
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [(Int
forall a. Num a => a
eNL80211_ATTR_IFINDEX, Put -> ByteString
runPut (Put -> ByteString) -> Put -> ByteString
forall a b. (a -> b) -> a -> b
$Putter Word32
putWord32host Word32
ifindex)]
getConnectedWifi
:: NL80211Socket
-> Word32
-> IO [NL80211Packet]
getConnectedWifi :: NL80211Socket -> Word32 -> IO [NL80211Packet]
getConnectedWifi NL80211Socket
sock Word32
ifindex = (NL80211Packet -> Bool) -> [NL80211Packet] -> [NL80211Packet]
forall a. (a -> Bool) -> [a] -> [a]
filter NL80211Packet -> Bool
isConn ([NL80211Packet] -> [NL80211Packet])
-> IO [NL80211Packet] -> IO [NL80211Packet]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NL80211Socket -> Word32 -> IO [NL80211Packet]
getScanResults NL80211Socket
sock Word32
ifindex
where isConn :: NL80211Packet -> Bool
isConn :: NL80211Packet -> Bool
isConn (Packet Header
_ GenlData NoData80211
_ Attributes
attrs) = Maybe ByteString -> Bool
hasConn (Maybe ByteString -> Bool) -> Maybe ByteString -> Bool
forall a b. (a -> b) -> a -> b
$Int -> Attributes -> Maybe ByteString
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Int
forall a. Num a => a
eNL80211_ATTR_BSS Attributes
attrs
isConn x :: NL80211Packet
x@(ErrorMsg Header
_ CInt
e NL80211Packet
_) = if CInt
e CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== (-CInt
16)
then Bool
False
else String -> Bool
forall a. HasCallStack => String -> a
error (String
"Something stupid happened" String -> ShowS
forall a. [a] -> [a] -> [a]
++ NL80211Packet -> String
forall a. Show a => a -> String
show NL80211Packet
x)
isConn (DoneMsg Header
_) = Bool
False
hasConn :: Maybe ByteString -> Bool
hasConn Maybe ByteString
Nothing = Bool
False
hasConn (Just ByteString
attrs) = Int -> Attributes -> Bool
forall k a. Ord k => k -> Map k a -> Bool
M.member Int
forall a. Num a => a
eNL80211_BSS_STATUS (Attributes -> Bool) -> Attributes -> Bool
forall a b. (a -> b) -> a -> b
$Either String Attributes -> Attributes
forall a b. Show a => Either a b -> b
getRight (Either String Attributes -> Attributes)
-> Either String Attributes -> Attributes
forall a b. (a -> b) -> a -> b
$Get Attributes -> ByteString -> Either String Attributes
forall a. Get a -> ByteString -> Either String a
runGet Get Attributes
getAttributes ByteString
attrs
getWifiAttributes :: NL80211Packet -> Maybe Attributes
getWifiAttributes :: NL80211Packet -> Maybe Attributes
getWifiAttributes (Packet Header
_ GenlData NoData80211
_ Attributes
attrs) = Either String Attributes -> Attributes
forall a b. Show a => Either a b -> b
getRight (Either String Attributes -> Attributes)
-> (ByteString -> Either String Attributes)
-> ByteString
-> Attributes
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get Attributes -> ByteString -> Either String Attributes
forall a. Get a -> ByteString -> Either String a
runGet Get Attributes
getWifiEIDs (ByteString -> Attributes) -> Maybe ByteString -> Maybe Attributes
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe ByteString
eids
where bssattrs :: Maybe Attributes
bssattrs = Either String Attributes -> Attributes
forall a b. Show a => Either a b -> b
getRight (Either String Attributes -> Attributes)
-> (ByteString -> Either String Attributes)
-> ByteString
-> Attributes
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Get Attributes -> ByteString -> Either String Attributes
forall a. Get a -> ByteString -> Either String a
runGet Get Attributes
getAttributes (ByteString -> Attributes) -> Maybe ByteString -> Maybe Attributes
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Attributes -> Maybe ByteString
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Int
forall a. Num a => a
eNL80211_ATTR_BSS Attributes
attrs
eids :: Maybe ByteString
eids = Int -> Attributes -> Maybe ByteString
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Int
forall a. Num a => a
eNL80211_BSS_INFORMATION_ELEMENTS (Attributes -> Maybe ByteString)
-> Maybe Attributes -> Maybe ByteString
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Maybe Attributes
bssattrs
getWifiAttributes x :: NL80211Packet
x@(ErrorMsg{}) = String -> Maybe Attributes
forall a. HasCallStack => String -> a
error (String
"Something stupid happened" String -> ShowS
forall a. [a] -> [a] -> [a]
++ NL80211Packet -> String
forall a. Show a => a -> String
show NL80211Packet
x)
getWifiAttributes (DoneMsg Header
_) = Maybe Attributes
forall a. Maybe a
Nothing
getPacket :: NL80211Socket -> IO [NL80211Packet]
getPacket :: NL80211Socket -> IO [NL80211Packet]
getPacket (NLS NetlinkSocket
sock Word16
_) = NetlinkSocket -> IO [NL80211Packet]
forall a.
(Convertable a, Eq a, Show a) =>
NetlinkSocket -> IO [Packet a]
I.recvOne NetlinkSocket
sock