packages feed

snmp 0.2.1.1 → 0.3.0.0

raw patch · 15 files changed

+1222/−1887 lines, 15 filesdep +cryptonitedep +ipdep +language-asndep −asn1-encodingdep −asn1-parsedep −asn1-typesdep ~basedep ~bytestringdep ~containerssetup-changednew-uploaderPVP ok

version bump matches the API change (PVP)

Dependencies added: cryptonite, ip, language-asn, memory, stm, vector

Dependencies removed: asn1-encoding, asn1-parse, asn1-types, async, binary, cipher-aes, cipher-des, crypto-cipher-types, cryptohash, mtl, network-info, random, securemem, text, time

Dependency ranges changed: base, bytestring, containers, network

API changes (from Hackage documentation)

- Network.Protocol.Snmp: AES :: PrivType
- Network.Protocol.Snmp: AuthNoPriv :: PrivAuth
- Network.Protocol.Snmp: AuthPriv :: PrivAuth
- Network.Protocol.Snmp: Community :: ByteString -> Community
- Network.Protocol.Snmp: ContextEngineID :: ByteString -> ContextEngineID
- Network.Protocol.Snmp: ContextName :: ByteString -> ContextName
- Network.Protocol.Snmp: Counter32 :: Word32 -> Value
- Network.Protocol.Snmp: Counter64 :: Word64 -> Value
- Network.Protocol.Snmp: Coupla :: OID -> Value -> Coupla
- Network.Protocol.Snmp: CryptedPDU :: ByteString -> PDU V3
- Network.Protocol.Snmp: DES :: PrivType
- Network.Protocol.Snmp: EndOfMibView :: Value
- Network.Protocol.Snmp: Flag :: Reportable -> PrivAuth -> Flag
- Network.Protocol.Snmp: Gauge32 :: Word32 -> Value
- Network.Protocol.Snmp: GetBulk :: RequestId -> ErrorStatus -> ErrorIndex -> Request
- Network.Protocol.Snmp: GetNextRequest :: RequestId -> ErrorStatus -> ErrorIndex -> Request
- Network.Protocol.Snmp: GetRequest :: RequestId -> ErrorStatus -> ErrorIndex -> Request
- Network.Protocol.Snmp: GetResponse :: RequestId -> ErrorStatus -> ErrorIndex -> Request
- Network.Protocol.Snmp: ID :: Int32 -> ID
- Network.Protocol.Snmp: Inform :: RequestId -> ErrorStatus -> ErrorIndex -> Request
- Network.Protocol.Snmp: Integer :: Int32 -> Value
- Network.Protocol.Snmp: IpAddress :: Word8 -> Word8 -> Word8 -> Word8 -> Value
- Network.Protocol.Snmp: MD5 :: AuthType
- Network.Protocol.Snmp: MaxSize :: Integer -> MaxSize
- Network.Protocol.Snmp: NoAuthNoPriv :: PrivAuth
- Network.Protocol.Snmp: NoSuchInstance :: Value
- Network.Protocol.Snmp: NoSuchObject :: Value
- Network.Protocol.Snmp: OI :: OID -> Value
- Network.Protocol.Snmp: Opaque :: ByteString -> Value
- Network.Protocol.Snmp: Report :: RequestId -> ErrorStatus -> ErrorIndex -> Request
- Network.Protocol.Snmp: SHA :: AuthType
- Network.Protocol.Snmp: SecurityParameter :: ByteString -> Int32 -> Int32 -> ByteString -> ByteString -> ByteString -> SecurityParameter
- Network.Protocol.Snmp: ServerException :: Integer -> ClientException
- Network.Protocol.Snmp: SetRequest :: RequestId -> ErrorStatus -> ErrorIndex -> Request
- Network.Protocol.Snmp: String :: ByteString -> Value
- Network.Protocol.Snmp: Suite :: [Coupla] -> Suite
- Network.Protocol.Snmp: TimeTicks :: Word32 -> Value
- Network.Protocol.Snmp: TimeoutException :: ClientException
- Network.Protocol.Snmp: UserBasedSecurityModel :: SecurityModel
- Network.Protocol.Snmp: V2Trap :: RequestId -> ErrorStatus -> ErrorIndex -> Request
- Network.Protocol.Snmp: Version1 :: Version
- Network.Protocol.Snmp: Version2 :: Version
- Network.Protocol.Snmp: Version3 :: Version
- Network.Protocol.Snmp: Zero :: Value
- Network.Protocol.Snmp: ZeroDotZero :: Value
- Network.Protocol.Snmp: aesDecrypt :: Key -> Salt -> EngineBootId -> EngineTime -> Encrypted -> Raw
- Network.Protocol.Snmp: aesEncrypt :: Key -> EngineBootId -> EngineTime -> Rand64 -> Raw -> (Encrypted, Salt)
- Network.Protocol.Snmp: authenticationParameters :: SecurityParameter -> ByteString
- Network.Protocol.Snmp: authoritiveEngineBoots :: SecurityParameter -> Int32
- Network.Protocol.Snmp: authoritiveEngineId :: SecurityParameter -> ByteString
- Network.Protocol.Snmp: authoritiveEngineTime :: SecurityParameter -> Int32
- Network.Protocol.Snmp: class Construct a
- Network.Protocol.Snmp: class HasItem a
- Network.Protocol.Snmp: class HasV2 a
- Network.Protocol.Snmp: class HasV3 a
- Network.Protocol.Snmp: cleanPass :: ByteString
- Network.Protocol.Snmp: data AuthType
- Network.Protocol.Snmp: data ClientException
- Network.Protocol.Snmp: data Coupla
- Network.Protocol.Snmp: data Flag
- Network.Protocol.Snmp: data Header a
- Network.Protocol.Snmp: data PDU a
- Network.Protocol.Snmp: data Packet
- Network.Protocol.Snmp: data PrivAuth
- Network.Protocol.Snmp: data PrivType
- Network.Protocol.Snmp: data Request
- Network.Protocol.Snmp: data SecurityModel
- Network.Protocol.Snmp: data SecurityParameter
- Network.Protocol.Snmp: data V2
- Network.Protocol.Snmp: data V3
- Network.Protocol.Snmp: data Value
- Network.Protocol.Snmp: data Version
- Network.Protocol.Snmp: desDecrypt :: Key -> Salt -> Encrypted -> Raw
- Network.Protocol.Snmp: desEncrypt :: Key -> EngineBootId -> Rand32 -> Raw -> (Encrypted, Salt)
- Network.Protocol.Snmp: ei :: Request -> ErrorIndex
- Network.Protocol.Snmp: es :: Request -> ErrorStatus
- Network.Protocol.Snmp: getAuthenticationParameters :: HasV3 a => Header a -> ByteString
- Network.Protocol.Snmp: getAuthenticationParametersP :: Packet -> ByteString
- Network.Protocol.Snmp: getAuthoritiveEngineBoots :: HasV3 a => Header a -> Int32
- Network.Protocol.Snmp: getAuthoritiveEngineId :: HasV3 a => Header a -> ByteString
- Network.Protocol.Snmp: getAuthoritiveEngineTime :: HasV3 a => Header a -> Int32
- Network.Protocol.Snmp: getCommunity :: HasV2 a => Header a -> Community
- Network.Protocol.Snmp: getContextEngineID :: HasV3 a => PDU a -> ContextEngineID
- Network.Protocol.Snmp: getContextName :: HasV3 a => PDU a -> ContextName
- Network.Protocol.Snmp: getEngineBootsP :: Packet -> EngineBootId
- Network.Protocol.Snmp: getEngineIdP :: Packet -> EngineId
- Network.Protocol.Snmp: getEngineTimeP :: Packet -> Int32
- Network.Protocol.Snmp: getErrorStatus :: Packet -> ErrorStatus
- Network.Protocol.Snmp: getFlag :: HasV3 a => Header a -> Flag
- Network.Protocol.Snmp: getHeader :: HasItem a => Packet -> Header a
- Network.Protocol.Snmp: getID :: HasV3 a => Header a -> ID
- Network.Protocol.Snmp: getMaxSize :: HasV3 a => Header a -> MaxSize
- Network.Protocol.Snmp: getPDU :: HasItem a => Packet -> PDU a
- Network.Protocol.Snmp: getPrivParametersP :: Packet -> ByteString
- Network.Protocol.Snmp: getPrivacyParameters :: HasV3 a => Header a -> ByteString
- Network.Protocol.Snmp: getRequest :: Packet -> Request
- Network.Protocol.Snmp: getRid :: Packet -> RequestId
- Network.Protocol.Snmp: getSecurityModel :: HasV3 a => Header a -> SecurityModel
- Network.Protocol.Snmp: getSecurityParameter :: HasV3 a => Header a -> SecurityParameter
- Network.Protocol.Snmp: getSuite :: Packet -> Suite
- Network.Protocol.Snmp: getUserName :: HasV3 a => Header a -> ByteString
- Network.Protocol.Snmp: getVersion :: Packet -> Version
- Network.Protocol.Snmp: initial :: Construct a => a
- Network.Protocol.Snmp: instance ASN1Object (Header V2)
- Network.Protocol.Snmp: instance ASN1Object (Header V3)
- Network.Protocol.Snmp: instance ASN1Object (PDU V2)
- Network.Protocol.Snmp: instance ASN1Object (PDU V3)
- Network.Protocol.Snmp: instance ASN1Object Community
- Network.Protocol.Snmp: instance ASN1Object Flag
- Network.Protocol.Snmp: instance ASN1Object ID
- Network.Protocol.Snmp: instance ASN1Object MaxSize
- Network.Protocol.Snmp: instance ASN1Object Packet
- Network.Protocol.Snmp: instance ASN1Object SecurityModel
- Network.Protocol.Snmp: instance ASN1Object SecurityParameter
- Network.Protocol.Snmp: instance ASN1Object Suite
- Network.Protocol.Snmp: instance ASN1Object Value
- Network.Protocol.Snmp: instance ASN1Object Version
- Network.Protocol.Snmp: instance Binary (PDU V3)
- Network.Protocol.Snmp: instance Binary Packet
- Network.Protocol.Snmp: instance Construct (Header V2)
- Network.Protocol.Snmp: instance Construct (Header V3)
- Network.Protocol.Snmp: instance Construct (PDU V2)
- Network.Protocol.Snmp: instance Construct (PDU V3)
- Network.Protocol.Snmp: instance Construct (Version -> Packet)
- Network.Protocol.Snmp: instance Construct Request
- Network.Protocol.Snmp: instance Construct SecurityParameter
- Network.Protocol.Snmp: instance Construct Suite
- Network.Protocol.Snmp: instance Eq (Header a)
- Network.Protocol.Snmp: instance Eq (PDU a)
- Network.Protocol.Snmp: instance Eq AuthType
- Network.Protocol.Snmp: instance Eq ClientException
- Network.Protocol.Snmp: instance Eq Community
- Network.Protocol.Snmp: instance Eq ContextEngineID
- Network.Protocol.Snmp: instance Eq ContextName
- Network.Protocol.Snmp: instance Eq Coupla
- Network.Protocol.Snmp: instance Eq Flag
- Network.Protocol.Snmp: instance Eq ID
- Network.Protocol.Snmp: instance Eq MaxSize
- Network.Protocol.Snmp: instance Eq Packet
- Network.Protocol.Snmp: instance Eq PrivAuth
- Network.Protocol.Snmp: instance Eq PrivType
- Network.Protocol.Snmp: instance Eq Request
- Network.Protocol.Snmp: instance Eq SecurityModel
- Network.Protocol.Snmp: instance Eq SecurityParameter
- Network.Protocol.Snmp: instance Eq Suite
- Network.Protocol.Snmp: instance Eq Value
- Network.Protocol.Snmp: instance Eq Version
- Network.Protocol.Snmp: instance Exception ClientException
- Network.Protocol.Snmp: instance HasItem V2
- Network.Protocol.Snmp: instance HasItem V3
- Network.Protocol.Snmp: instance HasV2 V2
- Network.Protocol.Snmp: instance HasV3 V3
- Network.Protocol.Snmp: instance Monoid Suite
- Network.Protocol.Snmp: instance Show (Header a)
- Network.Protocol.Snmp: instance Show (PDU a)
- Network.Protocol.Snmp: instance Show AuthType
- Network.Protocol.Snmp: instance Show ClientException
- Network.Protocol.Snmp: instance Show Community
- Network.Protocol.Snmp: instance Show ContextEngineID
- Network.Protocol.Snmp: instance Show ContextName
- Network.Protocol.Snmp: instance Show Coupla
- Network.Protocol.Snmp: instance Show Flag
- Network.Protocol.Snmp: instance Show ID
- Network.Protocol.Snmp: instance Show MaxSize
- Network.Protocol.Snmp: instance Show Packet
- Network.Protocol.Snmp: instance Show PrivAuth
- Network.Protocol.Snmp: instance Show PrivType
- Network.Protocol.Snmp: instance Show Request
- Network.Protocol.Snmp: instance Show SecurityModel
- Network.Protocol.Snmp: instance Show SecurityParameter
- Network.Protocol.Snmp: instance Show Suite
- Network.Protocol.Snmp: instance Show Value
- Network.Protocol.Snmp: instance Show Version
- Network.Protocol.Snmp: instance Typeable ClientException
- Network.Protocol.Snmp: newtype Community
- Network.Protocol.Snmp: newtype ContextEngineID
- Network.Protocol.Snmp: newtype ContextName
- Network.Protocol.Snmp: newtype ID
- Network.Protocol.Snmp: newtype MaxSize
- Network.Protocol.Snmp: newtype Suite
- Network.Protocol.Snmp: oid :: Coupla -> OID
- Network.Protocol.Snmp: passwordToKey :: AuthType -> Password -> EngineId -> Key
- Network.Protocol.Snmp: privacyParameters :: SecurityParameter -> ByteString
- Network.Protocol.Snmp: rid :: Request -> RequestId
- Network.Protocol.Snmp: setAuthenticationParameters :: HasV3 a => ByteString -> Header a -> Header a
- Network.Protocol.Snmp: setAuthenticationParametersP :: ByteString -> Packet -> Packet
- Network.Protocol.Snmp: setAuthoritiveEngineBoots :: HasV3 a => Int32 -> Header a -> Header a
- Network.Protocol.Snmp: setAuthoritiveEngineId :: HasV3 a => ByteString -> Header a -> Header a
- Network.Protocol.Snmp: setAuthoritiveEngineTime :: HasV3 a => Int32 -> Header a -> Header a
- Network.Protocol.Snmp: setCommunity :: HasV2 a => Community -> Header a -> Header a
- Network.Protocol.Snmp: setCommunityP :: Community -> Packet -> Packet
- Network.Protocol.Snmp: setContextEngineID :: HasV3 a => ContextEngineID -> PDU a -> PDU a
- Network.Protocol.Snmp: setContextName :: HasV3 a => ContextName -> PDU a -> PDU a
- Network.Protocol.Snmp: setEngineBootsP :: EngineBootId -> Packet -> Packet
- Network.Protocol.Snmp: setEngineIdP :: EngineId -> Packet -> Packet
- Network.Protocol.Snmp: setEngineTimeP :: Int32 -> Packet -> Packet
- Network.Protocol.Snmp: setErrorStatus :: ErrorStatus -> Packet -> Packet
- Network.Protocol.Snmp: setFlag :: HasV3 a => Flag -> Header a -> Header a
- Network.Protocol.Snmp: setHeader :: HasItem a => Header a -> Packet -> Packet
- Network.Protocol.Snmp: setID :: HasV3 a => ID -> Header a -> Header a
- Network.Protocol.Snmp: setIDP :: ID -> Packet -> Packet
- Network.Protocol.Snmp: setMaxSize :: HasV3 a => MaxSize -> Header a -> Header a
- Network.Protocol.Snmp: setMaxSizeP :: MaxSize -> Packet -> Packet
- Network.Protocol.Snmp: setPDU :: HasItem a => PDU a -> Packet -> Packet
- Network.Protocol.Snmp: setPrivAuthP :: PrivAuth -> Packet -> Packet
- Network.Protocol.Snmp: setPrivParametersP :: ByteString -> Packet -> Packet
- Network.Protocol.Snmp: setPrivacyParameters :: HasV3 a => ByteString -> Header a -> Header a
- Network.Protocol.Snmp: setReportableP :: Reportable -> Packet -> Packet
- Network.Protocol.Snmp: setRequest :: Request -> Packet -> Packet
- Network.Protocol.Snmp: setRid :: RequestId -> Packet -> Packet
- Network.Protocol.Snmp: setSecurityModel :: HasV3 a => SecurityModel -> Header a -> Header a
- Network.Protocol.Snmp: setSecurityParameter :: HasV3 a => SecurityParameter -> Header a -> Header a
- Network.Protocol.Snmp: setSuite :: Suite -> Packet -> Packet
- Network.Protocol.Snmp: setUserName :: HasV3 a => ByteString -> Header a -> Header a
- Network.Protocol.Snmp: setUserNameP :: ByteString -> Packet -> Packet
- Network.Protocol.Snmp: signPacket :: AuthType -> Key -> Packet -> Packet
- Network.Protocol.Snmp: toSalt :: Int32 -> Int32 -> ByteString
- Network.Protocol.Snmp: type Encrypted = ByteString
- Network.Protocol.Snmp: type EngineBootId = Int32
- Network.Protocol.Snmp: type EngineId = ByteString
- Network.Protocol.Snmp: type EngineTime = Int32
- Network.Protocol.Snmp: type ErrorIndex = Integer
- Network.Protocol.Snmp: type ErrorStatus = Integer
- Network.Protocol.Snmp: type Key = ByteString
- Network.Protocol.Snmp: type OID = [Integer]
- Network.Protocol.Snmp: type OIDS = [OID]
- Network.Protocol.Snmp: type Password = ByteString
- Network.Protocol.Snmp: type PrivacyParameter = ByteString
- Network.Protocol.Snmp: type Rand32 = Int32
- Network.Protocol.Snmp: type Rand64 = Int64
- Network.Protocol.Snmp: type Raw = ByteString
- Network.Protocol.Snmp: type Reportable = Bool
- Network.Protocol.Snmp: type RequestId = Int32
- Network.Protocol.Snmp: type Salt = ByteString
- Network.Protocol.Snmp: userName :: SecurityParameter -> ByteString
- Network.Protocol.Snmp: value :: Coupla -> Value
- Network.Snmp.Client: AuthNoPriv :: PrivAuth
- Network.Snmp.Client: AuthPriv :: PrivAuth
- Network.Snmp.Client: Community :: ByteString -> Community
- Network.Snmp.Client: ConfigV1 :: Hostname -> Port -> Int -> Community -> Config
- Network.Snmp.Client: ConfigV2 :: Hostname -> Port -> Int -> Community -> Config
- Network.Snmp.Client: ConfigV3 :: Hostname -> Port -> Int -> Login -> Password -> Password -> PrivAuth -> ByteString -> AuthType -> PrivType -> Config
- Network.Snmp.Client: Counter32 :: Word32 -> Value
- Network.Snmp.Client: Counter64 :: Word64 -> Value
- Network.Snmp.Client: Coupla :: OID -> Value -> Coupla
- Network.Snmp.Client: Gauge32 :: Word32 -> Value
- Network.Snmp.Client: Integer :: Int32 -> Value
- Network.Snmp.Client: IpAddress :: Word8 -> Word8 -> Word8 -> Word8 -> Value
- Network.Snmp.Client: MD5 :: AuthType
- Network.Snmp.Client: NoAuthNoPriv :: PrivAuth
- Network.Snmp.Client: OI :: OID -> Value
- Network.Snmp.Client: Opaque :: ByteString -> Value
- Network.Snmp.Client: SHA :: AuthType
- Network.Snmp.Client: String :: ByteString -> Value
- Network.Snmp.Client: Suite :: [Coupla] -> Suite
- Network.Snmp.Client: TimeTicks :: Word32 -> Value
- Network.Snmp.Client: Version1 :: Version
- Network.Snmp.Client: Version2 :: Version
- Network.Snmp.Client: Version3 :: Version
- Network.Snmp.Client: Zero :: Value
- Network.Snmp.Client: ZeroDotZero :: Value
- Network.Snmp.Client: authPass :: Config -> Password
- Network.Snmp.Client: authType :: Config -> AuthType
- Network.Snmp.Client: bulkget :: Client -> OIDS -> IO Suite
- Network.Snmp.Client: bulkwalk :: Client -> OIDS -> IO Suite
- Network.Snmp.Client: client :: Config -> IO Client
- Network.Snmp.Client: close :: Client -> IO ()
- Network.Snmp.Client: community :: Config -> Community
- Network.Snmp.Client: context :: Config -> ByteString
- Network.Snmp.Client: data AuthType
- Network.Snmp.Client: data Client
- Network.Snmp.Client: data Config
- Network.Snmp.Client: data Coupla
- Network.Snmp.Client: data PrivAuth
- Network.Snmp.Client: data Value
- Network.Snmp.Client: data Version
- Network.Snmp.Client: get :: Client -> OIDS -> IO Suite
- Network.Snmp.Client: getnext :: Client -> OIDS -> IO Suite
- Network.Snmp.Client: hostname :: Config -> Hostname
- Network.Snmp.Client: newtype Community
- Network.Snmp.Client: newtype Suite
- Network.Snmp.Client: oid :: Coupla -> OID
- Network.Snmp.Client: oidFromBS :: ByteString -> [Integer]
- Network.Snmp.Client: port :: Config -> Port
- Network.Snmp.Client: privPass :: Config -> Password
- Network.Snmp.Client: privType :: Config -> PrivType
- Network.Snmp.Client: sequrityLevel :: Config -> PrivAuth
- Network.Snmp.Client: sequrityName :: Config -> Login
- Network.Snmp.Client: set :: Client -> Suite -> IO Suite
- Network.Snmp.Client: timeout :: Config -> Int
- Network.Snmp.Client: type Hostname = String
- Network.Snmp.Client: type Login = ByteString
- Network.Snmp.Client: type Password = ByteString
- Network.Snmp.Client: type Port = String
- Network.Snmp.Client: value :: Coupla -> Value
- Network.Snmp.Client: walk :: Client -> OIDS -> IO Suite
+ Snmp.Client: Config :: !Int -> !Int -> !Int -> Config
+ Snmp.Client: Context :: !Session -> !Destination -> !Credentials -> Context
+ Snmp.Client: CredentialsConstructV2 :: CredentialsV2 -> Credentials
+ Snmp.Client: CredentialsConstructV3 :: CredentialsV3 -> Credentials
+ Snmp.Client: CredentialsV2 :: ByteString -> CredentialsV2
+ Snmp.Client: CredentialsV3 :: !Crypto -> !ByteString -> !ByteString -> CredentialsV3
+ Snmp.Client: Destination :: !IPv4 -> !Word16 -> Destination
+ Snmp.Client: PerHostV3 :: !EngineId -> !Int32 -> !Int32 -> PerHostV3
+ Snmp.Client: Session :: !Chan Socket -> !Int -> !TVar RequestId -> !TVar AesSalt -> !Int -> !Int -> !IORef (Map (AuthType, ByteString, EngineId) ByteString) -> Session
+ Snmp.Client: SnmpExceptionAuthenticationFailure :: !ByteString -> !ByteString -> SnmpException
+ Snmp.Client: SnmpExceptionBadEngineId :: !MessageV3 -> !MessageV3 -> SnmpException
+ Snmp.Client: SnmpExceptionDecoding :: !String -> SnmpException
+ Snmp.Client: SnmpExceptionDecryptionFailure :: SnmpException
+ Snmp.Client: SnmpExceptionEndOfMibView :: SnmpException
+ Snmp.Client: SnmpExceptionMismatchedBinding :: !ObjectIdentifier -> !ObjectIdentifier -> SnmpException
+ Snmp.Client: SnmpExceptionMissedResponse :: !RequestId -> !RequestId -> SnmpException
+ Snmp.Client: SnmpExceptionMultipleBindings :: !Int -> SnmpException
+ Snmp.Client: SnmpExceptionNoSuchInstance :: !ObjectIdentifier -> SnmpException
+ Snmp.Client: SnmpExceptionNoSuchObject :: !ObjectIdentifier -> SnmpException
+ Snmp.Client: SnmpExceptionNonPduResponseV2 :: !MessageV2 -> SnmpException
+ Snmp.Client: SnmpExceptionNonPduResponseV3 :: !MessageV3 -> SnmpException
+ Snmp.Client: SnmpExceptionNotAllBytesSent :: !Int -> !Int -> SnmpException
+ Snmp.Client: SnmpExceptionPduError :: !ErrorStatus -> !ErrorIndex -> SnmpException
+ Snmp.Client: SnmpExceptionSocketClosed :: SnmpException
+ Snmp.Client: SnmpExceptionTimeout :: SnmpException
+ Snmp.Client: SnmpExceptionTimeoutV3 :: !MessageV3 -> SnmpException
+ Snmp.Client: SnmpExceptionUnspecified :: SnmpException
+ Snmp.Client: [configRetries] :: Config -> !Int
+ Snmp.Client: [configSocketPoolSize] :: Config -> !Int
+ Snmp.Client: [configTimeoutMicroseconds] :: Config -> !Int
+ Snmp.Client: [contextCredentials] :: Context -> !Credentials
+ Snmp.Client: [contextDestination] :: Context -> !Destination
+ Snmp.Client: [contextSession] :: Context -> !Session
+ Snmp.Client: [credentialsV2CommunityString] :: CredentialsV2 -> ByteString
+ Snmp.Client: [credentialsV3ContextName] :: CredentialsV3 -> !ByteString
+ Snmp.Client: [credentialsV3Crypto] :: CredentialsV3 -> !Crypto
+ Snmp.Client: [credentialsV3User] :: CredentialsV3 -> !ByteString
+ Snmp.Client: [destinationHost] :: Destination -> !IPv4
+ Snmp.Client: [destinationPort] :: Destination -> !Word16
+ Snmp.Client: [perHostV3AuthoritativeEngineId] :: PerHostV3 -> !EngineId
+ Snmp.Client: [perHostV3ReceiverBoots] :: PerHostV3 -> !Int32
+ Snmp.Client: [perHostV3ReceiverTime] :: PerHostV3 -> !Int32
+ Snmp.Client: [sessionAesSalt] :: Session -> !TVar AesSalt
+ Snmp.Client: [sessionKeyCache] :: Session -> !IORef (Map (AuthType, ByteString, EngineId) ByteString)
+ Snmp.Client: [sessionMaxTries] :: Session -> !Int
+ Snmp.Client: [sessionRequestId] :: Session -> !TVar RequestId
+ Snmp.Client: [sessionSocketCount] :: Session -> !Int
+ Snmp.Client: [sessionSockets] :: Session -> !Chan Socket
+ Snmp.Client: [sessionTimeoutMicroseconds] :: Session -> !Int
+ Snmp.Client: closeSession :: Session -> IO ()
+ Snmp.Client: data Config
+ Snmp.Client: data Context
+ Snmp.Client: data Credentials
+ Snmp.Client: data CredentialsV3
+ Snmp.Client: data Destination
+ Snmp.Client: data PerHostV3
+ Snmp.Client: data Session
+ Snmp.Client: data SnmpException
+ Snmp.Client: get :: Context -> ObjectIdentifier -> IO ObjectSyntax
+ Snmp.Client: get' :: Context -> ObjectIdentifier -> IO (Either SnmpException ObjectSyntax)
+ Snmp.Client: getBulkChildren :: Context -> Int -> ObjectIdentifier -> IO (Vector (ObjectIdentifier, ObjectSyntax))
+ Snmp.Client: getBulkChildren' :: Context -> Int -> ObjectIdentifier -> IO (Either SnmpException (Vector (ObjectIdentifier, ObjectSyntax)))
+ Snmp.Client: getBulkStep :: Context -> Int -> ObjectIdentifier -> IO (Vector (ObjectIdentifier, ObjectSyntax))
+ Snmp.Client: getBulkStep' :: Context -> Int -> ObjectIdentifier -> IO (Either SnmpException (Vector (ObjectIdentifier, ObjectSyntax)))
+ Snmp.Client: instance GHC.Classes.Eq Snmp.Client.Config
+ Snmp.Client: instance GHC.Classes.Eq Snmp.Client.Credentials
+ Snmp.Client: instance GHC.Classes.Eq Snmp.Client.CredentialsV2
+ Snmp.Client: instance GHC.Classes.Eq Snmp.Client.CredentialsV3
+ Snmp.Client: instance GHC.Classes.Eq Snmp.Client.Destination
+ Snmp.Client: instance GHC.Classes.Eq Snmp.Client.SnmpException
+ Snmp.Client: instance GHC.Exception.Type.Exception Snmp.Client.SnmpException
+ Snmp.Client: instance GHC.Show.Show Snmp.Client.Config
+ Snmp.Client: instance GHC.Show.Show Snmp.Client.Credentials
+ Snmp.Client: instance GHC.Show.Show Snmp.Client.CredentialsV2
+ Snmp.Client: instance GHC.Show.Show Snmp.Client.CredentialsV3
+ Snmp.Client: instance GHC.Show.Show Snmp.Client.Destination
+ Snmp.Client: instance GHC.Show.Show Snmp.Client.SnmpException
+ Snmp.Client: newtype CredentialsV2
+ Snmp.Client: openSession :: Config -> IO Session
+ Snmp.Decoding: applicationSyntax :: AsnDecoding ApplicationSyntax
+ Snmp.Decoding: bindingResult :: AsnDecoding BindingResult
+ Snmp.Decoding: bulkPdu :: AsnDecoding BulkPdu
+ Snmp.Decoding: genericTrap :: AsnDecoding GenericTrap
+ Snmp.Decoding: headerData :: AsnDecoding HeaderData
+ Snmp.Decoding: messageV2 :: AsnDecoding MessageV2
+ Snmp.Decoding: messageV3 :: AsnDecoding MessageV3
+ Snmp.Decoding: objectSyntax :: AsnDecoding ObjectSyntax
+ Snmp.Decoding: pdu :: AsnDecoding Pdu
+ Snmp.Decoding: pdus :: AsnDecoding Pdus
+ Snmp.Decoding: scopedPdu :: AsnDecoding ScopedPdu
+ Snmp.Decoding: scopedPduDataDecoding :: AsnDecoding ScopedPduData
+ Snmp.Decoding: simpleSyntax :: AsnDecoding SimpleSyntax
+ Snmp.Decoding: trapPdu :: AsnDecoding TrapPdu
+ Snmp.Decoding: usm :: AsnDecoding Usm
+ Snmp.Decoding: varBind :: AsnDecoding VarBind
+ Snmp.Encoding: aesDecrypt :: ByteString -> ByteString -> Int32 -> Int32 -> ByteString -> Maybe ByteString
+ Snmp.Encoding: aesEncrypt :: ByteString -> Int32 -> Int32 -> AesSalt -> ByteString -> (ByteString, ByteString)
+ Snmp.Encoding: applicationSyntax :: AsnEncoding ApplicationSyntax
+ Snmp.Encoding: bindingResult :: AsnEncoding BindingResult
+ Snmp.Encoding: bulkPdu :: AsnEncoding BulkPdu
+ Snmp.Encoding: checkSign :: AuthType -> ByteString -> MessageV3 -> Maybe (ByteString, ByteString)
+ Snmp.Encoding: defaultAuthParams :: AuthParameters
+ Snmp.Encoding: defaultEngineId :: EngineId
+ Snmp.Encoding: defaultObjectIdentifier :: ObjectIdentifier
+ Snmp.Encoding: defaultPdu :: Pdu
+ Snmp.Encoding: defaultPrivParams :: PrivParameters
+ Snmp.Encoding: defaultScopedPdu :: ScopedPdu
+ Snmp.Encoding: defaultUsm :: Usm
+ Snmp.Encoding: desDecrypt :: ByteString -> ByteString -> ByteString -> Maybe ByteString
+ Snmp.Encoding: desEncrypt :: ByteString -> Int32 -> Int32 -> ByteString -> (ByteString, ByteString)
+ Snmp.Encoding: hash :: AuthType -> ByteString -> ByteString
+ Snmp.Encoding: hashlazy :: AuthType -> ByteString -> ByteString
+ Snmp.Encoding: headerData :: AsnEncoding HeaderData
+ Snmp.Encoding: hmacEncodedMessage :: AuthType -> ByteString -> ByteString -> ByteString
+ Snmp.Encoding: messageV2 :: AsnEncoding MessageV2
+ Snmp.Encoding: messageV3 :: AsnEncoding MessageV3
+ Snmp.Encoding: mkCipher :: Cipher c => ByteString -> c
+ Snmp.Encoding: mkSign :: AuthType -> ByteString -> ByteString -> ByteString
+ Snmp.Encoding: objectSyntax :: AsnEncoding ObjectSyntax
+ Snmp.Encoding: passwordToKey :: AuthType -> ByteString -> EngineId -> ByteString
+ Snmp.Encoding: pdu :: AsnEncoding Pdu
+ Snmp.Encoding: pdus :: AsnEncoding Pdus
+ Snmp.Encoding: resetAuthParams :: MessageV3 -> MessageV3
+ Snmp.Encoding: scopedPdu :: AsnEncoding ScopedPdu
+ Snmp.Encoding: scopedPduDataEncoding :: AsnEncoding ScopedPduData
+ Snmp.Encoding: simpleSyntax :: AsnEncoding SimpleSyntax
+ Snmp.Encoding: stripBS :: ByteString -> ByteString
+ Snmp.Encoding: tagFromInt :: Int -> Tag
+ Snmp.Encoding: toSalt :: Int32 -> Int32 -> ByteString
+ Snmp.Encoding: trapPdu :: AsnEncoding TrapPdu
+ Snmp.Encoding: usm :: AsnEncoding Usm
+ Snmp.Encoding: varBind :: AsnEncoding VarBind
+ Snmp.Encoding: wToBs :: Word64 -> ByteString
+ Snmp.Types: AesSalt :: Word64 -> AesSalt
+ Snmp.Types: ApplicationSyntaxArbitrary :: !ByteString -> ApplicationSyntax
+ Snmp.Types: ApplicationSyntaxBigCounter :: !Word64 -> ApplicationSyntax
+ Snmp.Types: ApplicationSyntaxCounter :: !Word32 -> ApplicationSyntax
+ Snmp.Types: ApplicationSyntaxIpAddress :: !Word32 -> ApplicationSyntax
+ Snmp.Types: ApplicationSyntaxTimeTicks :: !Word32 -> ApplicationSyntax
+ Snmp.Types: ApplicationSyntaxUnsignedInteger :: !Word32 -> ApplicationSyntax
+ Snmp.Types: AuthNoPriv :: !AuthParameters -> Crypto
+ Snmp.Types: AuthParameters :: !AuthType -> !ByteString -> AuthParameters
+ Snmp.Types: AuthPriv :: !AuthParameters -> !PrivParameters -> Crypto
+ Snmp.Types: AuthTypeMd5 :: AuthType
+ Snmp.Types: AuthTypeSha :: AuthType
+ Snmp.Types: BindingResultEndOfMibView :: BindingResult
+ Snmp.Types: BindingResultNoSuchInstance :: BindingResult
+ Snmp.Types: BindingResultNoSuchObject :: BindingResult
+ Snmp.Types: BindingResultUnspecified :: BindingResult
+ Snmp.Types: BindingResultValue :: !ObjectSyntax -> BindingResult
+ Snmp.Types: BulkPdu :: !RequestId -> !Int32 -> !Int32 -> !Vector VarBind -> BulkPdu
+ Snmp.Types: EngineId :: ByteString -> EngineId
+ Snmp.Types: ErrorIndex :: Int32 -> ErrorIndex
+ Snmp.Types: ErrorStatus :: Integer -> ErrorStatus
+ Snmp.Types: GenericTrapAuthenticationFailure :: GenericTrap
+ Snmp.Types: GenericTrapColdStart :: GenericTrap
+ Snmp.Types: GenericTrapEgpNeighborLoss :: GenericTrap
+ Snmp.Types: GenericTrapEnterpriseSpecific :: GenericTrap
+ Snmp.Types: GenericTrapLinkDown :: GenericTrap
+ Snmp.Types: GenericTrapLinkUp :: GenericTrap
+ Snmp.Types: GenericTrapWarmStart :: GenericTrap
+ Snmp.Types: HeaderData :: !RequestId -> !Int32 -> !Word8 -> HeaderData
+ Snmp.Types: MessageV2 :: !ByteString -> !Pdus -> MessageV2
+ Snmp.Types: MessageV3 :: !HeaderData -> !Usm -> !ScopedPduData -> MessageV3
+ Snmp.Types: NoAuthNoPriv :: Crypto
+ Snmp.Types: ObjectSyntaxApplication :: !ApplicationSyntax -> ObjectSyntax
+ Snmp.Types: ObjectSyntaxSimple :: !SimpleSyntax -> ObjectSyntax
+ Snmp.Types: Pdu :: !RequestId -> !ErrorStatus -> !ErrorIndex -> !Vector VarBind -> Pdu
+ Snmp.Types: PdusGetBulkRequest :: !BulkPdu -> Pdus
+ Snmp.Types: PdusGetNextRequest :: !Pdu -> Pdus
+ Snmp.Types: PdusGetRequest :: !Pdu -> Pdus
+ Snmp.Types: PdusInformRequest :: !Pdu -> Pdus
+ Snmp.Types: PdusReport :: !Pdu -> Pdus
+ Snmp.Types: PdusResponse :: !Pdu -> Pdus
+ Snmp.Types: PdusSetRequest :: !Pdu -> Pdus
+ Snmp.Types: PdusSnmpTrap :: !TrapPdu -> Pdus
+ Snmp.Types: PrivParameters :: !PrivType -> !ByteString -> PrivParameters
+ Snmp.Types: PrivTypeAes :: PrivType
+ Snmp.Types: PrivTypeDes :: PrivType
+ Snmp.Types: RequestId :: Int -> RequestId
+ Snmp.Types: ScopedPdu :: !EngineId -> !ByteString -> !Pdus -> ScopedPdu
+ Snmp.Types: ScopedPduDataEncrypted :: !ByteString -> ScopedPduData
+ Snmp.Types: ScopedPduDataPlaintext :: !ScopedPdu -> ScopedPduData
+ Snmp.Types: SimpleSyntaxInteger :: !Int32 -> SimpleSyntax
+ Snmp.Types: SimpleSyntaxObjectId :: !ObjectIdentifier -> SimpleSyntax
+ Snmp.Types: SimpleSyntaxString :: !ByteString -> SimpleSyntax
+ Snmp.Types: TrapPdu :: !ObjectIdentifier -> !Word32 -> !GenericTrap -> !Integer -> !Integer -> [VarBind] -> TrapPdu
+ Snmp.Types: Usm :: !EngineId -> !Int32 -> !Int32 -> !ByteString -> !ByteString -> !ByteString -> Usm
+ Snmp.Types: VarBind :: !ObjectIdentifier -> !BindingResult -> VarBind
+ Snmp.Types: [authParametersKey] :: AuthParameters -> !ByteString
+ Snmp.Types: [authParametersType] :: AuthParameters -> !AuthType
+ Snmp.Types: [bulkPduMaxRepetitions] :: BulkPdu -> !Int32
+ Snmp.Types: [bulkPduNonRepeaters] :: BulkPdu -> !Int32
+ Snmp.Types: [bulkPduRequestId] :: BulkPdu -> !RequestId
+ Snmp.Types: [bulkPduVariableBindings] :: BulkPdu -> !Vector VarBind
+ Snmp.Types: [getAesSalt] :: AesSalt -> Word64
+ Snmp.Types: [getEngineId] :: EngineId -> ByteString
+ Snmp.Types: [getErrorIndex] :: ErrorIndex -> Int32
+ Snmp.Types: [getErrorStatus] :: ErrorStatus -> Integer
+ Snmp.Types: [getRequestId] :: RequestId -> Int
+ Snmp.Types: [headerDataFlags] :: HeaderData -> !Word8
+ Snmp.Types: [headerDataId] :: HeaderData -> !RequestId
+ Snmp.Types: [headerDataMaxSize] :: HeaderData -> !Int32
+ Snmp.Types: [messageV2CommunityString] :: MessageV2 -> !ByteString
+ Snmp.Types: [messageV2Data] :: MessageV2 -> !Pdus
+ Snmp.Types: [messageV3Data] :: MessageV3 -> !ScopedPduData
+ Snmp.Types: [messageV3GlobalData] :: MessageV3 -> !HeaderData
+ Snmp.Types: [messageV3SecurityParameters] :: MessageV3 -> !Usm
+ Snmp.Types: [pduErrorIndex] :: Pdu -> !ErrorIndex
+ Snmp.Types: [pduErrorStatus] :: Pdu -> !ErrorStatus
+ Snmp.Types: [pduRequestId] :: Pdu -> !RequestId
+ Snmp.Types: [pduVariableBindings] :: Pdu -> !Vector VarBind
+ Snmp.Types: [privParametersKey] :: PrivParameters -> !ByteString
+ Snmp.Types: [privParametersType] :: PrivParameters -> !PrivType
+ Snmp.Types: [scopedPduContextEngineId] :: ScopedPdu -> !EngineId
+ Snmp.Types: [scopedPduContextName] :: ScopedPdu -> !ByteString
+ Snmp.Types: [scopedPduData] :: ScopedPdu -> !Pdus
+ Snmp.Types: [trapPduAgentAddress] :: TrapPdu -> !Word32
+ Snmp.Types: [trapPduEnterprise] :: TrapPdu -> !ObjectIdentifier
+ Snmp.Types: [trapPduGenericTrap] :: TrapPdu -> !GenericTrap
+ Snmp.Types: [trapPduSpecificTrap] :: TrapPdu -> !Integer
+ Snmp.Types: [trapPduTimeStamp] :: TrapPdu -> !Integer
+ Snmp.Types: [trapPduVariableBindings] :: TrapPdu -> [VarBind]
+ Snmp.Types: [usmAuthenticationParameters] :: Usm -> !ByteString
+ Snmp.Types: [usmAuthoritativeEngineBoots] :: Usm -> !Int32
+ Snmp.Types: [usmAuthoritativeEngineId] :: Usm -> !EngineId
+ Snmp.Types: [usmAuthoritativeEngineTime] :: Usm -> !Int32
+ Snmp.Types: [usmPrivacyParameters] :: Usm -> !ByteString
+ Snmp.Types: [usmUserName] :: Usm -> !ByteString
+ Snmp.Types: [varBindName] :: VarBind -> !ObjectIdentifier
+ Snmp.Types: [varBindResult] :: VarBind -> !BindingResult
+ Snmp.Types: cryptoAuth :: Crypto -> Maybe AuthParameters
+ Snmp.Types: cryptoFlags :: Crypto -> Word8
+ Snmp.Types: cryptoPriv :: Crypto -> Maybe PrivParameters
+ Snmp.Types: data ApplicationSyntax
+ Snmp.Types: data AuthParameters
+ Snmp.Types: data AuthType
+ Snmp.Types: data BindingResult
+ Snmp.Types: data BulkPdu
+ Snmp.Types: data Crypto
+ Snmp.Types: data GenericTrap
+ Snmp.Types: data HeaderData
+ Snmp.Types: data MessageV2
+ Snmp.Types: data MessageV3
+ Snmp.Types: data ObjectSyntax
+ Snmp.Types: data Pdu
+ Snmp.Types: data Pdus
+ Snmp.Types: data PrivParameters
+ Snmp.Types: data PrivType
+ Snmp.Types: data ScopedPdu
+ Snmp.Types: data ScopedPduData
+ Snmp.Types: data SimpleSyntax
+ Snmp.Types: data TrapPdu
+ Snmp.Types: data Usm
+ Snmp.Types: data VarBind
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.ApplicationSyntax
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.AuthParameters
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.AuthType
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.BindingResult
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.BulkPdu
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.Crypto
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.EngineId
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.ErrorIndex
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.ErrorStatus
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.GenericTrap
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.HeaderData
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.MessageV2
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.MessageV3
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.ObjectSyntax
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.Pdu
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.Pdus
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.PrivParameters
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.PrivType
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.RequestId
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.ScopedPdu
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.ScopedPduData
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.SimpleSyntax
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.TrapPdu
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.Usm
+ Snmp.Types: instance GHC.Classes.Eq Snmp.Types.VarBind
+ Snmp.Types: instance GHC.Classes.Ord Snmp.Types.AuthType
+ Snmp.Types: instance GHC.Classes.Ord Snmp.Types.EngineId
+ Snmp.Types: instance GHC.Classes.Ord Snmp.Types.PrivType
+ Snmp.Types: instance GHC.Classes.Ord Snmp.Types.RequestId
+ Snmp.Types: instance GHC.Read.Read Snmp.Types.RequestId
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.ApplicationSyntax
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.AuthParameters
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.AuthType
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.BindingResult
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.BulkPdu
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.Crypto
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.EngineId
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.ErrorIndex
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.ErrorStatus
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.GenericTrap
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.HeaderData
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.MessageV2
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.MessageV3
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.ObjectSyntax
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.Pdu
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.Pdus
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.PrivParameters
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.PrivType
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.RequestId
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.ScopedPdu
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.ScopedPduData
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.SimpleSyntax
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.TrapPdu
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.Usm
+ Snmp.Types: instance GHC.Show.Show Snmp.Types.VarBind
+ Snmp.Types: newtype AesSalt
+ Snmp.Types: newtype EngineId
+ Snmp.Types: newtype ErrorIndex
+ Snmp.Types: newtype ErrorStatus
+ Snmp.Types: newtype RequestId

Files

+ CHANGELOG.md view
@@ -0,0 +1,12 @@+# Changelog++`snmp` uses [PVP Versioning][1].+The changelog is available [on GitHub][2].++0.0.0+=====++* Initially created.++[1]: https://pvp.haskell.org+[2]: https://github.com/chessai/snmp/releases
LICENSE view
@@ -1,30 +1,29 @@-Copyright (c) 2014, Alexey Smirnov+BSD 3-Clause License +Copyright (c) 2019, chessai All rights reserved.  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -    * Redistributions of source code must retain the above copyright-      notice, this list of conditions and the following disclaimer.+* Redistributions of source code must retain the above copyright notice, this+  list of conditions and the following disclaimer. -    * Redistributions in binary form must reproduce the above-      copyright notice, this list of conditions and the following-      disclaimer in the documentation and/or other materials provided-      with the distribution.+* Redistributions in binary form must reproduce the above copyright notice,+  this list of conditions and the following disclaimer in the documentation+  and/or other materials provided with the distribution. -    * Neither the name of Alexey Smirnov nor the names of other-      contributors may be used to endorse or promote products derived-      from this software without specific prior written permission.+* Neither the name of the copyright holder nor the names of its+  contributors may be used to endorse or promote products derived from+  this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
− Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
snmp.cabal view
@@ -1,44 +1,55 @@-name:                snmp-version:             0.2.1.1-synopsis:            API for write snmp client.-description:         API for write snmp client.        -license:             BSD3-license-file:        LICENSE-author:              Alexey Smirnov-maintainer:          Alexey Smirnov <chemistmail@gmail.com>--- copyright:           -category:            Network-build-type:          Simple--- extra-source-files:  -cabal-version:       >=1.10+cabal-version: 2.4+name:+  snmp+version:+  0.3.0.0+synopsis:+  SNMP protocol library+description:+  SNMP library for writing client applications with SNMP+homepage:+  https://github.com/chessai/snmp.git+license:+  BSD-3-Clause+license-file:+  LICENSE+author:+  Andrew Martin+maintainer:+  chessai1996@gmail.com+copyright:+  2019 (c) Andrew Martin+category:+  Language+build-type:+  Simple+extra-source-files:+  CHANGELOG.md  source-repository head-  type:              git-  location:          git@github.com:chemist/snmp.git+  type: git+  location: https://github.com/chessai/language-asn  library-  exposed-modules: Network.Protocol.Snmp, Network.Snmp.Client, Network.Snmp.Example-  other-modules: Network.Snmp.Client.Internal, Network.Snmp.Client.Types, Network.Snmp.Client.Version2, Network.Snmp.Client.Version3     -  -- other-extensions:    -  build-depends:       base >=4.6 && <4.9, -                       asn1-encoding, -                       asn1-types, -                       asn1-parse, -                       bytestring, -                       network, -                       mtl, -                       text, -                       time, -                       containers, -                       async, -                       binary, -                       network-info, -                       cryptohash, -                       cipher-des, -                       crypto-cipher-types, -                       securemem, -                       random, -                       cipher-aes-  hs-source-dirs:      src-  ghc-options: -Wall-  default-language:    Haskell2010+  exposed-modules:+    Snmp.Types+    Snmp.Encoding+    Snmp.Decoding+    Snmp.Client +  build-depends:+    , base >=4.10.1 && < 4.13+    , bytestring >= 0.10 && < 0.11+    , containers >= 0.5 && < 0.7+    , cryptonite >= 0.20 && < 0.26+    , ip >= 1.3 && < 1.5+    , language-asn >= 0.1 && < 0.2+    , memory >= 0.14 && < 0.15+    , stm >= 2.4 && < 2.6+    , vector >= 0.11 && < 0.13+    , network >= 2.8 && < 2.9+  hs-source-dirs:+    src+  default-language:+    Haskell2010+  ghc-options:+    -Wall
− src/Network/Protocol/Snmp.hs
@@ -1,1059 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleInstances #-}-module Network.Protocol.Snmp (--- * snmp types-  Value(..)-, OID-, OIDS--- * top level types-, V2-, V3-, Version(..)-, Packet--- ** header-, Header --- *** header snmpV2-, Community(..)--- *** header snmpV3-, ID(..)-, MaxSize(..)-, Flag(..)-, SecurityModel(..)-, SecurityParameter(..)-, Reportable-, PrivAuth(..)-, EngineBootId-, PrivacyParameter-, EngineTime-, EngineId--- ** PDU-, PDU (CryptedPDU)--- *** PDU universal-, Request(..)-, RequestId-, ErrorStatus-, ErrorIndex-, Suite(..)-, Coupla(..)--- *** PDU snmpV3-, ContextEngineID(..)-, ContextName(..)--- * some classes and helpers --- *** universal, for work with both versions-, HasItem(..)--- *** v2 only, for work with Header V2-, HasV2(..)--- *** v3 only, for work with Header V3, PDU V3-, HasV3(..)--- *** create new Packet-, Construct(..)--- ** helpers for work with Packet--- *** universal-, getVersion-, getRequest-, setRequest-, getRid-, setRid-, getSuite-, setSuite-, getErrorStatus-, setErrorStatus--- *** v2 only-, setCommunityP--- *** v3 only-, setIDP-, setMaxSizeP-, setUserNameP-, getAuthenticationParametersP-, setAuthenticationParametersP-, setReportableP-, setPrivAuthP-, getEngineIdP-, setEngineIdP-, getEngineBootsP-, setEngineBootsP-, getEngineTimeP-, setEngineTimeP-, getPrivParametersP-, setPrivParametersP--- * authentication-, passwordToKey-, signPacket-, AuthType(..)-, PrivType(..)-, Password-, Key-, cleanPass--- * priv-, Salt-, Raw-, Encrypted-, Rand32-, Rand64-, desEncrypt-, desDecrypt-, aesEncrypt-, aesDecrypt-, toSalt--- * exceptions-, ClientException(..) --- * usage example--- $example-)-where--import Data.ByteString (ByteString)-import qualified Data.ByteString as B-import qualified Data.ByteString.Lazy as BL-#if MIN_VERSION_base(4,7,0)-import Data.Bits (testBit, complement, shiftL, (.|.), (.&.), setBit, shiftR, zeroBits, xor, clearBit)-#else-import Data.Bits (testBit, complement, shiftL, (.|.), (.&.), setBit, shiftR, xor, clearBit, Bits(..))-#endif-import Data.ASN1.Types (ASN1Object(..), ASN1(..), OID, ASN1ConstructionType(..), ASN1Class(..))-import Data.ASN1.Parse (getNext, getObject, runParseASN1, runParseASN1State, ParseASN1, getNextContainer, onNextContainer, getMany)-import Data.ASN1.BinaryEncoding (DER(..))-import Data.ASN1.Encoding (encodeASN1', decodeASN1')-import Control.Applicative ((<$>), (<*>), (*>), (<*))-import Data.Monoid (Monoid, (<>))-import Control.Exception (Exception, throw)-import Data.Typeable (Typeable)-import qualified Crypto.Hash.MD5 as Md5-import qualified Crypto.Hash.SHA1 as Sha-import qualified Crypto.MAC.HMAC as HMAC-import qualified Crypto.Cipher.Types as Priv-import qualified Crypto.Cipher.DES as Priv-import qualified Crypto.Cipher.AES as Priv-import Data.Int-import Data.Binary-import Data.Binary.Get-import Data.Binary.Put---- $example------ Here example for snmpV2 ------ @--- import Network.Protocol.Snmp--- import Control.Applicative--- import Network.Socket.ByteString (recv, sendAll)--- import Network.Socket hiding (recv, sendAll)------ -- create new empty packet--- v2 :: Packet--- v2 = initial Version2--- --- community = Community "hello"------ oi = Coupla [1,3,6,1,2,1,1,4,0] Zero------ -- set community, oid--- packet :: Community -> Coupla -> Packet--- packet community oi = ---   setCommunityP community . setSuite (Suite [oi]) $ v2--- --- -- here must be code for create udp socket--- makeSocket :: Hostname -> Port -> IO Socket--- makeSocket = undefined------ main :: IO ()--- main = do---    socket <- makeSocket "localhost" "161"---    sendAll socket $ encode $ setRequest (GetRequest 1 0 0) packet---    result <- decode <$\> recv socket 1500 :: IO Packet---    print $ getSuite result --- --- @--- ---------------------------------------------------------------------------------------------------------------------fI :: (Num b, Integral a) => a -> b-fI = fromIntegral--#if MIN_VERSION_base(4,7,0)-#else-zeroBits :: (Num a, Bits a) =>  a-zeroBits = clearBit (bit 0) 0-  where-  bit :: (Bits a, Num a) => Int -> a-  bit i = 1 `shiftL` i-#endif---- | Phantom type for version 1 (Header V2, PDU V2)-data V1--- | Phantom type for version 2 (Header V2, PDU V2)-data V2--- | Phantom type for version 3 (Header V3, PDU V3)-data V3---- | Snmp version tag-data Version = Version1-             | Version2 -             | Version3-             deriving (Eq, Show)--type OIDS = [OID]---- | Top level type, which describe snmp packet-data Packet where-  V2Packet :: Version -> Header V2 -> PDU V2 -> Packet-  V3Packet :: Version -> Header V3 -> PDU V3 -> Packet--deriving instance Show Packet -deriving instance Eq Packet ---- | Snmp header without version tag-data Header a where-  V2Header :: Community -> Header V2-  V3Header :: ID -> MaxSize -> Flag -> SecurityModel -> SecurityParameter -> Header V3--deriving instance Show (Header a)-deriving instance Eq (Header a)---- | Snmp body-data PDU a where-  PDU :: Request -> Suite -> PDU V2-  ScopedPDU :: ContextEngineID -> ContextName -> PDU V2 -> PDU V3-  CryptedPDU :: ByteString -> PDU V3--deriving instance Show (PDU a)-deriving instance Eq (PDU a)---- | Snmp data types-data Value = OI OID-           | Zero-           | Integer Int32-           | String ByteString-           | IpAddress Word8 Word8 Word8 Word8-           | Counter32 Word32-           | Gauge32 Word32-           | TimeTicks Word32-           | Opaque ByteString-           | Counter64 Word64-           | ZeroDotZero-           | NoSuchInstance-           | NoSuchObject-           | EndOfMibView-           deriving (Show, Eq)---- | Request id -type RequestId = Int32---- | Error status -type ErrorStatus = Integer---- | Error index -type ErrorIndex = Integer---- | requests-data Request = GetRequest     { rid :: RequestId, es :: ErrorStatus, ei :: ErrorIndex }-             | GetNextRequest { rid :: RequestId, es :: ErrorStatus, ei :: ErrorIndex }-             | GetResponse    { rid :: RequestId, es :: ErrorStatus, ei :: ErrorIndex }-             | SetRequest     { rid :: RequestId, es :: ErrorStatus, ei :: ErrorIndex }-             | GetBulk        { rid :: RequestId, es :: ErrorStatus, ei :: ErrorIndex }-             | Inform         { rid :: RequestId, es :: ErrorStatus, ei :: ErrorIndex }-             | V2Trap         { rid :: RequestId, es :: ErrorStatus, ei :: ErrorIndex }-             | Report         { rid :: RequestId, es :: ErrorStatus, ei :: ErrorIndex }-             deriving (Show, Eq)---- | Coupla oid -> value-data Coupla = Coupla { oid :: OID, value :: Value } deriving (Eq)---- | Variable bindings-newtype Suite = Suite [Coupla] deriving (Eq, Monoid)---- ** Types describing header---- | (snmp2 only) Community for 2(1) version-newtype Community = Community ByteString deriving (Show, Eq)---- | (snmp3 only) Message Identifier (like RequestId in PDU)-newtype ID = ID Int32 deriving (Show, Eq)---- | (snmp3 only) Message max size must be > 484-newtype MaxSize = MaxSize Integer deriving (Show, Eq)---- | (snmp3 only) rfc3412, type for create message flag-data PrivAuth = NoAuthNoPriv | AuthNoPriv | AuthPriv deriving (Show, Eq)---- | (snmp3 only) rfc3412, as PrivAuth-type Reportable = Bool---- | (snmp3 only) rfc3412, message flag-data Flag = Flag Reportable PrivAuth  deriving (Show, Eq)---- | (snmp3 only) rfc3412, security model-data SecurityModel = UserBasedSecurityModel deriving (Show, Eq)---- | (snmp3 only) rfc3412, security parameter-data SecurityParameter = SecurityParameter -  { authoritiveEngineId :: ByteString-  , authoritiveEngineBoots :: Int32-  , authoritiveEngineTime :: Int32-  , userName :: ByteString-  , authenticationParameters :: ByteString-  , privacyParameters :: ByteString-  }-  deriving (Eq)---- | (snmp3 only) rfc3412, types for ScopedPDU-newtype ContextEngineID = ContextEngineID ByteString deriving (Show, Eq)-newtype ContextName = ContextName ByteString deriving (Show, Eq)---- | some exception-data ClientException = TimeoutException -                     | ServerException Integer-                     deriving (Typeable, Eq)---- | some universal getters, setters-class HasItem a where-    getHeader :: Packet -> Header a-    setHeader :: Header a -> Packet -> Packet-    getPDU :: Packet -> PDU a-    setPDU :: PDU a -> Packet -> Packet---- | (snmp2 only) getters, setters for work with Header V2-class HasV2 a where-    getCommunity :: Header a -> Community-    setCommunity :: Community -> Header a -> Header a---- | (snmp3 only) getters, setters for work with Header V3 and PDU V3.-class HasV3 a where-    getID :: Header a -> ID-    getMaxSize :: Header a -> MaxSize-    getFlag :: Header a -> Flag-    getSecurityModel :: Header a -> SecurityModel-    getSecurityParameter :: Header a -> SecurityParameter-    getAuthoritiveEngineId :: Header a -> ByteString-    getAuthoritiveEngineBoots :: Header a -> Int32-    getAuthoritiveEngineTime :: Header a -> Int32-    getUserName :: Header a -> ByteString-    getAuthenticationParameters :: Header a -> ByteString-    getPrivacyParameters :: Header a -> ByteString-    getContextEngineID :: PDU a -> ContextEngineID-    getContextName :: PDU a -> ContextName-    setID :: ID -> Header a -> Header a-    setMaxSize :: MaxSize -> Header a -> Header a-    setFlag :: Flag -> Header a -> Header a-    setSecurityModel :: SecurityModel -> Header a -> Header a-    setSecurityParameter :: SecurityParameter -> Header a -> Header a-    setAuthoritiveEngineId :: ByteString -> Header a -> Header a-    setAuthoritiveEngineBoots :: Int32 -> Header a -> Header a-    setAuthoritiveEngineTime :: Int32 -> Header a -> Header a-    setUserName :: ByteString -> Header a -> Header a-    setAuthenticationParameters :: ByteString -> Header a -> Header a-    setPrivacyParameters :: ByteString -> Header a -> Header a-    setContextEngineID :: ContextEngineID -> PDU a -> PDU a-    setContextName :: ContextName -> PDU a -> PDU a---- | initial new object, like mempty for monoid-class Construct a where-    initial :: a-------------------------------------------------------------------------------------------instance Construct (Version -> Packet) where-    initial Version3 = V3Packet Version3 initial initial-    initial Version2 = V2Packet Version2 initial initial-    initial Version1 = V2Packet Version1 initial initial--instance Construct (Header V3) where-    initial = V3Header (ID 0) (MaxSize 65007) (Flag False NoAuthNoPriv) UserBasedSecurityModel initial--instance Construct (Header V2) where-    initial = V2Header (Community "")--instance Construct (PDU V3) where-    initial = ScopedPDU (ContextEngineID "") (ContextName "") initial--instance Construct (PDU V2) where-    initial = PDU initial initial--instance Construct SecurityParameter where-    initial = SecurityParameter "" 0 0 "" "" ""--instance Construct Suite where-    initial = Suite []--instance Construct Request where-     initial = GetRequest 0 0 0------------------------------------------------------------------------------------------instance HasItem V2 where-    getHeader (V2Packet _ x _) = x-    getHeader _ = undefined-    setHeader h (V2Packet v _ x) = V2Packet v h x-    setHeader _ _ = undefined-    getPDU (V2Packet _ _ x) = x-    getPDU _ = undefined-    setPDU p (V2Packet v h _) = V2Packet v h p-    setPDU _ _ = undefined--instance HasItem V3 where-    getHeader (V3Packet _ x _) = x-    getHeader _ = undefined-    setHeader h (V3Packet v _ x) = V3Packet v h x-    setHeader _ _ = undefined-    getPDU (V3Packet _ _ x) = x-    getPDU _ = undefined-    setPDU p (V3Packet v h _) = V3Packet v h p-    setPDU _ _ = undefined--instance HasV2 V2 where-    getCommunity (V2Header c) = c-    setCommunity c (V2Header _) = V2Header c--instance HasV3 V3 where-    getID (V3Header i _ _ _ _) = i-    getMaxSize (V3Header _ i _ _ _) = i-    getFlag (V3Header _ _ i _ _) = i-    getSecurityModel (V3Header _ _ _ i _) = i-    getSecurityParameter (V3Header _ _ _ _ i) = i-    getAuthoritiveEngineId = authoritiveEngineId . getSecurityParameter-    getAuthoritiveEngineBoots = authoritiveEngineBoots . getSecurityParameter-    getAuthoritiveEngineTime = authoritiveEngineTime . getSecurityParameter-    getUserName = userName . getSecurityParameter-    getAuthenticationParameters = authenticationParameters . getSecurityParameter-    getPrivacyParameters = privacyParameters . getSecurityParameter-    getContextEngineID (ScopedPDU i _ _) = i-    getContextEngineID _ = undefined-    getContextName (ScopedPDU _ i _) = i-    getContextName _ = undefined-    setID i (V3Header _ a b c d) = V3Header i a b c d-    setMaxSize i (V3Header a _ b c d) = V3Header a i b c d-    setFlag i (V3Header a b _ c d) = V3Header a b i c d-    setSecurityModel i (V3Header a b c _ d) = V3Header a b c i d-    setSecurityParameter i (V3Header a b c d _) = V3Header a b c d i-    setAuthoritiveEngineId      i (V3Header a b c d f) = V3Header a b c d (f { authoritiveEngineId = i })-    setAuthoritiveEngineBoots   i (V3Header a b c d f) = V3Header a b c d (f { authoritiveEngineBoots = i })-    setAuthoritiveEngineTime    i (V3Header a b c d f) = V3Header a b c d (f { authoritiveEngineTime = i })-    setUserName                 i (V3Header a b c d f) = V3Header a b c d (f { userName = i })-    setAuthenticationParameters i (V3Header a b c d f) = V3Header a b c d (f { authenticationParameters = i })-    setPrivacyParameters        i (V3Header a b c d f) = V3Header a b c d (f { privacyParameters = i })-    setContextEngineID i (ScopedPDU _ b c) = ScopedPDU i b c-    setContextEngineID _ _ = undefined-    setContextName i (ScopedPDU a _ b) = ScopedPDU a i b -    setContextName _ _ = undefined-------------------------------------------------------------------------------------------setIDP :: ID -> Packet -> Packet -setIDP x p = -  let header = getHeader p :: Header V3-      newHeader = setID x header-  in setHeader newHeader p--setMaxSizeP :: MaxSize -> Packet -> Packet -setMaxSizeP x p = -  let header = getHeader p :: Header V3-      newHeader = setMaxSize x header-  in setHeader newHeader p --setCommunityP :: Community -> Packet -> Packet -setCommunityP x p = -  let header = getHeader p :: Header V2-      newHeader = setCommunity x header-  in setHeader newHeader p--getEngineIdP :: Packet -> EngineId-getEngineIdP p = -  let header = getHeader p :: Header V3-  in getAuthoritiveEngineId header--setEngineIdP :: EngineId -> Packet -> Packet-setEngineIdP x p =-  let header = getHeader p :: Header V3-      newHeader = setAuthoritiveEngineId x header-  in setHeader newHeader p--getEngineBootsP :: Packet -> EngineBootId-getEngineBootsP p = -  let header = getHeader p :: Header V3-  in getAuthoritiveEngineBoots header--setEngineBootsP :: EngineBootId -> Packet -> Packet-setEngineBootsP x p =-  let header = getHeader p :: Header V3-      newHeader = setAuthoritiveEngineBoots x header-  in setHeader newHeader p-  -getEngineTimeP :: Packet -> Int32-getEngineTimeP p = -  let header = getHeader p :: Header V3-  in getAuthoritiveEngineTime header--setEngineTimeP :: Int32 -> Packet -> Packet-setEngineTimeP x p =-  let header = getHeader p :: Header V3-      newHeader = setAuthoritiveEngineTime x header-  in setHeader newHeader p--setReportableP :: Reportable -> Packet -> Packet-setReportableP r p = -  let header = getHeader p :: Header V3-      Flag _ a = getFlag header-      newHeader = setFlag (Flag r a) header-  in setHeader newHeader p--setPrivAuthP :: PrivAuth -> Packet -> Packet-setPrivAuthP x p = -  let header = getHeader p :: Header V3-      Flag r _ = getFlag header-      newHeader = setFlag (Flag r x) header-  in setHeader newHeader p--setUserNameP :: ByteString -> Packet -> Packet -setUserNameP x p = -  let header = getHeader p :: Header V3-      sp = getSecurityParameter header-      newHeader = setSecurityParameter (sp { userName = x }) header-  in setHeader newHeader p--setAuthenticationParametersP :: ByteString -> Packet -> Packet -setAuthenticationParametersP x p = -  let header = getHeader p :: Header V3-      sp = getSecurityParameter header-      newHeader = setSecurityParameter (sp { authenticationParameters = x }) header-  in setHeader newHeader p-  -getAuthenticationParametersP :: Packet -> ByteString-getAuthenticationParametersP p = -  let header = getHeader p :: Header V3-  in authenticationParameters (getSecurityParameter header)--setPrivParametersP :: ByteString -> Packet -> Packet -setPrivParametersP x p = -  let header = getHeader p :: Header V3-      sp = getSecurityParameter header-      newHeader = setSecurityParameter (sp { privacyParameters = x }) header-  in setHeader newHeader p--getPrivParametersP :: Packet -> ByteString-getPrivParametersP p =-  let header = getHeader p :: Header V3-  in privacyParameters $ getSecurityParameter header---getVersion :: Packet -> Version-getVersion (V2Packet v _ _) = v-getVersion (V3Packet v _ _) = v--getRid :: Packet -> RequestId -getRid (V2Packet _ _ (PDU r _)) = rid r -getRid (V3Packet _ _ (ScopedPDU _ _ (PDU r _))) = rid r -getRid _ = undefined--setRid :: RequestId -> Packet -> Packet-setRid r (V2Packet v h (PDU req s)) = V2Packet v h (PDU req { rid = r } s)-setRid r (V3Packet v h (ScopedPDU a b (PDU req s))) = V3Packet v h (ScopedPDU a b (PDU req { rid = r } s))-setRid _ _ = undefined--getErrorStatus :: Packet -> ErrorStatus -getErrorStatus (V2Packet _ _ (PDU r _)) = es r -getErrorStatus (V3Packet _ _ (ScopedPDU _ _ (PDU r _))) = es r -getErrorStatus _ = undefined--setErrorStatus :: ErrorStatus -> Packet -> Packet-setErrorStatus e (V2Packet v h (PDU req s)) = V2Packet v h (PDU req { es = e } s)-setErrorStatus e (V3Packet v h (ScopedPDU a b (PDU req s))) = V3Packet v h (ScopedPDU a b (PDU req { es = e } s))-setErrorStatus _ _ = undefined--getSuite :: Packet -> Suite-getSuite (V2Packet _ _ (PDU _ r)) = r -getSuite (V3Packet _ _ (ScopedPDU _ _ (PDU _ r))) = r -getSuite _ = undefined--setSuite :: Suite -> Packet -> Packet-setSuite s (V2Packet v h (PDU req _)) = V2Packet v h (PDU req s)-setSuite s (V3Packet v h (ScopedPDU a b (PDU req _))) = V3Packet v h (ScopedPDU a b (PDU req s))-setSuite _ _ = undefined--getRequest :: Packet -> Request-getRequest (V2Packet _ _ (PDU r _)) = r -getRequest (V3Packet _ _ (ScopedPDU _ _ (PDU r _))) = r -getRequest _ = undefined--setRequest :: Request -> Packet -> Packet-setRequest req (V2Packet v h (PDU _ s)) = V2Packet v h (PDU req s)-setRequest req (V3Packet v h (ScopedPDU a b (PDU _ s))) = V3Packet v h (ScopedPDU a b (PDU req s))-setRequest _ _ = undefined-------------------------------------------------------------------------------------------instance ASN1Object (Header V2) where-    toASN1 (V2Header c) = toASN1 c -    fromASN1 asn = flip runParseASN1State asn $ V2Header <$> getObject--sS :: ParseASN1 ()-sS = do-    Start Sequence <- getNext-    return ()--eS :: ParseASN1 ()-eS = do-    End Sequence <- getNext-    return ()--instance ASN1Object (Header V3) where-    toASN1 (V3Header i ms f sm sp) xs = -        Start Sequence : toASN1 i (toASN1 ms (toASN1 f (toASN1 sm [End Sequence]))) ++ toASN1 sp xs-    fromASN1 asn = flip runParseASN1State asn $-        V3Header <$> (sS *> getObject) <*> getObject <*> getObject <*> (getObject <* eS) <*> getObject--instance ASN1Object (PDU V2) where-    toASN1 (PDU (GetRequest rid _ _    ) sd) xs = (Start $ Container Context 0):IntVal (fromIntegral rid) : IntVal 0  : IntVal 0 : Start Sequence : toASN1 sd [] ++ [ End Sequence, End (Container Context 0)] ++ xs-    toASN1 (PDU (GetNextRequest rid _ _) sd) xs = (Start $ Container Context 1):IntVal (fromIntegral rid) : IntVal 0  : IntVal 0 : Start Sequence : toASN1 sd [] ++ [ End Sequence, End (Container Context 1)] ++ xs-    toASN1 (PDU (GetResponse rid es ei ) sd) xs = (Start $ Container Context 2):IntVal (fromIntegral rid) : IntVal es : IntVal ei: Start Sequence : toASN1 sd [] ++ [ End Sequence, End (Container Context 2)] ++ xs-    toASN1 (PDU (SetRequest rid _ _    ) sd) xs = (Start $ Container Context 3):IntVal (fromIntegral rid) : IntVal 0  : IntVal 0 : Start Sequence : toASN1 sd [] ++ [ End Sequence, End (Container Context 3)] ++ xs-    toASN1 (PDU (GetBulk rid es ei     ) sd) xs = (Start $ Container Context 5):IntVal (fromIntegral rid) : IntVal es : IntVal ei: Start Sequence : toASN1 sd [] ++ [ End Sequence, End (Container Context 4)] ++ xs-    toASN1 (PDU (Inform rid es ei     ) sd) xs = (Start $ Container Context 6):IntVal (fromIntegral rid) : IntVal es : IntVal ei: Start Sequence : toASN1 sd [] ++ [ End Sequence, End (Container Context 4)] ++ xs-    toASN1 (PDU (V2Trap rid es ei     ) sd) xs = (Start $ Container Context 7):IntVal (fromIntegral rid) : IntVal es : IntVal ei: Start Sequence : toASN1 sd [] ++ [ End Sequence, End (Container Context 4)] ++ xs-    toASN1 (PDU (Report rid es ei      ) sd) xs = (Start $ Container Context 8):IntVal (fromIntegral rid) : IntVal es : IntVal ei: Start Sequence : toASN1 sd [] ++ [ End Sequence, End (Container Context 8)] ++ xs-    fromASN1 asn = runParseASN1State pduParser asn --pduParser :: ParseASN1 (PDU V2)-pduParser = do-    Start (Container Context n) <- getNext-    IntVal rid' <- getNext-    IntVal es <- getNext-    IntVal ei <- getNext-    x <- getNextContainer Sequence -    End (Container Context _) <- getNext-    let psuite = fromASN1 x-        rid = fromIntegral rid'-    case (n, psuite) of-         (0, Right (suite, _)) -> return $ PDU (GetRequest     rid es ei) suite-         (1, Right (suite, _)) -> return $ PDU (GetNextRequest rid es ei) suite-         (2, Right (suite, _)) -> return $ PDU (GetResponse    rid es ei) suite-         (3, Right (suite, _)) -> return $ PDU (SetRequest     rid es ei) suite-         (5, Right (suite, _)) -> return $ PDU (GetBulk        rid es ei) suite-         (6, Right (suite, _)) -> return $ PDU (Inform         rid es ei) suite-         (7, Right (suite, _)) -> return $ PDU (V2Trap         rid es ei) suite-         (8, Right (suite, _)) -> return $ PDU (Report         rid es ei) suite-         _ -> throw $ ServerException 9--instance ASN1Object (PDU V3) where-    toASN1 (ScopedPDU (ContextEngineID x) (ContextName y) pdu) xs = -      [Start Sequence, OctetString x, OctetString y] ++ toASN1 pdu (End Sequence :xs)-    toASN1 (CryptedPDU cryptedBody) xs = OctetString cryptedBody : xs-    fromASN1 asn = flip runParseASN1State asn $ do-        whatIs <- getNext-        case whatIs of-             Start Sequence -> do-                 OctetString x <- getNext-                 OctetString y <- getNext-                 p <- pduParser -                 End Sequence <- getNext-                 return $ ScopedPDU (ContextEngineID x) (ContextName y) p-             OctetString x -> return $ CryptedPDU x-             _ -> throw $ ServerException 9--instance ASN1Object Version where-    toASN1 Version1 xs = IntVal 0 : xs-    toASN1 Version2 xs = IntVal 1 : xs-    toASN1 Version3 xs = IntVal 3 : xs-    fromASN1 asn = flip runParseASN1State asn $ do-        IntVal x <- getNext-        case x of -             0 -> return Version1-             1 -> return Version2-             3 -> return Version3-             _ -> throw $ ServerException 10--instance ASN1Object Packet where-    toASN1 (V2Packet Version1 header body) _ = Start Sequence : toASN1 Version1 (toASN1 header (toASN1 body [End Sequence]))-    toASN1 (V2Packet Version2 header body) _ = Start Sequence : toASN1 Version2 (toASN1 header (toASN1 body [End Sequence]))-    toASN1 (V3Packet Version3 header body) _ = Start Sequence : toASN1 Version3 (toASN1 header (toASN1 body [End Sequence]))-    toASN1 _ _ = throw $ ServerException 10-    fromASN1 asn = flip runParseASN1State asn $ onNextContainer Sequence $ do-        v <- getObject-        case v of-             Version1 -> V2Packet Version1 <$> getObject <*> getObject-             Version2 -> V2Packet Version2 <$> getObject <*> getObject-             Version3 -> V3Packet Version3 <$> getObject <*> getObject--instance ASN1Object Value where-    toASN1 NoSuchObject xs = Other Context 0 "" : xs-    toASN1 NoSuchInstance xs = Other Context 1 "" : xs-    toASN1 EndOfMibView xs = Other Context 2 "" : xs-    toASN1 (OI x) xs = OID x : xs-    toASN1 Zero xs = Null : xs-    toASN1 ZeroDotZero xs = OID [0,0] : xs-    toASN1 (Integer x) xs = IntVal (fI x) : xs-    toASN1 (String x) xs = OctetString x : xs-    toASN1 (IpAddress a1 a2 a3 a4) xs = Other Application 0 (B.pack [a1, a2, a3, a4]) : xs-    toASN1 (Counter32 x) xs = Other Application 1 (packInteger (fI x)) : xs-    toASN1 (Gauge32 x) xs = Other Application 2 (packInteger (fI x)) : xs-    toASN1 (TimeTicks x) xs = Other Application 3 (packInteger (fI x)) : xs-    toASN1 (Opaque x) xs = Other Application 4 x : xs-    toASN1 (Counter64 x) xs = Other Application 6 (packInteger (fI x)) : xs-    fromASN1 asn = runParseASN1State (unp =<< getNext) asn-      where-      unp (Other Context 0 "") = return NoSuchObject-      unp (Other Context 1 "") = return NoSuchInstance-      unp (Other Context 2 "") = return EndOfMibView-      unp Null = return Zero-      unp (OID [0,0]) = return ZeroDotZero-      unp (IntVal x) = return $ Integer (fI x)-      unp (OctetString x) = return $ String x-      unp (Other Application 0 y) = let [a1, a2, a3, a4] = B.unpack y-                                    in return $ IpAddress a1 a2 a3 a4-      unp (Other Application 1 y) = case unpackInteger y of-                                         Right z -> return $ Counter32 (fI z)-                                         Left _ -> throw $ ServerException 9-      unp (Other Application 2 y) = case unpackInteger y of-                                         Right z -> return $ Gauge32 (fI z)-                                         Left _ -> throw $ ServerException 9-      unp (Other Application 3 y) = case unpackInteger y of-                                         Right z -> return $ TimeTicks (fI z)-                                         Left _ -> throw $ ServerException 9-      unp (Other Application 4 y) = return $ Opaque y-      unp (Other Application 6 y) = case unpackInteger y of-                                         Right z -> return $ Counter64 (fI z)-                                         Left _ -> throw $ ServerException 9-      unp (OID x) = return . OI $ x-      unp _ = throw $ ServerException 9--instance ASN1Object Community where-    toASN1 (Community x) xs = OctetString x : xs-    fromASN1 asn = flip runParseASN1State asn $ do-        OctetString x <- getNext-        return $ Community x--instance Show SecurityParameter where-    show msg = "SecurityParameter:\n\t\tAuthoritiveEngineId: " -       ++ show (authoritiveEngineId msg )-       ++ "\n\t\tAuthoritiveEngineBoots: " ++ show (authoritiveEngineBoots msg )-       ++ "\n\t\tAuthoritiveEngineTime: " ++ show (authoritiveEngineTime msg )-       ++ "\n\t\tUserName: " ++ show (userName msg )-       ++ "\n\t\tAuthenticationParameters: " ++ show (authenticationParameters msg )-       ++ "\n\t\tPrivacyParameters: " ++ show (privacyParameters msg )--instance ASN1Object ID where-    toASN1 (ID x) xs = IntVal (fromIntegral x) : xs-    fromASN1 asn = flip runParseASN1State asn $ do-        IntVal x <- getNext-        return $ ID (fromIntegral x)--instance ASN1Object MaxSize where-    toASN1 (MaxSize x) xs = IntVal x : xs-    fromASN1 asn = flip runParseASN1State asn $ do-        IntVal x <- getNext-        return $ MaxSize x--instance ASN1Object Flag where-    toASN1 (Flag r pa) xs = let zero = zeroBits :: Word8-                                reportable = if r then setBit zero 0 else zero-                                privauth = case pa of-                                                NoAuthNoPriv -> zero-                                                AuthNoPriv -> setBit zero 2-                                                AuthPriv -> setBit zero 1 .|. setBit zero 2-                                flag = reportable .|. privauth-                            in OctetString (B.pack [flag]) : xs-    fromASN1 asn = flip runParseASN1State asn $ do-        OctetString x <- getNext-        let [w] = B.unpack x-        return $ case (testBit w 0, testBit w 1) of-                      (True, True) -> Flag (testBit w 2) AuthPriv-                      (False, False) -> Flag (testBit w 2) NoAuthNoPriv-                      (True, False) -> Flag (testBit w 2) AuthNoPriv-                      _ -> throw $ ServerException 10---instance ASN1Object SecurityModel where-    toASN1 UserBasedSecurityModel xs = IntVal 3 : xs-    fromASN1 asn = flip runParseASN1State asn $ do-        IntVal x <- getNext-        case x of-             3 -> return UserBasedSecurityModel-             _ -> throw $ ServerException 7--instance ASN1Object SecurityParameter where-    toASN1 SecurityParameter{..} xs = OctetString (encodeASN1' DER-      [ Start Sequence-      ,   OctetString authoritiveEngineId -      ,   IntVal $ fromIntegral authoritiveEngineBoots -      ,   IntVal $ fromIntegral authoritiveEngineTime -      ,   OctetString userName -      ,   OctetString authenticationParameters -      ,   OctetString privacyParameters -      , End Sequence-      ]) : xs-    fromASN1 asn = flip runParseASN1State asn $ do-        OctetString packed <- getNext-        let r = case decodeASN1' DER packed of-             Left _ -> throw $ ServerException 9-             Right asn' -> parseMsgSecurityParameter asn'-        case r of-             Left _ -> throw $ ServerException 9-             Right r' -> return r'--parseMsgSecurityParameter :: [ASN1] -> Either String SecurityParameter-parseMsgSecurityParameter asn = flip runParseASN1 asn $ do-     Start Sequence <- getNext-     OctetString msgAuthoritiveEngineId <- getNext-     IntVal msgAuthoritiveEngineBoots <- getNext-     IntVal msgAuthoritiveEngineTime <- getNext-     OctetString msgUserName <- getNext-     OctetString msgAuthenticationParameters <- getNext-     OctetString msgPrivacyParameters <- getNext-     End Sequence <- getNext-     return $ SecurityParameter msgAuthoritiveEngineId (fromIntegral msgAuthoritiveEngineBoots) (fromIntegral msgAuthoritiveEngineTime) msgUserName msgAuthenticationParameters msgPrivacyParameters --instance Binary (PDU V3) where-    put = putByteString . encodeASN1' DER . flip toASN1 [] -    get = toP . BL.toStrict <$> getRemainingLazyByteString---    encode s = encodeASN1' DER $ toASN1 s []---    decode = toP--toP :: ByteString -> PDU V3-toP bs = let a = fromASN1 <$> decodeASN1' DER bs-         in case a of-                 Right (Right (r, _)) -> r-                 _ -> throw $ ServerException 9--instance Binary Packet where-    put = putByteString . encodeASN1' DER . flip toASN1 []---    encode s = encodeASN1' DER $ toASN1 s []-    get = toB . BL.toStrict <$> getRemainingLazyByteString--toB :: ByteString -> Packet -toB bs = let a = fromASN1 <$> decodeASN1' DER bs-         in case a of-                 Right (Right (r, _)) -> r-                 _ -> throw $ ServerException 9-                 --}-                 ---instance Show Coupla where-    show (Coupla o v) = oidToString o ++ " = " ++ show v--instance Show Suite where-    show (Suite xs) = unlines $ map show xs--oidToString :: OID -> String-oidToString xs = foldr1 (\x y -> x ++ "." ++ y) $ map show xs--instance ASN1Object Suite where-    toASN1 (Suite xs) ys = foldr toA [] xs ++ ys-      where -      toA ::Coupla -> [ASN1] -> [ASN1]-      toA (Coupla o v) zs = [Start Sequence , OID o] ++ toASN1 v (End Sequence : zs)-    fromASN1 asn = flip runParseASN1State asn $ do-        xs <- getMany $ do-               Start Sequence <- getNext-               OID x <- getNext-               v <-  getObject-               End Sequence <- getNext-               return $ Coupla x v-        return $ Suite xs--instance Show ClientException where-    show TimeoutException = "Timeout exception"-    show (ServerException 1) = "tooBig"-    show (ServerException 2) = "noSuchName"-    show (ServerException 3) = "badValue"-    show (ServerException 4) = "readOnly"-    show (ServerException 5) = "genErr"-    show (ServerException 6) = "noAccess"-    show (ServerException 7) = "wrongType"-    show (ServerException 8) = "wrongLength"-    show (ServerException 9) = "wrongEncoding"-    show (ServerException 10) = "wrongValue"-    show (ServerException 11) = "noCreation"-    show (ServerException 12) = "inconsistentValue"-    show (ServerException 13) = "resourceUnavailable"-    show (ServerException 14) = "commitFailed"-    show (ServerException 15) = "undoFailed"-    show (ServerException 16) = "authorizationError"-    show (ServerException 17) = "notWritable"-    show (ServerException 18) = "inconsistentName"-    show (ServerException 80) = "General IO failure occured on the set request"-    show (ServerException 81) = "General SNMP timeout occured"-    show (ServerException x) = "Exception " ++ show x--instance Exception ClientException---- copy paste from asn1-encoding--packInteger :: Integer -> ByteString-packInteger = B.pack . bytesOfInt --unpackInteger :: ByteString -> Either String Integer-unpackInteger = getIntegerRaw "Integer"--bytesOfInt :: Integer -> [Word8]-bytesOfInt i-  | i > 0      = if testBit (head uints) 7 then 0 : uints else uints-  | i == 0     = [0]-  | otherwise  = if testBit (head nints) 7 then nints else 0xff : nints-      where-      uints = bytesOfUInt (abs i)-      nints = reverse $ plusOne $ reverse $ map complement uints-      plusOne []     = [1]-      plusOne (x:xs) = if x == 0xff then 0 : plusOne xs else (x+1) : xs-----bytesOfUInt i = B.unfoldr (\x -> if x == 0 then Nothing else Just (fromIntegral (x .&. 0xff), x `shiftR` 8)) i-bytesOfUInt :: Integer -> [Word8]-bytesOfUInt x = reverse (list x)-  where list i = if i <= 0xff then [fromIntegral i] else (fromIntegral i .&. 0xff) : list (i `shiftR` 8)--{- | According to X.690 section 8.4 integer and enumerated values should be encoded the same way. -}-getIntegerRaw :: String -> ByteString -> Either String Integer-getIntegerRaw typestr s-    | B.length s == 0 = Left $ typestr ++ ": null encoding"-    | B.length s == 1 = Right $ snd $ intOfBytes s-    | otherwise       =-        if (v1 == 0xff && testBit v2 7) || (v1 == 0x0 && not (testBit v2 7))-            then Left $ typestr ++ ": not shortest encoding"-            else Right $ snd $ intOfBytes s-    where-        v1 = s `B.index` 0-        v2 = s `B.index` 1--{- | intOfBytes returns the number of bytes in the list and-the represented integer by a two's completement list of bytes -}-intOfBytes :: ByteString -> (Int, Integer)-intOfBytes b-    | B.length b == 0   = (0, 0)-    | otherwise         = (len, if isNeg then -(maxIntLen - v + 1) else v)-    where-        (len, v)  = uintOfBytes b-        maxIntLen = 2 ^ (8 * len) - 1-        isNeg     = testBit (B.head b) 7--{- | uintOfBytes returns the number of bytes and the unsigned integer represented by the bytes -}-uintOfBytes :: ByteString -> (Int, Integer)-uintOfBytes b = (B.length b, B.foldl (\acc n -> (acc `shiftL` 8) + fromIntegral n) 0 b)----------------------------------------------------------------------------------------------------------cleanPass :: ByteString-cleanPass = B.pack $ replicate 12 0x00- -data PrivType = DES | AES deriving (Show, Eq)-data AuthType = MD5 | SHA deriving (Show, Eq)-type Key = ByteString-type Password = ByteString--hash :: AuthType -> ByteString -> ByteString-hash MD5 = Md5.hash-hash SHA = Sha.hash--hashlazy :: AuthType -> BL.ByteString -> ByteString-hashlazy MD5 = Md5.hashlazy-hashlazy SHA = Sha.hashlazy---- | (only V3) sign Packet -signPacket :: AuthType -> Key -> Packet -> Packet -signPacket at key packet = -    let packetAsBin = BL.toStrict $ encode packet-        sign = B.take 12 $ HMAC.hmac (hash at) 64 key packetAsBin -    in setAuthenticationParametersP sign packet---- | create auth key from password and context engine id-passwordToKey :: AuthType -> Password -> EngineId -> Key-passwordToKey at pass eid = -  let buf = BL.take 1048576 $ BL.fromChunks $ repeat pass-      authKey = hashlazy at buf-  in hash at $ authKey <> eid <> authKey---------------------------------------------------------------------------------------------------------type EngineBootId = Int32-type PrivacyParameter = ByteString-type EngineId = ByteString-type Salt = ByteString-type Encrypted = ByteString-type Raw = ByteString-type Rand32 = Int32-type Rand64 = Int64--desEncrypt :: Key -> EngineBootId -> Rand32 -> Raw -> (Encrypted, Salt)-desEncrypt privKey engineBoot localInt dataToEncrypt = -    let desKey = B.take 8 privKey-        preIV = B.drop 8 $ B.take 16 privKey-        salt = toSalt engineBoot localInt-        ivR = B.pack $ zipWith xor (B.unpack preIV) (B.unpack salt)-        Just iv = Priv.makeIV ivR-        Right key = Priv.makeKey desKey -        des = Priv.cipherInit key :: Priv.DES-        tailLen = (8 - B.length dataToEncrypt `rem` 8) `rem` 8-        tailB = B.replicate tailLen 0x00-    in (Priv.cbcEncrypt des iv (dataToEncrypt <> tailB), salt)--type EngineTime = Int32--aesEncrypt :: Key -> EngineBootId -> EngineTime -> Rand64 -> Raw -> (Encrypted, Salt)-aesEncrypt privKey engineBoot engineTime rcounter dataToEncrypt =-    let aesKey = B.take 16 privKey-        salt = wToBs rcounter-        Just iv = Priv.makeIV $ toSalt engineBoot engineTime <> salt-        Right key = Priv.makeKey aesKey-        aes = Priv.cipherInit key :: Priv.AES128-    in (Priv.cfbEncrypt aes iv dataToEncrypt, salt)---wToBs :: Int64 -> ByteString-wToBs x = B.pack-  [ fromIntegral $ x `shiftR` 56 .&. 0xff-  , fromIntegral $ x `shiftR` 48 .&. 0xff-  , fromIntegral $ x `shiftR` 40 .&. 0xff-  , fromIntegral $ x `shiftR` 32 .&. 0xff-  , fromIntegral $ x `shiftR` 24 .&. 0xff-  , fromIntegral $ x `shiftR` 16 .&. 0xff-  , fromIntegral $ x `shiftR` 8 .&. 0xff-  , fromIntegral $ x `shiftR` 0 .&. 0xff-  ]--toSalt :: Int32 -> Int32 -> ByteString-toSalt x y = B.pack-  [ fromIntegral $ x `shiftR` 24 .&. 0xff -  , fromIntegral $ x `shiftR` 16 .&. 0xff-  , fromIntegral $ x `shiftR`  8 .&. 0xff-  , fromIntegral $ x `shiftR`  0 .&. 0xff-  , fromIntegral $ y `shiftR` 24 .&. 0xff-  , fromIntegral $ y `shiftR` 16 .&. 0xff-  , fromIntegral $ y `shiftR`  8 .&. 0xff-  , fromIntegral $ y `shiftR`  0 .&. 0xff-  ]--desDecrypt :: Key -> Salt -> Encrypted -> Raw-desDecrypt privKey privParameters dataToDecrypt =-    let desKey = B.take 8 privKey-        preIV = B.drop 8 $ B.take 16 privKey-        salt = privParameters-        ivR = zipWith xor (B.unpack preIV) (B.unpack salt)-        Just iv = Priv.makeIV (B.pack ivR)-        Right key = Priv.makeKey desKey-        des = Priv.cipherInit key :: Priv.DES-    in stripBS $ Priv.cbcDecrypt des iv dataToDecrypt--aesDecrypt :: Key -> Salt -> EngineBootId -> EngineTime -> Encrypted -> Raw-aesDecrypt privKey privParameters engineBoot engineTime dataToDecrypt =-    let aesKey = B.take 16 privKey-        salt = privParameters-        ivR = toSalt engineBoot engineTime <> salt-        Just iv = Priv.makeIV ivR-        Right key = Priv.makeKey aesKey-        aes = Priv.cipherInit key :: Priv.AES128-    in stripBS $ Priv.cfbDecrypt aes iv dataToDecrypt--stripBS :: ByteString -> ByteString-stripBS bs = -    let bs' = B.drop 1 bs-        l1 = fromIntegral $ B.head bs'-    in if testBit l1 7-        then case clearBit l1 7 of-                  0   -> throw $ ServerException 12-                  len -> -                    let size = uintbs (B.take len (B.drop 1 bs'))-                    in B.take (size + len + 2) bs-        else B.take (l1 + 2) bs-    where-      {- uintbs return the unsigned int represented by the bytes -}-      uintbs = B.foldl (\acc n -> (acc `shiftL` 8) + fromIntegral n) 0-
− src/Network/Snmp/Client.hs
@@ -1,58 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE RecordWildCards #-}-module Network.Snmp.Client (--- * types-  Client-, Port-, Hostname-, Login-, Password-, Version(..)-, Community(..)-, Config(..)-, Coupla(..)-, Suite(..)-, PrivAuth(..)-, AuthType(..)-, Value(String, Integer, IpAddress, Counter32, Gauge32, TimeTicks, Opaque, Counter64, ZeroDotZero, Zero, OI)--- * client -, client--- ** client methods-, get-, bulkget-, getnext-, walk-, bulkwalk-, set-, close--- * useful functions-, oidFromBS-)-where--import Network.Protocol.Snmp-import Network.Snmp.Client.Types-import Network.Snmp.Client.Internal-import Network.Snmp.Client.Version2-import Network.Snmp.Client.Version3--client :: Config -> IO Client-client ConfigV1{..} = clientV1 hostname -                               port -                               timeout -                               community-client ConfigV2{..} = clientV2 hostname -                               port -                               timeout -                               community-client ConfigV3{..} = clientV3 hostname       -                               port           -                               timeout        -                               sequrityName   -                               authPass       -                               privPass       -                               sequrityLevel  -                               authType       -                               privType      -
− src/Network/Snmp/Client/Internal.hs
@@ -1,67 +0,0 @@-module Network.Snmp.Client.Internal -( oidFromBS-, makeSocket-, succCounter-, predCounter-, lastS-, isUpLevel-, uniqID-)-where--import Data.ByteString (ByteString)-import Network.Socket hiding (recv, socket, close)-import qualified Network.Socket as NS-import qualified Data.ByteString.Char8 as C-import Control.Applicative ((<$>))-import Data.Maybe (catMaybes)-import Network.Protocol.Snmp (Coupla, Suite(..), OID)-import Network.Snmp.Client.Types (Port, Hostname)-import Data.IORef (IORef, atomicModifyIORef')-import Network.Info-import Data.Int--oidFromBS :: ByteString -> [Integer]-oidFromBS xs = catMaybes $ map (\x -> fst <$> C.readInteger x) $ C.splitWith (== '.') xs--makeSocket :: Hostname -> Port -> IO Socket-makeSocket hostname port = do-    serverAddress <- head <$> getAddrInfo (Just defaultHints) (Just hostname) (Just port)-    sock <- NS.socket (addrFamily serverAddress) Datagram defaultProtocol-    connect sock (addrAddress serverAddress)-    return sock--succCounter :: (Bounded a, Integral a) => IORef a -> IO a-succCounter ref = atomicModifyIORef' ref  check -    where-      check x -        | x < maxBound  = (succ x, succ x)-        | otherwise = (0, 0)-          -predCounter :: (Bounded a, Integral a) => IORef a -> IO a-predCounter ref = atomicModifyIORef' ref  check -    where-      check x-        | x > 0 = (pred x, pred x)-        | otherwise = (maxBound, maxBound)--lastS :: Suite -> Coupla-lastS (Suite xs) = last xs--isUpLevel :: OID -> OID -> Bool-isUpLevel new old = let baseLength = length old-                    in old /= take baseLength new --uniqID :: IO Int32-uniqID = do-    nf <- getNetworkInterfaces-    let zeroMac = MAC 0 0 0 0 0 0-        zeroIp = IPv4 0-        ipToW (IPv4 x) = x-    return $ abs . fromIntegral $ case filter (\x -> ipv4 x /= zeroIp && mac x /= zeroMac ) nf of-         [] -> 1000000 -- i cant find ip address-         [x] -> ipToW (ipv4 x)-         x:_ -> ipToW (ipv4 x)---
− src/Network/Snmp/Client/Types.hs
@@ -1,56 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE FlexibleInstances #-}-module Network.Snmp.Client.Types where--import Network.Protocol.Snmp-import Data.ByteString (ByteString)---type Hostname = String-type Port = String-type Login = ByteString---data Config = ConfigV1 -  { hostname :: Hostname-  , port :: Port-  , timeout :: Int-  , community :: Community-  }         | ConfigV2-  { hostname :: Hostname-  , port :: Port-  , timeout :: Int-  , community :: Community-  }         | ConfigV3-  { hostname :: Hostname-  , port :: Port-  , timeout :: Int-  , sequrityName :: Login-  , authPass :: Password-  , privPass :: Password-  , sequrityLevel :: PrivAuth-  , context :: ByteString-  , authType :: AuthType-  , privType :: PrivType-  }-  deriving (Show, Eq)--sec :: Int -> Int-sec = (* 1000000)--data Client = Client -  { get :: OIDS -> IO Suite-  , bulkget :: OIDS -> IO Suite -  , getnext :: OIDS -> IO Suite-  , walk :: OIDS -> IO Suite-  , bulkwalk :: OIDS -> IO Suite-  , set :: Suite -> IO Suite-  , close :: IO ()-  }--instance Construct (Version -> Config) where-    initial Version1 = ConfigV1 "localhost" "161" (sec 5) (Community "public") -    initial Version2 = ConfigV2 "localhost" "161" (sec 5) (Community "public")-    initial Version3 = ConfigV3 "localhost" "161" (sec 5) "guest" "" "" AuthNoPriv "" MD5 DES--
− src/Network/Snmp/Client/Version2.hs
@@ -1,125 +0,0 @@-module Network.Snmp.Client.Version2-( clientV1-, clientV2-)-where--import Network.Socket hiding (recv, socket, close)-import qualified Network.Socket as NS-import Network.Socket.ByteString.Lazy (recv, sendAll)-import Control.Applicative ((<$>))-import Control.Concurrent.Async-import Data.IORef (newIORef)-import Control.Concurrent (threadDelay)-import Control.Exception-import Control.Monad (when)-import Data.Monoid ((<>), mconcat, mempty)-import Data.Binary hiding (get)--import Network.Protocol.Snmp hiding (rid)-import Network.Snmp.Client.Internal-import Network.Snmp.Client.Types hiding (timeout, community, hostname, port)--v2 :: Packet-v2 = initial Version2--v1 :: Packet-v1 = initial Version1--returnResult2 :: NS.Socket -> Int -> IO Suite-returnResult2 socket timeout = do-    result <- race (threadDelay timeout) (decode <$> recv socket 1500 :: IO Packet)-    case result of-         Right packet -> do-             when (getErrorStatus packet /= 0) $ throwIO $ ServerException $ getErrorStatus packet-             return $ getSuite packet-         Left _ -> throwIO TimeoutException            --setRCS :: Community -> OIDS -> Packet -> Packet-setRCS c o = setCommunityP c . setSuite (Suite $ map (`Coupla` Zero) o)--clientV1 :: Hostname -> Port -> Int -> Community -> IO Client-clientV1 = clientV12 v1--clientV2 :: Hostname -> Port -> Int -> Community -> IO Client-clientV2 = clientV12 v2--clientV12 :: Packet -> Hostname -> Port -> Int -> Community -> IO Client-clientV12 packet hostname port timeout community = do-    socket <- makeSocket hostname port -    uniqInteger <- uniqID-    ref <- newIORef uniqInteger-    let -        req oids = setRCS community oids packet-        get' oids = withSocketsDo $ do-            let packet' = req oids-                version = getVersion packet'-            rid <- succCounter ref-            sendAll socket $ encode $ setRequest (GetRequest rid 0 0) packet'-            case version of-                 Version2 -> returnResult2 socket timeout-                 Version1 -> catch (returnResult2 socket timeout) (fixErrorV1Get oids)-                 Version3 -> error "imposible"-        fixErrorV1Get oids (ServerException 2) = return $ Suite $ map (`Coupla` NoSuchObject) oids-        fixErrorV1Get _ e = throwIO e--        bulkget' oids = withSocketsDo $ do-            rid <- succCounter ref-            sendAll socket $ encode $ setRequest (GetBulk rid 0 10) (req oids)-            returnResult2 socket timeout--        getnext' oids = withSocketsDo $ do-            let packet' = req oids-                version = getVersion packet'-            rid <- succCounter ref-            sendAll socket $ encode $ setRequest (GetNextRequest rid 0 0) packet'-            case version of-                 Version2 -> returnResult2 socket timeout-                 Version1 -> catch (returnResult2 socket timeout) (fixErrorV1GetNext oids)-                 Version3 -> error "imposible"-        fixErrorV1GetNext oids (ServerException 2) = return $ Suite $ map (`Coupla` EndOfMibView) oids-        fixErrorV1GetNext _ e = throwIO e--        walk' oids base accumulator -            | oids == base = do-                first <- get' [oids]-                next <- getnext' [oids]-                case (first, next) of-                     (Suite [Coupla _ NoSuchObject], Suite [Coupla nextOid _]) -> walk' nextOid base next-                     (Suite [Coupla _ NoSuchInstance], Suite [Coupla nextOid _]) -> walk' nextOid base next-                     (Suite [Coupla _ EndOfMibView], _) -> return accumulator-                     (_, Suite [Coupla nextOid _]) -> walk' nextOid base first-                     (_, _) -> throwIO $ ServerException 5-            | otherwise = do-                nextData <- getnext' [oids]-                let Suite [Coupla next v] = nextData-                case (isUpLevel next base, v) of-                     (True, _) -> return accumulator-                     (_, NoSuchObject) -> walk' next base accumulator-                     (_, NoSuchInstance) -> walk' next base accumulator-                     (_, EndOfMibView) -> return accumulator-                     (_, _) -> walk' next base (accumulator <> nextData) --        bulkwalk' oids base accumulator = do-               first <- bulkget' [oids]-               let Coupla next snmpData = lastS first-                   filtered (Suite xs) = Suite $ filter (\(Coupla x _) -> not $ isUpLevel x base) xs-               case (isUpLevel next base , snmpData) of-                    (_, EndOfMibView) -> return $ accumulator <> filtered first-                    (False, _) -> bulkwalk' next base (accumulator <> first)-                    (True, _) -> return $ accumulator <> filtered first-        set' oids = withSocketsDo $ do-            rid <- succCounter ref-            sendAll socket $ encode $ setRequest (SetRequest rid 0 0) . setCommunityP community . setSuite oids $ packet-            returnResult2 socket timeout--    return Client -        { get = get'-        , bulkget = bulkget'-        , getnext = getnext'-        , walk = \oids -> mconcat <$> mapM (\oi -> walk' oi oi mempty) oids-        , bulkwalk = \oids -> mconcat <$> mapM (\oi -> bulkwalk' oi oi mempty) oids-        , set = set' -        , close = NS.close socket-        } -
− src/Network/Snmp/Client/Version3.hs
@@ -1,272 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE GADTs #-}-module Network.Snmp.Client.Version3 -( clientV3-)-where--import Data.ByteString (ByteString)-import Data.ByteString.Lazy (toStrict, fromStrict)-import Network.Socket hiding (recv, socket, close)-import qualified Network.Socket as NS-import Network.Socket.ByteString.Lazy (recv, sendAll)-import Control.Applicative ((<$>))-import Control.Concurrent.Async-import Data.IORef (newIORef, IORef, readIORef, atomicWriteIORef)-import Control.Concurrent (threadDelay)-import Control.Monad (when)-import Data.ASN1.Types hiding (Context) -import Data.Monoid ((<>), mempty, mconcat)-import Data.Int-import Control.Exception -import System.Random (randomIO)-import Data.Binary --import Network.Protocol.Snmp-import Network.Snmp.Client.Types-import Network.Snmp.Client.Internal --v3 :: Packet -v3 = initial Version3 --data ST = ST-  { authCache' :: IORef (Maybe ByteString)-  , privCache' :: IORef (Maybe ByteString)-  , engine' :: IORef (Maybe (ByteString, ContextEngineID, Int32, Int32))-  , ref' :: IORef Int32-  , salt32 :: IORef Int32-  , salt64 :: IORef Int64-  , securityLevel' :: PrivAuth-  , authType' :: AuthType-  , privType' :: PrivType-  , timeout' :: Int-  , socket' :: Socket-  , login' :: Login-  , authPass' :: Password-  , privPass' :: Password-  } --clientV3 :: Hostname -> Port -> Int -> Login -> Password -> Password -> PrivAuth -> AuthType -> PrivType -> IO Client-clientV3 hostname port timeout sequrityName authPass privPass securityLevel authType privType = do-    socket <- makeSocket hostname port -    uniqInteger <- uniqID-    ref <- newIORef uniqInteger-    salt32 <- newIORef =<< abs <$> randomIO-    salt64 <- newIORef =<< abs <$> randomIO-    authCache <- newIORef Nothing-    privCache <- newIORef Nothing-    engine <- newIORef Nothing-    let st = ST authCache privCache engine ref salt32 salt64 securityLevel authType privType timeout socket sequrityName authPass privPass-    return $ Client -      { get = get' st-      , bulkget = bulkget' st-      , getnext = getnext' st-      , walk = \oids -> mconcat <$> mapM (\oi -> walk' st oi oi mempty) oids-      , bulkwalk = \oids -> mconcat <$> mapM (\oi -> bulkwalk' st oi oi mempty) oids-      , set = set' st-      , close = NS.close socket-      }---init' :: ST -> IO (ByteString, ContextEngineID, Int32, Int32)-init' st = withSocketsDo $ do-    rid <- predCounter (ref' st)-    sendAll (socket' st) $ encode $ packet' rid-    result <- race (threadDelay (timeout' st)) (decode <$> recv (socket' st) 1500 :: IO Packet)-    case result of-         Left _ -> throwIO TimeoutException-         Right resp -> do-             let pdu = (getPDU resp :: PDU V3)-             atomicWriteIORef (engine' st) $ Just (getEngineIdP resp, getContextEngineID pdu, getEngineBootsP resp, getEngineTimeP resp) -             return (getEngineIdP resp, getContextEngineID pdu, getEngineBootsP resp, getEngineTimeP resp)-    where-      packet' x = ( setIDP (ID x)-                  . setMaxSizeP (MaxSize 1500)-                  . setReportableP False-                  . setPrivAuthP NoAuthNoPriv-                  . setRid x-                  ) v3---get' :: ST -> OIDS -> IO Suite-get' st oids = withSocketsDo $ do-    full <- packet st (toEmptySuite oids) GetRequest-    sendPacket st full-    packet' <-  decryptPacketWithCache st =<< returnResult st-    checkError packet'-    return $ getSuite packet'--bulkget' :: ST -> OIDS -> IO Suite-bulkget' st oids = withSocketsDo $ do-    full <- packet st (toEmptySuite oids) GetBulk-    sendPacket st full-    packet' <-  decryptPacketWithCache st =<< returnResult st-    checkError packet'-    return $ getSuite packet'--getnext' :: ST -> OIDS -> IO Suite-getnext' st oids = withSocketsDo $ do-    full <- packet st (toEmptySuite oids) GetNextRequest-    sendPacket st full-    packet' <-  decryptPacketWithCache st =<< returnResult st-    checkError packet'-    return $ getSuite packet'--set' :: ST -> Suite -> IO Suite-set' st suite = withSocketsDo $ do-    full <- packet st suite SetRequest-    sendPacket st full-    packet' <-  decryptPacketWithCache st =<< returnResult st-    checkError packet'-    return $ getSuite packet'--walk' :: ST -> OID -> OID -> Suite -> IO Suite-walk' st oids base accumulator  -    | oids == base = do-        first <- get' st [oids]-        next <- getnext' st [oids]-        case (first, next) of-             (Suite [Coupla _ NoSuchObject], Suite [Coupla nextOid _]) -> walk' st nextOid base next-             (Suite [Coupla _ NoSuchInstance], Suite [Coupla nextOid _]) -> walk' st nextOid base next-             (Suite [Coupla _ EndOfMibView], _) -> return accumulator-             (_, Suite [Coupla nextOid _]) -> walk' st nextOid base first-             (_, _) -> throwIO $ ServerException 5-    | otherwise = do-        nextData <- getnext' st [oids]-        let Suite [Coupla next v] = nextData-        case (isUpLevel next base, v) of-             (True, _) -> return accumulator-             (_, NoSuchObject) -> walk' st next base accumulator-             (_, NoSuchInstance) -> walk' st next base accumulator-             (_, EndOfMibView) -> return accumulator-             (_, _) -> walk' st next base (accumulator <> nextData) --bulkwalk' :: ST -> OID -> OID -> Suite -> IO Suite-bulkwalk' st oids base accumulator = do-       first <- bulkget' st [oids]-       let Coupla next snmpData = lastS first-           filtered (Suite xs) = Suite $ filter (\(Coupla x _) -> not $ isUpLevel x base) xs-       case (isUpLevel next base , snmpData) of-            (_, EndOfMibView) -> return $ accumulator <> filtered first-            (False, _) -> bulkwalk' st next base (accumulator <> first)-            (True, _) -> return $ accumulator <> filtered first-     -checkError :: Packet -> IO ()-checkError p = when (getErrorStatus p /= 0) $ throwIO $ ServerException $ getErrorStatus p--toEmptySuite :: OIDS -> Suite-toEmptySuite = Suite . map (\x -> Coupla x Zero) --packet :: ST -> Suite -> (RequestId -> ErrorStatus -> ErrorIndex -> Request) -> IO Packet-packet st suite r = do-    rid <- predCounter (ref' st)-    eid' <- readIORef (engine' st)-    (eid, ceid, boots, time) <- case eid' of-                                Just x -> return x-                                Nothing -> init' st-    let wrapBulk (GetBulk rid' x _) = GetBulk rid' x 10-        wrapBulk x = x-        full = ( (setReportableP True) -               . (setPrivAuthP (securityLevel' st)) -               . (setUserNameP (login' st))  -               . (setEngineIdP eid)-               . (setContextEngineIDPacket ceid)-               . (setEngineBootsP boots)-               . (setEngineTimeP time)-               . (setAuthenticationParametersP cleanPass)  -               . (setIDP (ID rid))-               . (setRequest $ wrapBulk (r rid 0 0))-               . (setSuite  suite)-               ) v3-    return full--setContextEngineIDPacket :: ContextEngineID -> Packet -> Packet-setContextEngineIDPacket ceid packet =-    let pdu = (getPDU packet :: PDU V3)-        newpdu = setContextEngineID ceid pdu-    in setPDU newpdu packet---sendPacket :: ST -> Packet -> IO ()-sendPacket st packet' = sendAll (socket' st) . encode-      =<< signPacketWithCache st -      =<< encryptPacketWithCache st packet'--returnResult :: ST -> IO Packet-returnResult st = do-    result <- race (threadDelay (timeout' st)) (decode <$> recv (socket' st) 1500 :: IO Packet)-    case result of-         Right resp -> return resp-         Left _ -> throwIO TimeoutException--signPacketWithCache :: ST -> Packet -> IO Packet-signPacketWithCache st packet' = do-    k <- readIORef (authCache' st)-    maybe (newKey packet') (reuseKey packet') k-    where-    newKey packet'' = do-        let key = passwordToKey (authType' st) (authPass' st) (getEngineIdP packet'')-        atomicWriteIORef (authCache' st) (Just key)-        return $ signPacket (authType' st) key packet'-    reuseKey packet'' key = return $ signPacket (authType' st) key packet''--encryptPacketWithCache :: ST -> Packet -> IO Packet-encryptPacketWithCache st packet'-    | (securityLevel' st) == AuthPriv = do-        k <- readIORef (privCache' st)-        maybe (newKey packet') (reuseKey packet') k-    | otherwise = return packet'-        where-          newKey packet'' = do-              let key = passwordToKey (authType' st) (privPass' st) (getEngineIdP packet'')-              atomicWriteIORef (privCache' st) (Just key)-              encryptPacket st key packet''  -          reuseKey packet'' key = encryptPacket st key packet''--decryptPacketWithCache :: ST -> Packet -> IO Packet-decryptPacketWithCache st packet' = do-    k <- readIORef (privCache' st)-    maybe (newKey packet') (reuseKey packet') k-    where-    newKey packet'' = do-        let key = passwordToKey (authType' st) (privPass' st) (getEngineIdP packet'')-        atomicWriteIORef (privCache' st) (Just key)-        return $ decryptPacket st key packet''-    reuseKey packet'' key = return $ decryptPacket st key packet''- -encryptPacket :: ST -> Key -> Packet -> IO Packet-encryptPacket st key packet'-  | privType' st == DES = do-      s <- succCounter (salt32 st)-      let eib = getEngineBootsP packet'-          (encrypted, salt) = desEncrypt key eib s (toStrict $ encode $ (getPDU packet' :: PDU V3))-      return $ setPrivParametersP salt . setPDU (CryptedPDU encrypted) $ packet'-  | privType' st == AES = do-      s <- succCounter (salt64 st)-      let eib = getEngineBootsP packet'-          t = getEngineTimeP packet'-          (encrypted, salt) = aesEncrypt key eib t s (toStrict $ encode $ (getPDU packet' :: PDU V3))-      return $ setPrivParametersP salt . setPDU (CryptedPDU encrypted) $ packet'-  | otherwise = throwIO $ ServerException 5--decryptPacket :: ST -> Key -> Packet -> Packet-decryptPacket st key packet'-  | privType' st == DES = -      let pdu = getPDU packet' :: PDU V3-          salt = getPrivParametersP packet'-      in case pdu of-              CryptedPDU x -> setPDU (decode (fromStrict $ desDecrypt key salt x) :: PDU V3) packet'-              _ -> packet'-  | privType' st == AES =-      let pdu = getPDU packet' :: PDU V3-          salt = getPrivParametersP packet'-          eib = getEngineBootsP packet'-          t = getEngineTimeP packet'-      in case pdu of-              CryptedPDU x -> setPDU (decode (fromStrict $ aesDecrypt key salt eib t x) :: PDU V3) packet'-              _ -> packet'-  | otherwise = throw $ ServerException 5-
− src/Network/Snmp/Example.hs
@@ -1,188 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-module Network.Snmp.Example (--- * Usage--- ** Imports--- $imports---- ** Create config--- $config- --- ** Describe oids--- $oids---- ** Describe requests--- $request---- ** Do IO--- $send-) where--import Data.ByteString (ByteString)-import Control.Exception (bracket, try)--import Network.Snmp.Client-import Network.Protocol.Snmp--{- $imports-> -- imports here-> import Data.ByteString (ByteString)-> import Control.Exception (bracket, try)-> -> import Network.Snmp.Client-> import Network.Protocol.Snmp--}--{- $config-> -- First you must create config-> -- For SNMPv1-> conf1 :: Config-> conf1 = (initial Version1) { hostname = "salt" ->                            , community = Community "helloall"->                            } -> -- For SNMPv2-> conf2 :: Config-> conf2 = (initial Version2) { hostname = "salt" ->                            , community = Community "helloall"->                            } -> -> -- For SNMPv3-> conf3 :: Config-> conf3 = (initial Version3) { hostname = "salt" ->                            , sequrityName = "aes"->                            , authPass = "helloallhello"->                            , privPass = "helloallhello"->                            , authType = SHA->                            , privType = AES->                            , sequrityLevel = AuthPriv->                            } -> --}-conf1 :: Config-conf1 = (initial Version1) { hostname = "salt" -                           , community = Community "helloall"-                           } -conf2 :: Config-conf2 = (initial Version2) { hostname = "salt" -                           , community = Community "helloall"-                           } ---- For SNMPv3-conf3 :: Config-conf3 = (initial Version3) { hostname = "salt" -                           , sequrityName = "aes"-                           , authPass = "helloallhello"-                           , privPass = "helloallhello"-                           , authType = SHA-                           , privType = AES-                           , sequrityLevel = AuthPriv-                           } --{- $send-> -- do io -> client3 :: IO ()-> client3 = bracket (client conf3)->                   close->                   requests-> -> client2 :: IO ()-> client2 = bracket (client conf2)->                   close->                   requests->-> client1 :: IO ()-> client1 = bracket (client conf1)->                   close->                   requests-> --}-client3 :: IO ()-client3 = bracket (client conf3)-                  close-                  requests--client2 :: IO ()-client2 = bracket (client conf2)-                  close-                  requests--client1 :: IO ()-client1 = bracket (client conf1)-                  close-                  requests--{- $oids-> -- Describe oids which you need-> root, eth0, tabl, ipAddr, zeroDotZero :: [Integer]-> root = [1,3,6,1,2,1,2,2,1,2]-> eth0 = [1,3,6,1,2,1,2,2,1,2,1]-> tabl = [31,1,1,1,1]-> ipAddr = [1,3,6,1,2,1,4,22,1,3,3,192,168,3,1]-> zeroDotZero = [1,3,6,1,2,1,2,2,1,22,20]-> -> oi, sysUptime, memory, sysContact, bad, testOid :: ByteString-> oi = ".1.3.6.1.2.1.1.9.1.2.1"-> sysUptime = "1.3.6.1.2.1.25.1.1.0"-> memory = "1.3.6.1.2.1.25.2"-> sysContact = "1.3.6.1.2.1.1.4.0"-> bad = "1.4.6.1.2.1.1.4"-> testOid = "1.3.6.1.2.1.25.1.1.0"--}-root, eth0, tabl, ipAddr, zeroDotZero :: [Integer]-root = [1,3,6,1,2,1,2,2,1,2]-eth0 = [1,3,6,1,2,1,2,2,1,2,1]-tabl = [31,1,1,1,1]-ipAddr = [1,3,6,1,2,1,4,22,1,3,3,192,168,3,1]-zeroDotZero = [1,3,6,1,2,1,2,2,1,22,20]--oi, sysUptime, memory, sysContact, bad, testOid, inet :: ByteString-oi = ".1.3.6.1.2.1.1.9.1.2.1"-sysUptime = "1.3.6.1.2.1.25.1.1.0"-memory = "1.3.6.1.2.1.25.2"-sysContact = "1.3.6.1.2.1.1.4.0"-bad = "1.4.6.1.2.1.1.4"-testOid = "1.3.6.1.2.1.25.1.1.0"-inet = ".1.3.6.1"--{- $request-> -- Describe requests-> requests :: Client -> IO ()-> requests snmp = do->     print "get request"->     putStr . show =<< get snmp [oidFromBS testOid]->     putStr . show =<< get snmp [oidFromBS testOid]->     putStr . show =<< get snmp [oidFromBS sysUptime, oidFromBS oi, zeroDotZero]->     print "bulkget request"->     putStr . show =<< bulkget snmp [oidFromBS sysUptime]->     print "getnext request"->     putStr . show =<< getnext snmp [oidFromBS sysUptime]->     print "walk memory"->     putStr . show =<< walk snmp [oidFromBS memory]->     print "bulkwalk memory"->     putStr . show =<< bulkwalk snmp [oidFromBS memory]->     print "get sysContact"->     putStr . show =<< get snmp [oidFromBS sysContact]->     print "set sysContact"->     putStr . show =<< (try $ set snmp (Suite [Coupla (oidFromBS sysContact) (String "hello all")]) :: IO (Either ClientException Suite))->     print "get sysContact"->     putStr . show =<< get snmp [oidFromBS sysContact]--}-requests :: Client -> IO ()-requests snmp = do-    print "get request"-    putStr . show =<< get snmp [oidFromBS testOid]-    putStr . show =<< get snmp [oidFromBS sysUptime, oidFromBS oi, zeroDotZero]-    print "bulkget request"-    putStr . show =<< bulkget snmp [oidFromBS sysUptime]-    print "getnext request"-    putStr . show =<< getnext snmp [oidFromBS sysUptime]-    print "walk memory"-    putStr . show =<< walk snmp [oidFromBS memory]-    print "bulkwalk memory"-    putStr . show =<< bulkwalk snmp [oidFromBS memory]-    print "get sysContact"-    putStr . show =<< get snmp [oidFromBS sysContact]-    print "set sysContact"-    putStr . show =<< (try $ set snmp (Suite [Coupla (oidFromBS sysContact) (String "hello all")]) :: IO (Either ClientException Suite))-    print "get sysContact"-    putStr . show =<< get snmp [oidFromBS sysContact]-
+ src/Snmp/Client.hs view
@@ -0,0 +1,451 @@+{-# language BangPatterns #-}+{-# language OverloadedStrings #-}++module Snmp.Client+  ( Session(..)+  , Config(..)+  , Destination(..)+  , Credentials(..)+  , CredentialsV2(..)+  , CredentialsV3(..)+  , Context(..)+  , PerHostV3(..)+  , SnmpException(..)+  , openSession+  , closeSession+  , get+  , get'+  , getBulkStep+  , getBulkStep'+  , getBulkChildren+  , getBulkChildren'+  ) where++import Control.Applicative ((<|>))+import Control.Concurrent (Chan,newChan,writeList2Chan,readChan,threadWaitReadSTM,writeChan)+import Control.Concurrent.STM.TVar (TVar,newTVarIO,registerDelay,readTVar,writeTVar)+import Control.Exception (throwIO,Exception)+import Control.Monad (replicateM,replicateM_,when,(<=<))+import Control.Monad.STM (STM,atomically,check)+import Data.Bits ((.|.))+import Data.ByteString (ByteString)+import Data.Functor (($>))+import Data.IORef (IORef,readIORef,writeIORef,newIORef)+import Data.Int (Int32)+import Data.Map (Map)+import Data.Maybe (mapMaybe)+import Data.Vector (Vector)+import Data.Word (Word16)+import Language.Asn.Types+import Snmp.Types+import Net.Types (IPv4)+import Text.Printf (printf)+import qualified Data.ByteString as ByteString+import qualified Data.ByteString.Lazy as LB+import qualified Data.Map as Map+import qualified Data.Vector as Vector+import qualified Language.Asn.Decoding as AsnDecoding+import qualified Language.Asn.Encoding as AsnEncoding+import qualified Language.Asn.ObjectIdentifier as OID+import qualified Net.IPv4 as IPv4+import qualified Snmp.Decoding as SnmpDecoding+import qualified Snmp.Encoding as SnmpEncoding+import qualified Network.Socket as NS+import qualified Network.Socket.ByteString as NSB+import qualified System.Posix.Types++data Session = Session+  { sessionSockets :: !(Chan NS.Socket)+  -- , sessionCredsTimestamps :: !(TVar (Map Word32+  , sessionSocketCount :: !Int+  , sessionRequestId :: !(TVar RequestId)+  , sessionAesSalt :: !(TVar AesSalt)+  , sessionTimeoutMicroseconds :: !Int+  , sessionMaxTries :: !Int+  , sessionKeyCache :: !(IORef (Map (AuthType,ByteString,EngineId) ByteString))+  }++data Config = Config+  { configSocketPoolSize :: !Int+  , configTimeoutMicroseconds :: !Int+  , configRetries :: !Int+  } deriving (Show,Eq)++data Destination = Destination+  { destinationHost :: !IPv4+  , destinationPort :: !Word16+  } deriving (Show,Eq)++data Credentials+  = CredentialsConstructV2 CredentialsV2+  | CredentialsConstructV3 CredentialsV3+  deriving (Show,Eq)++newtype CredentialsV2 = CredentialsV2+  { credentialsV2CommunityString :: ByteString+  } deriving (Show,Eq)+++data CredentialsV3 = CredentialsV3+  { credentialsV3Crypto :: !Crypto+  , credentialsV3ContextName :: !ByteString+  , credentialsV3User :: !ByteString+  } deriving (Show,Eq)++data Context = Context+  { contextSession :: !Session+  , contextDestination :: !Destination+  , contextCredentials :: !Credentials+  }++data PerHostV3 = PerHostV3+  { perHostV3AuthoritativeEngineId :: !EngineId+  , perHostV3ReceiverTime :: !Int32+  , perHostV3ReceiverBoots :: !Int32+  }++-- | Only one connection can be open at a time on a given port.+openSession :: Config -> IO Session+openSession (Config socketPoolSize timeout retries) = do+  addrinfos <- NS.getAddrInfo+    (Just (NS.defaultHints {NS.addrFlags = [NS.AI_PASSIVE]}))+    (Just "0.0.0.0")+    Nothing+  let serveraddr = head addrinfos+  allSockets <- replicateM socketPoolSize $ do+    sock <- NS.socket (NS.addrFamily serveraddr) NS.Datagram NS.defaultProtocol+    NS.bind sock (NS.addrAddress serveraddr)+    return sock+  requestIdVar <- newTVarIO (RequestId 1)+  aesSaltVar <- newTVarIO (AesSalt 1)+  socketChan <- newChan+  writeList2Chan socketChan allSockets+  keyCache <- newIORef Map.empty+  return (Session socketChan socketPoolSize requestIdVar aesSaltVar timeout retries keyCache)++closeSession :: Session -> IO ()+closeSession session = replicateM_ (sessionSocketCount session) $ do+  sock <- readChan (sessionSockets session)+  NS.close sock++generalRequest ::+     (RequestId -> Pdus)+  -> (Pdu -> Either SnmpException a)+  -> Context+  -> IO (Either SnmpException a)+generalRequest pdusFromRequestId fromPdu (Context session (Destination ip port) creds) = do+  sock <- readChan (sessionSockets session)+  case creds of+    CredentialsConstructV2 (CredentialsV2 commStr) -> do+      requestId <- nextRequestId (sessionRequestId session)+      let !bs = id+            $ LB.toStrict+            $ AsnEncoding.der SnmpEncoding.messageV2+            $ MessageV2 commStr+            $ pdusFromRequestId requestId+          !bsLen = ByteString.length bs+          go1 :: Int -> IO (Either SnmpException Pdu)+          go1 !n1 = if n1 > 0+            then do+              when inDebugMode $ putStrLn "Sending:"+              when inDebugMode $ putStrLn (hexByteStringInternal bs)+              bytesSentLen <- NSB.sendTo sock bs (NS.SockAddrInet (fromIntegral port) (NS.tupleToHostAddress (IPv4.toOctets ip)))+              if bytesSentLen /= bsLen+                then return $ Left $ SnmpExceptionNotAllBytesSent bytesSentLen bsLen+                else do+                  let go2 mperHostV3 = do+                        (isReadyAction,deregister) <- threadWaitReadSTM (mySockFd sock)+                        delay <- registerDelay (sessionTimeoutMicroseconds session)+                        isContentReady <- atomically $ (isReadyAction $> True) <|> (fini delay $> False)+                        deregister+                        if not isContentReady+                          then go1 (n1 - 1)+                          else do+                            bsRecv <- NSB.recv sock 10000+                            when inDebugMode $ putStrLn "Received:"+                            when inDebugMode $ print bsRecv+                            if ByteString.null bsRecv+                              then return (Left SnmpExceptionSocketClosed)+                              else case AsnDecoding.ber SnmpDecoding.messageV2 bsRecv of+                                  Left err -> return (Left $ SnmpExceptionDecoding err)+                                  Right msg -> case messageV2Data msg of+                                    PdusResponse pdu@(Pdu respRequestId _ _ _) ->+                                      case compare requestId respRequestId of+                                        GT -> go2 mperHostV3+                                        EQ -> return (Right pdu)+                                        LT -> return $ Left $ SnmpExceptionMissedResponse requestId respRequestId+                                    _ -> return (Left (SnmpExceptionNonPduResponseV2 msg))+                  go2 Nothing+            else return $ Left SnmpExceptionTimeout+      e <- go1 (sessionMaxTries session)+      writeChan (sessionSockets session) sock+      return (e >>= fromPdu)+    CredentialsConstructV3 (CredentialsV3 crypto contextName user) -> do+      let passwordToKeyCached typ password eng = do+            keyCache <- readIORef (sessionKeyCache session)+            let triple = (typ,password,eng)+            case Map.lookup triple keyCache of+              Nothing -> do+                let key = SnmpEncoding.passwordToKey typ password eng+                writeIORef (sessionKeyCache session) (Map.insert triple key keyCache)+                return key+              Just key -> return key+      -- setting the reportable flags is very important+      -- for AuthPriv+      let flags = cryptoFlags crypto .|. 0x04+          mkAuthParams :: RequestId -> PerHostV3 -> (ByteString,ScopedPduData) -> IO ByteString+          mkAuthParams reqId phv3 privPair = case cryptoAuth crypto of+            Nothing -> return ByteString.empty+            Just (AuthParameters typ password) -> do+              key <- passwordToKeyCached typ password (perHostV3AuthoritativeEngineId phv3)+              let serializationWithoutAuth = snd (makeBs (ByteString.replicate 12 0x00) reqId privPair phv3)+              pure (SnmpEncoding.mkSign typ key serializationWithoutAuth)+          mkPrivParams :: AesSalt -> RequestId -> PerHostV3 -> IO (ByteString,ScopedPduData)+          mkPrivParams theSalt reqId phv3 = case crypto of+            AuthPriv (AuthParameters authType _) (PrivParameters privType privPass) -> do+              key <- passwordToKeyCached authType privPass (perHostV3AuthoritativeEngineId phv3)+              case privType of+                PrivTypeAes ->+                  let (encrypted,actualSaltBs) = SnmpEncoding.aesEncrypt+                        key+                        (perHostV3ReceiverBoots phv3)+                        (perHostV3ReceiverTime phv3)+                        theSalt+                        (LB.toStrict (AsnEncoding.der SnmpEncoding.scopedPdu spdu))+                   in pure (actualSaltBs,ScopedPduDataEncrypted encrypted)+                PrivTypeDes ->+                  let (encrypted,actualSaltBs) = SnmpEncoding.desEncrypt+                        key+                        (perHostV3ReceiverBoots phv3)+                        (fromIntegral (getAesSalt theSalt))+                        -- (perHostV3ReceiverTime phv3)+                        (LB.toStrict (AsnEncoding.der SnmpEncoding.scopedPdu spdu))+                   in pure (actualSaltBs,ScopedPduDataEncrypted encrypted)+            _ -> pure (ByteString.empty,ScopedPduDataPlaintext spdu)+            where spdu = ScopedPdu (perHostV3AuthoritativeEngineId phv3) contextName (pdusFromRequestId reqId)+          makeBs :: ByteString -> RequestId -> (ByteString,ScopedPduData) -> PerHostV3 -> (MessageV3,ByteString)+          makeBs activeAuthParams reqId (activePrivParams,spdud) (PerHostV3 authoritativeEngineId receiverTime boots) =+            let myMsg = MessageV3+                  (HeaderData reqId 1500 flags) -- making up a max size+                  (Usm authoritativeEngineId boots receiverTime user activeAuthParams activePrivParams)+                  spdud+                -- myMsg2 = trace ("THE MESSAGE TO SEND: " ++ show myMsg) myMsg+             in (myMsg, LB.toStrict $ AsnEncoding.der SnmpEncoding.messageV3 $ myMsg)+          fullMakeBs :: AesSalt -> RequestId -> PerHostV3 -> IO (MessageV3, ByteString)+          fullMakeBs theSalt reqId phv3 = do+            privPair <- mkPrivParams theSalt reqId phv3+            authParams <- mkAuthParams reqId phv3 privPair+            return (makeBs authParams reqId privPair phv3)+          go1 :: Int -> RequestId -> (MessageV3,ByteString) -> Bool -> IO (Either SnmpException Pdu)+          go1 !n1 !requestId (!sentMsg,!bsSent) !engineIdsAcquired = if n1 > 0+            then do+              when inDebugMode $ putStrLn "Sending:"+              when inDebugMode $ putStrLn (hexByteStringInternal bsSent)+              let bsLen = ByteString.length bsSent+              bytesSentLen <- NSB.sendTo sock bsSent (NS.SockAddrInet (fromIntegral port) (NS.tupleToHostAddress (IPv4.toOctets ip)))+              if bytesSentLen /= bsLen+                then return $ Left $ SnmpExceptionNotAllBytesSent bytesSentLen bsLen+                else do+                  let go2 :: IO (Either SnmpException Pdu)+                      go2 = do+                        (isReadyAction,deregister) <- threadWaitReadSTM (mySockFd sock)+                        delay <- registerDelay (sessionTimeoutMicroseconds session)+                        isContentReady <- atomically $ (isReadyAction $> True) <|> (fini delay $> False)+                        deregister+                        if not isContentReady+                          then do+                            when inDebugMode $ putStrLn "NO RESPONSE"+                            requestId' <- nextRequestId (sessionRequestId session)+                            go1 (n1 - 1) requestId' (sentMsg,bsSent) engineIdsAcquired+                          else do+                            bsRecv <- NSB.recv sock 10000+                            when inDebugMode $ putStrLn "Received:"+                            when inDebugMode $ putStrLn (hexByteStringInternal bsRecv)+                            if ByteString.null bsRecv+                              then return (Left SnmpExceptionSocketClosed)+                              else case AsnDecoding.ber SnmpDecoding.messageV3 bsRecv of+                                Left err -> return (Left $ SnmpExceptionDecoding err)+                                Right msg -> do+                                  case cryptoAuth crypto of+                                    Nothing -> return ()+                                    Just (AuthParameters typ password) -> do+                                      when inDebugMode $ putStrLn "THE RECEIVED MESSAGE"+                                      when inDebugMode $ print msg+                                      let reencoded = LB.toStrict $ AsnEncoding.der SnmpEncoding.messageV3 msg+                                      when inDebugMode $ putStrLn $ hexByteStringInternal $ reencoded+                                      when (reencoded /= bsRecv) $ do+                                        when inDebugMode $ putStrLn "NOT THE SAME"+                                      key <- passwordToKeyCached typ password (usmAuthoritativeEngineId (messageV3SecurityParameters msg))+                                      case SnmpEncoding.checkSign typ key msg of+                                        Nothing -> return ()+                                        Just (expected,actual) -> do+                                          when (not $ ByteString.null actual) $ do+                                            throwIO $ SnmpExceptionAuthenticationFailure expected actual+                                  let handleSpdu :: ScopedPdu -> IO (Either SnmpException Pdu)+                                      handleSpdu spdu = case scopedPduData spdu of+                                        -- check to make sure that we requested an unencrypted response+                                        -- somehow check the message id in here too+                                        PdusResponse pdu@(Pdu respRequestId _ _ _) ->+                                          case compare requestId respRequestId of+                                            GT -> go2+                                            EQ -> return (Right pdu)+                                            LT -> return $ Left $ SnmpExceptionMissedResponse requestId respRequestId+                                        PdusReport (Pdu respRequestId _ _ _) -> do+                                          when inDebugMode $ putStrLn $ "Expected Request ID: " ++ show requestId+                                          when inDebugMode $ putStrLn $ "Received Request ID: " ++ show respRequestId+                                          if engineIdsAcquired+                                            then return $ Left (SnmpExceptionBadEngineId sentMsg msg)+                                            else do+                                              let usm = messageV3SecurityParameters msg+                                                  phv3 = PerHostV3+                                                    (usmAuthoritativeEngineId usm)+                                                    (usmAuthoritativeEngineTime usm)+                                                    (usmAuthoritativeEngineBoots usm)+                                              theSalt <- atomically $ nextSalt (sessionAesSalt session)+                                              requestId' <- nextRequestId (sessionRequestId session)+                                              -- Notice that n1 is not decremented in this+                                              -- situation. This is intentional.+                                              internalFragment <- fullMakeBs theSalt requestId' phv3+                                              go1 n1 requestId' internalFragment True+                                        _ -> return (Left (SnmpExceptionNonPduResponseV3 msg))+                                  case messageV3Data msg of+                                    ScopedPduDataEncrypted encrypted -> case crypto of+                                     NoAuthNoPriv -> error "internal library error: messageV3Data NoAuthPriv"+                                     AuthNoPriv _ -> error "internal library error: messageV3Data (AuthNoPriv _)"  +                                     AuthPriv (AuthParameters authType _) (PrivParameters privType privPass) -> do+                                        let usm = messageV3SecurityParameters msg+                                        key <- passwordToKeyCached authType privPass (usmAuthoritativeEngineId usm)+                                        let mdecrypted = case privType of+                                              PrivTypeDes -> SnmpEncoding.desDecrypt key (usmPrivacyParameters usm) encrypted+                                              PrivTypeAes -> SnmpEncoding.aesDecrypt key (usmPrivacyParameters usm) (usmAuthoritativeEngineBoots usm) (usmAuthoritativeEngineTime usm) encrypted+                                        case mdecrypted of+                                          Just bs -> case AsnDecoding.ber SnmpDecoding.scopedPdu bs of+                                            Left err -> throwIO (SnmpExceptionDecoding err)+                                            Right spdu -> handleSpdu spdu+                                          Nothing -> throwIO SnmpExceptionDecryptionFailure+                                    ScopedPduDataPlaintext spdu -> handleSpdu spdu+                  go2+            else return $ Left $ SnmpExceptionTimeoutV3 sentMsg+      -- boots and estimated time are made up for this, we could do better+      let originalPhv3 = PerHostV3 (EngineId "initial-engine-id") 0xFFFFFF 0xEEEEEE+      theSalt <- atomically $ nextSalt (sessionAesSalt session)+      requestId' <- nextRequestId (sessionRequestId session)+      theFragment <- fullMakeBs theSalt requestId' originalPhv3 +      e <- go1 (sessionMaxTries session) requestId' theFragment False+      writeChan (sessionSockets session) sock+      return (e >>= fromPdu)++nextSalt :: TVar AesSalt -> STM AesSalt+nextSalt v = do+  AesSalt w <- readTVar v+  let s = AesSalt (w + 1)+  writeTVar v s+  return s++throwSnmpException :: IO (Either SnmpException a) -> IO a+throwSnmpException = (either throwIO return =<<)++get :: Context -> ObjectIdentifier -> IO ObjectSyntax+get ctx ident = throwSnmpException (get' ctx ident)++getBulkStep :: Context -> Int -> ObjectIdentifier -> IO (Vector (ObjectIdentifier,ObjectSyntax))+getBulkStep ctx maxRep ident = throwSnmpException (getBulkStep' ctx maxRep ident)++getBulkChildren :: Context -> Int -> ObjectIdentifier -> IO (Vector (ObjectIdentifier,ObjectSyntax))+getBulkChildren ctx maxRep oid1 = throwSnmpException (getBulkChildren' ctx maxRep oid1)++get' :: Context -> ObjectIdentifier -> IO (Either SnmpException ObjectSyntax)+get' ctx ident = generalRequest+  (\reqId -> PdusGetRequest (Pdu reqId (ErrorStatus 0) (ErrorIndex 0) (Vector.singleton (VarBind ident BindingResultUnspecified))))+  (singleBindingValue ident <=< onlyBindings)+  ctx++getBulkStep' :: Context -> Int -> ObjectIdentifier -> IO (Either SnmpException (Vector (ObjectIdentifier,ObjectSyntax)))+getBulkStep' ctx maxRep ident = generalRequest+  (\reqId -> PdusGetBulkRequest (BulkPdu reqId 0 (fromIntegral maxRep) (Vector.singleton (VarBind ident BindingResultUnspecified))))+  (fmap multipleBindings . onlyBindings)+  ctx++getBulkChildren' :: Context -> Int -> ObjectIdentifier -> IO (Either SnmpException (Vector (ObjectIdentifier,ObjectSyntax)))+getBulkChildren' ctx maxRep oid1 = go Vector.empty oid1 where+  go prevPairs ident = do+    epairsUnfiltered <- getBulkStep' ctx maxRep ident+    case epairsUnfiltered of+      Left e -> return (Left e)+      Right pairsUnfiltered -> do+        let pairs = Vector.filter (\(oid,_) -> oidIsPrefixOf oid1 oid) pairsUnfiltered+        if Vector.null pairs+          then return (Right prevPairs)+          else go (prevPairs Vector.++ pairs) (fst (Vector.last pairs))++oidIsPrefixOf :: ObjectIdentifier -> ObjectIdentifier -> Bool+oidIsPrefixOf = OID.isPrefixOf++-- There is not a mapMaybe for vector until 0.12.0.0+multipleBindings :: Vector VarBind -> Vector (ObjectIdentifier,ObjectSyntax)+multipleBindings = Vector.fromList . mapMaybe+  ( \(VarBind ident br) -> case br of+       BindingResultValue obj -> Just (ident,obj)+       _ -> Nothing+  ) . Vector.toList++singleBindingValue :: ObjectIdentifier -> Vector VarBind -> Either SnmpException ObjectSyntax+singleBindingValue oid v = if Vector.length v == 1+  then do+    let VarBind name res = v Vector.! 0+    when (name /= oid) $ Left $ SnmpExceptionMismatchedBinding oid name+    case res of+      BindingResultValue obj -> Right obj+      BindingResultUnspecified -> Left SnmpExceptionUnspecified+      BindingResultNoSuchObject -> Left (SnmpExceptionNoSuchObject oid)+      BindingResultNoSuchInstance -> Left (SnmpExceptionNoSuchInstance oid)+      BindingResultEndOfMibView -> Left SnmpExceptionEndOfMibView+  else Left (SnmpExceptionMultipleBindings (Vector.length v))++onlyBindings :: Pdu -> Either SnmpException (Vector VarBind)+onlyBindings (Pdu _ errStatus@(ErrorStatus e) errIndex bindings) =+  if e == 0 then Right bindings else Left (SnmpExceptionPduError errStatus errIndex)++data SnmpException+  = SnmpExceptionNotAllBytesSent !Int !Int+  | SnmpExceptionTimeout+  | SnmpExceptionTimeoutV3 !MessageV3+  | SnmpExceptionPduError !ErrorStatus !ErrorIndex+  | SnmpExceptionMultipleBindings !Int+  | SnmpExceptionMismatchedBinding !ObjectIdentifier !ObjectIdentifier+  | SnmpExceptionUnspecified -- ^ Should not happen+  | SnmpExceptionNoSuchObject !ObjectIdentifier+  | SnmpExceptionNoSuchInstance !ObjectIdentifier+  | SnmpExceptionEndOfMibView+  | SnmpExceptionMissedResponse !RequestId !RequestId+  | SnmpExceptionNonPduResponseV2 !MessageV2+  | SnmpExceptionNonPduResponseV3 !MessageV3+  | SnmpExceptionDecoding !String+  | SnmpExceptionSocketClosed+  | SnmpExceptionAuthenticationFailure !ByteString !ByteString+  | SnmpExceptionBadEngineId !MessageV3 !MessageV3+  | SnmpExceptionDecryptionFailure+  deriving (Show,Eq)++instance Exception SnmpException++fini :: TVar Bool -> STM ()+fini = check <=< readTVar++nextRequestId :: TVar RequestId -> IO RequestId+nextRequestId requestIdVar = atomically $ do+  RequestId i1 <- readTVar requestIdVar+  let !i2 = mod (i1 + 1) 100000000+      !i3 = if i2 == 0 then 1 else i2+  writeTVar requestIdVar (RequestId i3)+  return (RequestId i3)++mySockFd :: NS.Socket -> System.Posix.Types.Fd+mySockFd s = System.Posix.Types.Fd (NS.fdSocket s)++hexByteStringInternal :: ByteString -> String+hexByteStringInternal = ByteString.foldr (\w xs -> printf "%02X" w ++ xs) []++inDebugMode :: Bool+inDebugMode = False+
+ src/Snmp/Decoding.hs view
@@ -0,0 +1,160 @@+{-# language BangPatterns #-}+{-# language LambdaCase #-}+{-# language OverloadedStrings #-}++module Snmp.Decoding where++import Data.Bifunctor (first)+import Data.Coerce (coerce)+import Language.Asn.Decoding+import Language.Asn.Types+import Snmp.Types+import qualified Data.Vector as Vector+import qualified Language.Asn.Decoding as AsnDecoding++import Prelude hiding (sequence,null)++trapPdu :: AsnDecoding TrapPdu+trapPdu = sequence $ TrapPdu+  <$> required "enterprise" objectIdentifier+  <*> required "agent-addr"+      ( choice+        [ option "internet" $ tag Application 0 Implicit octetStringWord32+        ]+      )+  <*> required "generic-trap" genericTrap+  <*> required "specific-trap" integer+  <*> required "time-stamp" (tag Application 3 Implicit integer)+  <*> required "variable-bindings" (sequenceOf varBind)++genericTrap :: AsnDecoding GenericTrap+genericTrap = flip mapFailable integer $ \case+  0 -> Right GenericTrapColdStart+  1 -> Right GenericTrapWarmStart+  2 -> Right GenericTrapLinkDown+  3 -> Right GenericTrapLinkUp+  4 -> Right GenericTrapAuthenticationFailure+  5 -> Right GenericTrapEgpNeighborLoss+  6 -> Right GenericTrapEnterpriseSpecific+  _ -> Left "unrecognized generic-trap number"++messageV2 :: AsnDecoding MessageV2+messageV2 = sequence $ MessageV2+  <$  required "version" integer -- make this actually demand that it's 1+  <*> required "community" octetString+  <*> required "data" pdus++simpleSyntax :: AsnDecoding SimpleSyntax+simpleSyntax = choice+  [ fmap SimpleSyntaxInteger $ option "integer-value" int32+  , fmap SimpleSyntaxString $ option "string-value" octetString+  , fmap SimpleSyntaxObjectId $ option "objectID-value" objectIdentifier+  ]++applicationSyntax :: AsnDecoding ApplicationSyntax+applicationSyntax = choice+  [ fmap ApplicationSyntaxIpAddress+      $ option "ipAddress-value" $ tag Application 0 Implicit octetStringWord32+  , fmap ApplicationSyntaxCounter+      $ option "counter-value" $ tag Application 1 Implicit word32+  , fmap ApplicationSyntaxTimeTicks+      $ option "timeticks-value" $ tag Application 3 Implicit word32+  , fmap ApplicationSyntaxArbitrary+      $ option "arbitrary-value" $ tag Application 4 Implicit octetString+  , fmap ApplicationSyntaxBigCounter+      $ option "big-counter-value" $ tag Application 6 Implicit word64+  , fmap ApplicationSyntaxUnsignedInteger+      $ option "unsigned-integer-value" $ tag Application 2 Implicit word32+  ]++objectSyntax :: AsnDecoding ObjectSyntax+objectSyntax = choice+  [ fmap ObjectSyntaxSimple $ option "simple" simpleSyntax+  , fmap ObjectSyntaxApplication $ option "application-wide" applicationSyntax+  ]++bindingResult :: AsnDecoding BindingResult+bindingResult = choice+  [ BindingResultValue <$> option "value" objectSyntax+  , BindingResultUnspecified <$ option "unSpecified" null+  , BindingResultNoSuchObject <$ option "noSuchObject" (tag ContextSpecific 0 Implicit null)+  , BindingResultNoSuchInstance <$ option "noSuchInstance" (tag ContextSpecific 1 Implicit null)+  , BindingResultEndOfMibView <$ option "endOfMibView" (tag ContextSpecific 2 Implicit null)+  ]++varBind :: AsnDecoding VarBind+varBind = sequence $ VarBind+  <$> required "name" objectIdentifier+  -- result is not actually named in the RFC+  <*> required "result" bindingResult++pdu :: AsnDecoding Pdu+pdu = sequence $ Pdu+  <$> required "request-id" (coerce int)+  <*> required "error-status" (coerce integer)+  <*> required "error-index" (coerce int32)+  <*> required "variable-bindings" (fmap Vector.fromList $ sequenceOf varBind)++bulkPdu :: AsnDecoding BulkPdu+bulkPdu = sequence $ BulkPdu+  <$> required "request-id" (coerce int)+  <*> required "non-repeaters" int32+  <*> required "max-repetitions" int32+  <*> required "variable-bindings" (fmap Vector.fromList $ sequenceOf varBind)++pdus :: AsnDecoding Pdus+pdus = choice+  [ PdusGetRequest <$> option "get-request" (tag ContextSpecific 0 Implicit pdu)+  , PdusGetNextRequest <$> option "get-next-request" (tag ContextSpecific 1 Implicit pdu)+  , PdusGetBulkRequest <$> option "get-bulk-request" (tag ContextSpecific 5 Implicit bulkPdu)+  , PdusResponse <$> option "response" (tag ContextSpecific 2 Implicit pdu)+  , PdusSetRequest <$> option "set-request" (tag ContextSpecific 3 Implicit pdu)+  , PdusInformRequest <$> option "inform-request" (tag ContextSpecific 6 Implicit pdu)+  , PdusSnmpTrap <$> option "snmpV2-trap" (tag ContextSpecific 4 Implicit trapPdu)+  , PdusReport <$> option "report" (tag ContextSpecific 8 Implicit pdu)+  ]++-- onlyMessageId :: AsnDecoding RequestId+-- onlyMessageId = sequence++messageV3 :: AsnDecoding MessageV3+messageV3 = sequence $ MessageV3+  <$  required "msgVersion" integer -- make this actually demand that it's 3+  <*> required "msgGlobalData" headerData+  <*> required "msgSecurityParameters" +        (mapFailable (first ("while decoding security params" ++) . AsnDecoding.ber usm) octetString)+  <*> required "msgData" scopedPduDataDecoding ++headerData :: AsnDecoding HeaderData+headerData = sequence $ HeaderData+  <$> required "msgID" (coerce int)+  <*> required "msgMaxSize" int32+  <*> required "msgFlags" octetStringWord8+  <*  required "msgSecurityModel" integer -- make sure this is actually 3++-- else Left $ concat+--   [ "wrong auth flags in header data: "+--   , "expected " ++ printf "%08b" (E.cryptoFlags c)+--   , " but found " ++ printf "%08b" w+--   ]++scopedPduDataDecoding :: AsnDecoding ScopedPduData+scopedPduDataDecoding = choice+  [ fmap ScopedPduDataPlaintext $ option "plaintext" scopedPdu+  , fmap ScopedPduDataEncrypted $ option "encryptedPDU" octetString+  ]++scopedPdu :: AsnDecoding ScopedPdu+scopedPdu = sequence $ ScopedPdu+  <$> required "contextEngineID" (coerce octetString)+  <*> required "contextName" octetString+  <*> required "data" pdus++usm :: AsnDecoding Usm -- ((Crypto,Maybe MessageV3),Usm)+usm = sequence $ Usm+  <$> required "msgAuthoritativeEngineID" (coerce octetString)+  <*> required "msgAuthoritativeEngineBoots" int32+  <*> required "msgAuthoritativeEngineTime" int32+  <*> required "msgUserName" octetString+  <*> required "msgAuthenticationParameters" octetString+  <*> required "msgPrivacyParameters" octetString
+ src/Snmp/Encoding.hs view
@@ -0,0 +1,345 @@+{-# language BangPatterns #-}+{-# language LambdaCase #-}+{-# language OverloadedStrings #-}+{-# language TupleSections #-}++module Snmp.Encoding where++import Data.Bits (Bits(..))+import Data.ByteString (ByteString)+import Data.Coerce (coerce)+import Data.Int (Int32)+import Data.Maybe (fromJust)+import Data.Monoid+import Data.Word (Word64)+import Language.Asn.Encoding+import Language.Asn.Types+import Language.Asn.Types.Internal+import Prelude hiding (sequence,null)+import Snmp.Types+import qualified Crypto.Cipher.AES as Priv+import qualified Crypto.Cipher.DES as Priv+import qualified Crypto.Cipher.Types as Priv+import qualified Crypto.Data.Padding as Pad+import qualified Crypto.Error as Priv+import qualified Crypto.Hash as Hash+import qualified Crypto.MAC.HMAC as HMAC+import qualified Data.ByteArray as BA+import qualified Data.ByteString as B+import qualified Data.ByteString as ByteString+import qualified Data.ByteString.Lazy as LB+import qualified Data.List as List+import qualified Data.Vector as Vector+import qualified GHC.Exts as E+import qualified Language.Asn.Encoding as AsnEncoding++messageV2 :: AsnEncoding MessageV2+messageV2 = sequence+  [ required "version" (const 1) integer+  , required "community" messageV2CommunityString octetString+  , required "data" messageV2Data pdus+  ]++simpleSyntax :: AsnEncoding SimpleSyntax+simpleSyntax = choice+  [ SimpleSyntaxInteger 0+  , SimpleSyntaxString ByteString.empty+  , SimpleSyntaxObjectId defaultObjectIdentifier+  ] $ \case+  SimpleSyntaxInteger n -> option 0 "integer-value" n int32+  SimpleSyntaxString bs -> option 1 "string-value" bs octetString+  SimpleSyntaxObjectId oid -> option 2 "objectID-value" oid objectIdentifier++applicationSyntax :: AsnEncoding ApplicationSyntax+applicationSyntax = choice+  [ ApplicationSyntaxIpAddress 0+  , ApplicationSyntaxCounter 0+  , ApplicationSyntaxTimeTicks 0+  , ApplicationSyntaxArbitrary ByteString.empty+  , ApplicationSyntaxBigCounter 0+  , ApplicationSyntaxUnsignedInteger 0+  ] $ \case+  ApplicationSyntaxIpAddress n -> option 0 "ipAddress-value" n+    $ tag Application 0 Implicit octetStringWord32+  ApplicationSyntaxCounter n -> option 1 "counter-value" n+    $ tag Application 1 Implicit word32+  ApplicationSyntaxTimeTicks n -> option 2 "timeticks-value" n+    $ tag Application 3 Implicit word32+  ApplicationSyntaxArbitrary n -> option 3 "arbitrary-value" n+    $ tag Application 4 Implicit octetString+  ApplicationSyntaxBigCounter n -> option 4 "big-counter-value" n+    $ tag Application 6 Implicit word64+  ApplicationSyntaxUnsignedInteger n -> option 5 "unsigned-integer-value" n+    $ tag Application 2 Implicit word32++objectSyntax :: AsnEncoding ObjectSyntax+objectSyntax = choice+  [ ObjectSyntaxSimple (SimpleSyntaxInteger 0)+  , ObjectSyntaxApplication (ApplicationSyntaxCounter 0)+  ] $ \case+  ObjectSyntaxSimple v -> option 0 "simple" v simpleSyntax+  ObjectSyntaxApplication v -> option 1 "application-wide" v applicationSyntax++bindingResult :: AsnEncoding BindingResult+bindingResult = choice+  [ BindingResultValue (ObjectSyntaxSimple (SimpleSyntaxInteger 0))+  , BindingResultUnspecified+  , BindingResultNoSuchObject+  , BindingResultNoSuchInstance+  , BindingResultEndOfMibView+  ] $ \case+  BindingResultValue obj -> option 0 "value" obj objectSyntax+  BindingResultUnspecified -> option 1 "unSpecified" () null+  BindingResultNoSuchObject -> option 2 "noSuchObject" () $ implicitTag (tagFromInt 0) null+  BindingResultNoSuchInstance -> option 3 "noSuchInstance" () $ implicitTag (tagFromInt 1) null+  BindingResultEndOfMibView -> option 4 "endOfMibView" () $ implicitTag (tagFromInt 2) null++varBind :: AsnEncoding VarBind+varBind = sequence+  [ required "name" varBindName objectIdentifier+    -- result is not actually named in the RFC+  , required "result" varBindResult bindingResult+  ]++pdu :: AsnEncoding Pdu+pdu = sequence+  [ required "request-id" pduRequestId (coerce int)+  , required "error-status" pduErrorStatus (coerce integer)+  , required "error-index" pduErrorIndex (coerce int32)+  , required "variable-bindings" pduVariableBindings (sequenceOf varBind)+  ]++trapPdu :: AsnEncoding TrapPdu+trapPdu = error "Net.Snmp.Encoding.trapPdu: not yet implemented"++bulkPdu :: AsnEncoding BulkPdu+bulkPdu = sequence+  [ required "request-id" bulkPduRequestId (coerce int)+  , required "non-repeaters" bulkPduNonRepeaters int32+  , required "max-repetitions" bulkPduMaxRepetitions int32+  , required "variable-bindings" bulkPduVariableBindings (sequenceOf varBind)+  ]++pdus :: AsnEncoding Pdus+pdus = choice+  [ PdusGetRequest defaultPdu+  , PdusGetNextRequest defaultPdu+  , PdusGetBulkRequest (BulkPdu (RequestId 0) 0 0 Vector.empty)+  , PdusResponse defaultPdu+  , PdusSetRequest defaultPdu+  , PdusInformRequest defaultPdu+  , PdusSnmpTrap (TrapPdu defaultObjectIdentifier 0 GenericTrapColdStart 0 0 [])+  , PdusReport defaultPdu+  ] $ \case+  PdusGetRequest p -> option 0 "get-request" p $ implicitTag (tagFromInt 0) pdu+  PdusGetNextRequest p -> option 1 "get-next-request" p $ implicitTag (tagFromInt 1) pdu+  PdusGetBulkRequest p -> option 2 "get-bulk-request" p $ implicitTag (tagFromInt 5) bulkPdu+  PdusResponse p -> option 3 "response" p $ implicitTag (tagFromInt 2) pdu+  PdusSetRequest p -> option 4 "set-request" p $ implicitTag (tagFromInt 3) pdu+  PdusInformRequest p -> option 5 "inform-request" p $ implicitTag (tagFromInt 6) pdu+  PdusSnmpTrap p -> option 6 "snmpV2-trap" p $ implicitTag (tagFromInt 4) trapPdu+  PdusReport p -> option 7 "report" p $ implicitTag (tagFromInt 8) pdu++defaultObjectIdentifier :: ObjectIdentifier+defaultObjectIdentifier = ObjectIdentifier (E.fromList [1,3,6])++defaultPdu :: Pdu+defaultPdu = Pdu (RequestId 0) (ErrorStatus 0) (ErrorIndex 0) Vector.empty++defaultUsm :: Usm+defaultUsm = Usm defaultEngineId 0 0 ByteString.empty ByteString.empty ByteString.empty++-- messageV3 :: AsnEncoding ((Crypto,AesSalt),MessageV3)+-- messageV3 = contramap (\(c,m) -> ((c,Just m),m)) internalMessageV3++messageV3 :: AsnEncoding MessageV3+messageV3 = sequence+  [ required "msgVersion" (const 3) integer+  , required "msgGlobalData" messageV3GlobalData headerData+  , required "msgSecurityParameters" +      (\msg -> LB.toStrict (AsnEncoding.der usm (messageV3SecurityParameters msg)))+      octetString+  , required "msgData" messageV3Data scopedPduDataEncoding+  ]++headerData :: AsnEncoding HeaderData+headerData = sequence+  [ required "msgID" headerDataId (coerce int)+  , required "msgMaxSize" headerDataMaxSize int32+  , required "msgFlags" headerDataFlags octetStringWord8+  , required "msgSecurityModel" (const 3) integer+  ]++scopedPduDataEncoding :: AsnEncoding ScopedPduData+scopedPduDataEncoding = choice+  [ ScopedPduDataPlaintext defaultScopedPdu+  , ScopedPduDataEncrypted ByteString.empty+  ] $ \case+  ScopedPduDataPlaintext spdu -> option 0 "plaintext" spdu scopedPdu+  ScopedPduDataEncrypted bs -> option 1 "encryptedPDU" bs octetString++scopedPdu :: AsnEncoding ScopedPdu+scopedPdu = sequence+  [ required "contextEngineID" scopedPduContextEngineId (coerce octetString)+  , required "contextName" scopedPduContextName octetString+  , required "data" scopedPduData pdus+  ]++usm :: AsnEncoding Usm+usm = sequence+  [ required "msgAuthoritativeEngineID" usmAuthoritativeEngineId (coerce octetString)+  , required "msgAuthoritativeEngineBoots" usmAuthoritativeEngineBoots int32+  , required "msgAuthoritativeEngineTime" usmAuthoritativeEngineTime int32+  , required "msgUserName" usmUserName octetString+  , required "msgAuthenticationParameters" usmAuthenticationParameters octetString+  , required "msgPrivacyParameters" usmPrivacyParameters octetString+  ]++hmacEncodedMessage :: AuthType -> ByteString -> ByteString -> ByteString+hmacEncodedMessage x key bs = case x of+  AuthTypeMd5 -> BA.convert (HMAC.hmac key bs :: HMAC.HMAC Hash.MD5)+  AuthTypeSha -> BA.convert (HMAC.hmac key bs :: HMAC.HMAC Hash.SHA1)++hash :: AuthType -> ByteString -> ByteString+hash AuthTypeMd5 = BA.convert . (Hash.hash :: ByteString -> Hash.Digest Hash.MD5)+hash AuthTypeSha = BA.convert . (Hash.hash :: ByteString -> Hash.Digest Hash.SHA1)++hashlazy :: AuthType -> LB.ByteString -> ByteString+hashlazy AuthTypeMd5 = BA.convert . (Hash.hashlazy :: LB.ByteString -> Hash.Digest Hash.MD5)+hashlazy AuthTypeSha = BA.convert . (Hash.hashlazy :: LB.ByteString -> Hash.Digest Hash.SHA1)++passwordToKey :: AuthType -> ByteString -> EngineId -> ByteString+passwordToKey at pass (EngineId eid) = +  hash at (authKey <> eid <> authKey)+  where+  mkAuthKey = hashlazy at . LB.take 1048576 . LB.fromChunks . List.repeat+  !authKey = mkAuthKey pass++defaultAuthParams :: AuthParameters+defaultAuthParams = AuthParameters AuthTypeSha ByteString.empty++defaultPrivParams :: PrivParameters+defaultPrivParams = PrivParameters PrivTypeDes ByteString.empty++defaultScopedPdu :: ScopedPdu+defaultScopedPdu = ScopedPdu defaultEngineId ByteString.empty (PdusGetRequest defaultPdu)++defaultEngineId :: EngineId+defaultEngineId = EngineId ByteString.empty++desEncrypt :: +     ByteString +  -> Int32 +  -> Int32 +  -> ByteString +  -> (ByteString,ByteString)+desEncrypt privKey eb et =+    (,salt) . Priv.cbcEncrypt cipher iv . Pad.pad Pad.PKCS5+  where+    preIV = B.drop 8 (B.take 16 privKey)+    salt = toSalt eb et+    iv :: Priv.IV Priv.DES+    !iv = fromJust $! Priv.makeIV (B.pack $ B.zipWith xor preIV salt)+    !cipher = mkCipher (B.take 8 privKey)++desDecrypt :: ByteString -> ByteString -> ByteString -> Maybe ByteString+desDecrypt privKey salt d = do+  iv <- iv'+  pure $ stripBS $ Priv.cbcDecrypt cipher iv d+  where+    preIV = B.drop 8 (B.take 16 privKey)+    iv' :: Maybe (Priv.IV Priv.DES)+    !iv' = Priv.makeIV (B.pack $ B.zipWith xor preIV salt)+    !cipher = mkCipher (B.take 8 privKey)++aesDecrypt :: ByteString -> ByteString -> Int32 -> Int32 -> ByteString -> Maybe ByteString+aesDecrypt privKey salt eb et b = do+  iv <- iv'+  pure $ stripBS $ Priv.cfbDecrypt cipher iv b+  where+    iv' :: Maybe (Priv.IV Priv.AES128)+    !iv' = Priv.makeIV (toSalt eb et <> salt)+    !cipher = mkCipher (B.take 16 privKey)++stripBS :: ByteString -> ByteString+stripBS bs =+    let bs' = B.drop 1 bs+        l1 = fromIntegral (B.head bs')+    in if testBit l1 7+        then case clearBit l1 7 of+                  0   -> error "something bad happened while decrypting"+                  len ->+                    let size = uintbs (B.take len (B.drop 1 bs'))+                    in B.take (size + len + 2) bs+        else B.take (l1 + 2) bs+  where+    {- uintbs return the unsigned int represented by the bytes -}+    uintbs = B.foldl' (\acc n -> (acc `shiftL` 8) + fromIntegral n) 0++aesEncrypt :: ByteString -> Int32 -> Int32 -> AesSalt -> ByteString -> (ByteString,ByteString)+aesEncrypt privKey eb et (AesSalt rcounter) =+  (,salt) . Priv.cfbEncrypt cipher iv+  where+  salt = wToBs rcounter+  iv :: Priv.IV Priv.AES128+  !iv = unJust $ Priv.makeIV (toSalt eb et <> salt)+  !cipher = mkCipher (B.take 16 privKey)+  unJust = \case+    Nothing -> error "Net.Snmp.Encoding: aesEncrypt: bad salt"+    Just a -> a+   +wToBs :: Word64 -> ByteString+wToBs x = B.pack+  [ fromIntegral (x `shiftR` 56 .&. 0xff)+  , fromIntegral (x `shiftR` 48 .&. 0xff)+  , fromIntegral (x `shiftR` 40 .&. 0xff)+  , fromIntegral (x `shiftR` 32 .&. 0xff)+  , fromIntegral (x `shiftR` 24 .&. 0xff)+  , fromIntegral (x `shiftR` 16 .&. 0xff)+  , fromIntegral (x `shiftR` 8 .&. 0xff)+  , fromIntegral (x `shiftR` 0 .&. 0xff)+  ]++toSalt :: Int32 -> Int32 -> ByteString+toSalt x y = B.pack+  [ fromIntegral (x `shiftR` 24 .&. 0xff)+  , fromIntegral (x `shiftR` 16 .&. 0xff)+  , fromIntegral (x `shiftR`  8 .&. 0xff)+  , fromIntegral (x `shiftR`  0 .&. 0xff)+  , fromIntegral (y `shiftR` 24 .&. 0xff)+  , fromIntegral (y `shiftR` 16 .&. 0xff)+  , fromIntegral (y `shiftR`  8 .&. 0xff)+  , fromIntegral (y `shiftR`  0 .&. 0xff)+  ]++mkCipher :: (Priv.Cipher c) => ByteString -> c+mkCipher = (\(Priv.CryptoPassed x) -> x) . Priv.cipherInit+{-# INLINE mkCipher #-}++mkSign :: AuthType -> ByteString -> ByteString -> ByteString+mkSign at key = B.take 12 . hmacEncodedMessage at key+{-# INLINE mkSign #-}++-- mkSign :: AuthType -> ByteString -> ByteString -> ByteString+-- mkSign = error "mkSign: write this"++checkSign :: AuthType -> ByteString -> MessageV3 -> Maybe (ByteString,ByteString)+checkSign at key msg = if expected == actual+  then Nothing+  else Just (expected,actual)+  where +  raw = LB.toStrict (AsnEncoding.der messageV3 (resetAuthParams msg))+  expected = mkSign at key raw+  actual = usmAuthenticationParameters (messageV3SecurityParameters msg)++resetAuthParams :: MessageV3 -> MessageV3+resetAuthParams m = m +  { messageV3SecurityParameters = (messageV3SecurityParameters m)+    { usmAuthenticationParameters = ByteString.replicate 12 0x00+    }+  }++tagFromInt :: Int -> Tag+tagFromInt !i = Tag ContextSpecific i+{-# inline tagFromInt #-}+
+ src/Snmp/Types.hs view
@@ -0,0 +1,184 @@+{-# language BangPatterns #-}+{-# language LambdaCase   #-}++module Snmp.Types where++import Language.Asn.Types+import Data.Int (Int32)+import Data.Word (Word8,Word32,Word64)+import Data.ByteString (ByteString)+import Data.Vector (Vector)++newtype RequestId = RequestId { getRequestId :: Int }+  deriving (Eq,Ord,Show,Read)+newtype ErrorIndex = ErrorIndex { getErrorIndex :: Int32 }+  deriving (Eq,Show)+newtype ErrorStatus = ErrorStatus { getErrorStatus :: Integer }+  deriving (Eq,Show)++data ObjectSyntax+  = ObjectSyntaxSimple !SimpleSyntax+  | ObjectSyntaxApplication !ApplicationSyntax+  deriving (Eq,Show)++data SimpleSyntax+  = SimpleSyntaxInteger !Int32+  | SimpleSyntaxString !ByteString+  | SimpleSyntaxObjectId !ObjectIdentifier+  deriving (Eq,Show)++data ApplicationSyntax+  = ApplicationSyntaxIpAddress !Word32+  | ApplicationSyntaxCounter !Word32+  | ApplicationSyntaxTimeTicks !Word32+  | ApplicationSyntaxArbitrary !ByteString+  | ApplicationSyntaxBigCounter !Word64+  | ApplicationSyntaxUnsignedInteger !Word32+  deriving (Eq,Show)++data VarBind = VarBind+  { varBindName :: !ObjectIdentifier+  , varBindResult :: !BindingResult+  } deriving (Eq,Show)++data BindingResult+  = BindingResultValue !ObjectSyntax+  | BindingResultUnspecified+  | BindingResultNoSuchObject+  | BindingResultNoSuchInstance+  | BindingResultEndOfMibView+  deriving (Eq,Show)++data Pdus+  = PdusGetRequest !Pdu+  | PdusGetNextRequest !Pdu+  | PdusGetBulkRequest !BulkPdu+  | PdusResponse !Pdu+  | PdusSetRequest !Pdu+  | PdusInformRequest !Pdu+  | PdusSnmpTrap !TrapPdu+  | PdusReport !Pdu+  deriving (Eq,Show)++-- | A message as defined by RFC1157. The @version@ field is omitted+--   since it is required to be 1. The encoding and decoding of 'Message'+--   do have this field present though.+data MessageV2 = MessageV2+  { messageV2CommunityString :: !ByteString+  , messageV2Data :: !Pdus+    -- ^ In the ASN.1 definition of @Message@, this field is an @ANY@.+    --   In practice, it is always @PDUs@.+  } deriving (Eq,Show)++data MessageV3 = MessageV3+  { messageV3GlobalData :: !HeaderData+  , messageV3SecurityParameters :: !Usm+  , messageV3Data :: !ScopedPduData+  } deriving (Eq,Show)++data HeaderData = HeaderData+  { headerDataId :: !RequestId+  , headerDataMaxSize :: !Int32+  , headerDataFlags :: !Word8+  -- The Security Model is omitted because we only+  -- support USM (User Security Model, represented by the number 3),+  -- which seems to be the only one actually in use.+  -- , headerDataSecurityModel :: !Int+  } deriving (Eq,Show)++data AuthType = AuthTypeMd5 | AuthTypeSha+  deriving (Eq,Ord,Show)+data PrivType = PrivTypeDes | PrivTypeAes+  deriving (Eq,Ord,Show)++data Crypto+  = NoAuthNoPriv+  | AuthNoPriv !AuthParameters+  | AuthPriv !AuthParameters !PrivParameters+  deriving (Eq,Show)++data AuthParameters = AuthParameters+  { authParametersType :: !AuthType+  , authParametersKey :: !ByteString+  } deriving (Eq,Show)++data PrivParameters = PrivParameters+  { privParametersType :: !PrivType+  , privParametersKey :: !ByteString+  } deriving (Eq,Show)++newtype AesSalt = AesSalt { getAesSalt :: Word64 }++cryptoFlags :: Crypto -> Word8+cryptoFlags = \case+  NoAuthNoPriv -> 0+  AuthNoPriv _ -> 1+  AuthPriv _ _ -> 3++cryptoAuth :: Crypto -> Maybe AuthParameters+cryptoAuth = \case+  NoAuthNoPriv -> Nothing+  AuthNoPriv a -> Just a+  AuthPriv a _ -> Just a++cryptoPriv :: Crypto -> Maybe PrivParameters+cryptoPriv = \case+  NoAuthNoPriv -> Nothing+  AuthNoPriv _ -> Nothing+  AuthPriv _ a -> Just a++data ScopedPduData+  = ScopedPduDataPlaintext !ScopedPdu+  | ScopedPduDataEncrypted !ByteString+  deriving (Eq,Show)++newtype EngineId = EngineId { getEngineId :: ByteString }+  deriving (Eq,Ord,Show)++data ScopedPdu = ScopedPdu+  { scopedPduContextEngineId :: !EngineId+  , scopedPduContextName :: !ByteString+  , scopedPduData :: !Pdus+  } deriving (Eq,Show)++data Usm = Usm+  { usmAuthoritativeEngineId :: !EngineId+  , usmAuthoritativeEngineBoots :: !Int32+  , usmAuthoritativeEngineTime :: !Int32+  , usmUserName :: !ByteString+  , usmAuthenticationParameters :: !ByteString+  , usmPrivacyParameters :: !ByteString+  } deriving (Eq,Show)++data Pdu = Pdu+  { pduRequestId :: !RequestId+  , pduErrorStatus :: !ErrorStatus+  , pduErrorIndex :: !ErrorIndex+  , pduVariableBindings :: !(Vector VarBind)+  } deriving (Eq,Show)++data BulkPdu = BulkPdu+  { bulkPduRequestId :: !RequestId+  , bulkPduNonRepeaters :: !Int32+  , bulkPduMaxRepetitions :: !Int32+  , bulkPduVariableBindings :: !(Vector VarBind)+  } deriving (Eq,Show)++data TrapPdu = TrapPdu+  { trapPduEnterprise :: !ObjectIdentifier+  , trapPduAgentAddress :: !Word32+  , trapPduGenericTrap :: !GenericTrap+  , trapPduSpecificTrap :: !Integer+  , trapPduTimeStamp :: !Integer+  , trapPduVariableBindings :: [VarBind]+  } deriving (Eq,Show)++data GenericTrap+  = GenericTrapColdStart+  | GenericTrapWarmStart+  | GenericTrapLinkDown+  | GenericTrapLinkUp+  | GenericTrapAuthenticationFailure+  | GenericTrapEgpNeighborLoss+  | GenericTrapEnterpriseSpecific+  deriving (Eq,Show)