diff options
-rw-r--r-- | include/uapi.h | 6 | ||||
-rw-r--r-- | src/Network/WireGuard/Foreign/UAPI.hsc | 29 |
2 files changed, 25 insertions, 10 deletions
diff --git a/include/uapi.h b/include/uapi.h index 9cf9b2c..130f30a 100644 --- a/include/uapi.h +++ b/include/uapi.h @@ -124,7 +124,13 @@ enum { WGDEVICE_REMOVE_PRESHARED_KEY = (1 << 2), WGDEVICE_REMOVE_FWMARK = (1 << 3) }; + +enum { + WG_API_VERSION_MAGIC = 0xbeef0001 +}; + struct wgdevice { + __u32 version_magic; /* Must be value of WG_API_VERSION_MAGIC */ char interface[IFNAMSIZ]; /* Get */ __u32 flags; /* Set */ diff --git a/src/Network/WireGuard/Foreign/UAPI.hsc b/src/Network/WireGuard/Foreign/UAPI.hsc index b3e2948..7aff338 100644 --- a/src/Network/WireGuard/Foreign/UAPI.hsc +++ b/src/Network/WireGuard/Foreign/UAPI.hsc @@ -17,6 +17,7 @@ module Network.WireGuard.Foreign.UAPI , writeConfig ) where +import Control.Monad (unless) import Data.ByteString.Internal (ByteString (..)) import Network.Socket.Internal (HostAddress, HostAddress6, SockAddr, peekSockAddr, @@ -64,6 +65,10 @@ deviceFlagRemovePrivateKey = #{const WGDEVICE_REMOVE_PRIVATE_KEY} :: DeviceF deviceFlagRemovePresharedKey = #{const WGDEVICE_REMOVE_PRESHARED_KEY} :: DeviceFlags deviceFlagRemoveFwmark = #{const WGDEVICE_REMOVE_FWMARK} :: DeviceFlags +type VersionMagicType = #{type typeof((struct wgdevice){0}.version_magic)} + +apiVersionMagic = #{const WG_API_VERSION_MAGIC } :: VersionMagicType + data WgDevice = WgDevice { deviceInterface :: ! String , deviceFlags :: ! DeviceFlags @@ -85,7 +90,7 @@ instance Storable WgIpmask where ip <- case ipFamily of #{const AF_INET} -> Left <$> #{peek struct wgipmask, ip4.s_addr} ptr #{const AF_INET6} -> Right . fromIn6Addr <$> #{peek struct wgipmask, ip6} ptr - _ -> error "WgIpmask.peek: unknown ipfamily" + _ -> fail "WgIpmask.peek: unknown ipfamily" cidr <- #{peek struct wgipmask, cidr} ptr return (WgIpmask ip cidr) @@ -137,18 +142,22 @@ instance Storable WgPeer where instance Storable WgDevice where sizeOf _ = #{size struct wgdevice} alignment _ = #{alignment struct wgdevice} - peek ptr = WgDevice <$> peekCString (ptr `plusPtr` #{offset struct wgdevice, interface}) - <*> #{peek struct wgdevice, flags} ptr - <*> (K.toByteString <$> #{peek struct wgdevice, public_key} ptr) - <*> (K.toByteString <$> #{peek struct wgdevice, private_key} ptr) - <*> (K.toByteString <$> #{peek struct wgdevice, preshared_key} ptr) - <*> #{peek struct wgdevice, fwmark} ptr - <*> #{peek struct wgdevice, port} ptr - <*> #{peek struct wgdevice, num_peers} ptr + peek ptr = do + magic <- #{peek struct wgdevice, version_magic} ptr + unless (magic == apiVersionMagic) $ fail "unexpected version_magic" + WgDevice <$> peekCString (ptr `plusPtr` #{offset struct wgdevice, interface}) + <*> #{peek struct wgdevice, flags} ptr + <*> (K.toByteString <$> #{peek struct wgdevice, public_key} ptr) + <*> (K.toByteString <$> #{peek struct wgdevice, private_key} ptr) + <*> (K.toByteString <$> #{peek struct wgdevice, preshared_key} ptr) + <*> #{peek struct wgdevice, fwmark} ptr + <*> #{peek struct wgdevice, port} ptr + <*> #{peek struct wgdevice, num_peers} ptr poke ptr self@WgDevice{..} - | length deviceInterface >= #{const IFNAMSIZ} = error "interface name is too long" + | length deviceInterface >= #{const IFNAMSIZ} = fail "interface name is too long" | otherwise = do zeroMemory ptr $ fromIntegral $ sizeOf self + #{poke struct wgdevice, version_magic} ptr apiVersionMagic pokeArray0 (0 :: Word8) (ptr `plusPtr` #{offset struct wgdevice, interface}) (map (fromIntegral.ord) deviceInterface) #{poke struct wgdevice, flags} ptr deviceFlags #{poke struct wgdevice, public_key} ptr (K.fromByteString devicePubkey) |