diff --git a/BUGS b/BUGS
deleted file mode 100644
--- a/BUGS
+++ /dev/null
@@ -1,75 +0,0 @@
-
-**
-** BUGS file for the Haskell binding to net-snmp
-**
-
-The binding is new and largely untested; there are sure to be bugs and
-many omissions.
-
-** 
-** SECURITY CONSIDERATIONS
-** 
-
-This code has not undergone any security review, and is very immature.
-It would be inappropriate to use this binding where security is a
-priority, without taking appropriate measures.
-
-** 
-** MISSING FEATURES
-** 
-
-This binding only supports a subset of the NetSNMP library's
-"single-session" api.  Only synchronous queries are supported, and only
-the get, next, and walk operations.
-
-No support for bulk get requests.
-
-No support (and none planned) for snmp traps.
-
-Many SNMP / ASN.1 data types are unsupported as yet.
-
-This binding only addresses use of the library for an snmp client.  No
-effort is made to support snmp agent or proxy operations.
-
-No support for snmpv3; currently only snmpv1 and snmpv2c with admittedly
-insecure SNMP community strings.  The documentation for the thread-safe API
-in the net-snmp C library suggests that the snmpv3 support is probably
-not thread-safe.
-
-This binding doesn't do anything with the library's log handling, and
-the library's default action is to spam stderr.  There should at least
-be a way to prevent this, and it should possibly suppress the logs by
-default.
-
-This code should be publicly hosted, perhaps on code.haskell.org.  It
-should use a public trac.
-
-** 
-** BROKENNESS
-** 
-
-Looking up OIDs by name doesn't seem to work yet.  Once it's fixed
-snmpwalk probably needs to be fixed as well.  It uses `isPrefixOf` to
-determine when the walk is over, which won't work if the original
-oid isn't dotted-decimal.
-
-There are too many things called 'session' in the library, and in the
-binding:
--  the C struct snmp_session.  The 'single session' examples use *3* of
-   these, with subtly different purposes, never fully explained.
--  data SnmpSession, the binding's representation of 'struct snmp_session'
--  data Session, the binding's abstract session container, holding
-   the above and managing C memory (de)allocation
-
-snmpWalk doesn't check for cyclical responses from an agent; reportedly
-there are agents with this misfeature.  Currently if it happens snmpWalk
-will happily follow the cycle until it runs out of memory or stack.
-
-I don't know how to intelligently set the alignment parameter for data
-types representing C structs in their Storable instances.  I'm using 16
-bytes as a (hopefully) conservative setting, but isn't there a way to
-detect and mimic what C uses?
-
-The binding is currently one monolithic .hsc file.  It should probably
-be organized into a few modules.
-
diff --git a/NetSNMP.cabal b/NetSNMP.cabal
--- a/NetSNMP.cabal
+++ b/NetSNMP.cabal
@@ -1,6 +1,6 @@
 
 Name:               NetSNMP
-Version:            0.1.6
+Version:            0.2.0.2
 Synopsis:           Bindings for net-snmp's C API for clients
 Description:        Network.Protocol.NetSNMP is a partial binding to the
                     library portion of the net-snmp package.  It uses the
@@ -10,15 +10,15 @@
                     expanded functionality, and especially if you would
                     like to contribute.
 Category:           Network
-Copyright:          (c) John Dorsey 2009
 Cabal-Version:      >= 1.2
 License:            BSD3
 License-file:       LICENSE
-Author:             John Dorsey <haskell@colquitt.org>
-Maintainer:         John Dorsey <haskell@colquitt.org>
+Author:             Pavlo Kerestey and Humane Software for Global Access Internet Services GmbH
+Maintainer:         Pavlo Kerestey <pavlo@kerestey.net>
 Stability:          alpha
 Build-type:         Simple
-Bug-reports:        mailto:haskell@colquitt.org
+Homepage:           https://github.com/ptek/netsnmp
+Bug-reports:        https://github.com/ptek/netsnmp/issues
 
 library
   hs-source-dirs:   src
@@ -27,4 +27,4 @@
   exposed-modules:  Network.Protocol.NetSNMP
   extensions:       ForeignFunctionInterface, CPP, EmptyDataDecls
   extra-libraries:  netsnmp
-
+  ghc-options:      -static -optc-static -optl-static -optl-pthread
diff --git a/README b/README
deleted file mode 100644
--- a/README
+++ /dev/null
@@ -1,27 +0,0 @@
-
-The (Haskell) NetSNMP package is a binding for a subset of the libsnmp
-api provided by the NetSNMP project.  It is initially being developed
-against NetSNMP version 5.4.1, but probably works with most or all 5.*
-versions.
-
-Currently supported protocol versions:
-  SNMPv1  -- original SNMP
-  SNMPv2c -- v2 protocol with old community-based security
-
-Not yet supported:
-  SNMPv3  -- v2 protocol plus new v3 party-based security
-
-Other versions are not supported by the underlying library, and are
-unlikely to ever be supported by this package.
-  SNMPsec -- first attempt to add strong security to SNMPv1
-  SNMPv2p -- initial SNMPv2, with v2 party-based security
-  SNMPv2u -- v2 protocol with user-based security
-  SNMPv2* -- proprietary hybrid variant of v2c and v2p
-
-This binding requires that net-snmp be built without
-NETSNMP_DISABLE_SNMPV1 or NETSNMP_DISABLE_SNMPV2C.  I'd love to support
-those options, since they may encourage better security, but I won't be able
-to prioritize this in the forseeable future.
-
-See also: BUGS
-
diff --git a/src/Network/Protocol/NetSNMP.hsc b/src/Network/Protocol/NetSNMP.hsc
--- a/src/Network/Protocol/NetSNMP.hsc
+++ b/src/Network/Protocol/NetSNMP.hsc
@@ -1,5 +1,5 @@
 
-{-# LANGUAGE CPP, ForeignFunctionInterface, EmptyDataDecls #-}
+{-# LANGUAGE CPP, DoAndIfThenElse, ForeignFunctionInterface, EmptyDataDecls #-}
 
 ----------------------------------------------------------------------
 -- |
@@ -24,7 +24,7 @@
   -- ** Library Initialization
   initialize,
   -- ** Queries
-  snmpGet, snmpNext, snmpWalk,
+  snmpGet, snmpNext, snmpWalk, snmpBulkWalk,
   -- ** Miscellany
   showASNValue,
   )
@@ -88,7 +88,7 @@
   | Integer32   Int32          -- ^@ASN_INTEGER@  32bit signed
   | Integer64   Int64          -- ^@ASN_INTEGER64@  64bit signed
   | Counter32   Word32         -- ^@ASN_COUNTER@ 32bit nondecreasing
-  | Counter64   Word64         -- ^@ASN_COUNTER64@ 64bit nondecreasing
+  | Counter64   Word64          -- ^@ASN_COUNTER64@ 64bit nondecreasing
   | Unsigned32  Word32         -- ^@ASN_UNSIGNED@ 32bit unsigned
   | Unsigned64  Word64         -- ^@ASN_UNSIGNED64@ 64bit unsigned
   | Gauge32     Word32         -- ^@ASN_GAUGE@ 32bit signed with min and max
@@ -314,14 +314,14 @@
 --     through all objects underneath that OID in the mib tree.
 --     On failure, returns a descriptive error message.
 --
--- The current implementation uses a series of next operations, but an
--- implementation using bulk requests would be more efficient.
+-- This implementation uses a series of next operations and is not very
+-- ressource friendly. Consider using snmpBulkWalk for better performance
 --
 -- Examples:
 --
--- * snmpWalk \"localhost\" \"public\" \".1.3.6.1.2.1.1\"
+-- * snmpWalk snmp_version_2c \"localhost\" \"public\" \".1.3.6.1.2.1.1\"
 --
--- * snmpWalk \"tcp:localhost:5161\" \"mypassword\" \".1.3.6.1.2.1.1\"
+-- * snmpWalk snmp_version_2c \"tcp:localhost:5161\" \"mypassword\" \".1.3.6.1.2.1.1\"
 snmpWalk
   :: SnmpVersion -- ^'snmp_version_1' or 'snmp_version_2c'
   -> Hostname    -- ^IP or hostname of the agent to be queried.  May have
@@ -348,17 +348,72 @@
             return (v:vs)
           | otherwise -> return [] -- throwT "end of walk" -- return []
 
+
+-- |Same as snmpWalk but implemented with bulk requests
+--
+-- Examples:
+--
+-- * snmpBulkWalk \"localhost\" \"public\" \".1.3.6.1.2.1.1\"
+--
+-- * snmpBulkWalk \"tcp:localhost:5161\" \"mypassword\" \".1.3.6.1.2.1.1\"
+snmpBulkWalk 
+  :: Hostname    -- ^IP or hostname of the agent to be queried.  May have
+                 --     prefix of @tcp:@ or suffix of @:port@
+  -> Community   -- ^SNMP community (password)
+  -> String      -- ^OID to be queried
+  -> IO (Either String [SnmpResult])
+snmpBulkWalk hostname community walkoid =
+    withCString hostname  $ \cshost  ->
+    withCString community $ \cscomm  ->
+    alloca                $ \session ->
+    runTrouble $ bracketT
+      (readyCommunitySession snmp_version_2c cshost cscomm session)
+      closeSession
+      (bulkWalk walkoid walkoid)
+  where
+    bulkWalk :: String -> String -> Session -> Trouble [SnmpResult]
+    bulkWalk rootoid startoid session = do
+      vals <- filter (\r -> (oid r) `isSubIdOf` rootoid) <$> mkSnmpBulkGet 0 50 startoid session
+      case vals of
+        [] -> return []
+        rs -> (vals ++) <$> bulkWalk rootoid (oid (last rs)) session
+    isSubIdOf :: String -> String -> Bool
+    isSubIdOf oa ob = (splitAt '.' ob) `isPrefixOf` (splitAt '.' oa)
+    splitAt :: Char -> String -> [String]
+    splitAt c s = case dropWhile (c ==) s of
+                      "" -> []
+                      s' -> w : splitAt c s''
+                            where (w, s'') = break (c ==) s'
+  
+-- getbulk, using session info from a 'data Session' and
+-- the supplied oid
+-- It is the caller's obligation to ensure the session's validity.  
+mkSnmpBulkGet :: CLong -> CLong -> String -> Session -> Trouble [SnmpResult]
+mkSnmpBulkGet non_repeaters max_repetitions oid session =
+  allocaArrayT (fromIntegral max_oid_len) $ \oids -> do
+  let version = getVersion session
+  pdu_req <- buildPDU snmp_msg_getbulk oid oids version
+  pokePDUNonRepeaters pdu_req non_repeaters
+  pokePDUMaxRepetitions pdu_req max_repetitions
+  dispatchSnmpReq pdu_req session
+
 -- get or getnext, using session info from a 'data Session' and
 -- the supplied oid
 -- It is the caller's obligation to ensure the session's validity.
 mkSnmpGet :: SnmpPDUType -> Session -> String -> Trouble SnmpResult
-mkSnmpGet pdutype session oid =
+mkSnmpGet pdutype session oid = do
+  res <- (allocaArrayT (fromIntegral max_oid_len) $ \oids -> do
+         let version = getVersion session
+         pdu_req <- buildPDU pdutype oid oids version
+         dispatchSnmpReq pdu_req session)
+  if (res == []) then throwT ("Could not get the snmp value at " ++ oid)
+  else return $ head res
+
+dispatchSnmpReq :: Ptr SnmpPDU -> Session -> Trouble [SnmpResult]
+dispatchSnmpReq pdu_req session = do
   allocaT $ \response_ptr -> do
-  allocaArrayT (fromIntegral max_oid_len) $ \oids -> do
-  let version = getVersion session
   let sessp = getSessp session
   let sptr = getSptr session
-  pdu_req <- buildPDU pdutype oid oids version
   pokeT response_ptr nullPtr
   handleT
     (\s -> do
@@ -371,9 +426,9 @@
       errstat <- peekPDUErrstat pdu_resp
       when (errstat /= snmp_err_noerror) (throwT "response PDU error")
       rawvars <- peekPDUVariables pdu_resp
-      vars <- extractVar rawvars
+      vars <- extractVars rawvars
       unless (pdu_resp == nullPtr) $ t_snmp_free_pdu pdu_resp
-      return vars)
+      return vars)  
 
 -- caller is obliged to ensure rv is valid and non-null
 vlist2oid :: Ptr CVarList -> Trouble String
@@ -405,13 +460,10 @@
     _ | t == asn_opaque       -> extractOpaque       rv
     _ | t == asn_integer      -> extractIntegralType rv Integer32
     _ | t == asn_unsigned     -> extractIntegralType rv Unsigned32
-    _ | t == asn_counter64    -> extractIntegralType rv Counter64
-    _ | t == asn_integer64    -> extractIntegralType rv Integer64
-    _ | t == asn_unsigned64   -> extractIntegralType rv Unsigned64
+    _ | t == asn_counter64    -> extractIntegral64Type rv Counter64
+    _ | t == asn_integer64    -> extractIntegral64Type rv Integer64
+    _ | t == asn_unsigned64   -> extractIntegral64Type rv Unsigned64
     _ | t == asn_object_id    -> extractOID          rv
-    -- _ | t == asn_boolean      -> extractBoolean      rv
-    -- _ | t == asn_double       -> extractDouble       rv
-    -- _ | t == asn_float        -> extractFloat        rv
     _ | t == asn_null         -> return Null
     _ -> do
           descr <- rawvar2cstring rv
@@ -436,6 +488,11 @@
   n <- fromIntegral <$> peekT intptr
   return (constructor n)
 
+extractIntegral64Type rv constructor = do
+  ptr <- peekVariableValInt rv
+  (high:low:[]) <- peekArrayT 2 (castPtr ptr) :: Trouble [Word64]
+  return (constructor (fromIntegral ((high * (2 ^ 32) + low) :: Word64)))
+
 extractIpAddress rv = do
   ptr <- peekVariableValInt rv
   octets <- peekArrayT 4 (castPtr ptr) :: Trouble [Word8]
@@ -583,6 +640,12 @@
 pokePDUCommand :: Ptr SnmpPDU -> CInt -> Trouble ()
 pokePDUCommand p t = hoistT $ #{poke struct snmp_pdu , command} p t
 
+pokePDUNonRepeaters :: Ptr SnmpPDU -> CLong -> Trouble ()
+pokePDUNonRepeaters p n = hoistT $ #{poke struct snmp_pdu , non_repeaters} p n
+
+pokePDUMaxRepetitions :: Ptr SnmpPDU -> CLong -> Trouble ()
+pokePDUMaxRepetitions p r = hoistT $ #{poke struct snmp_pdu , max_repetitions} p r
+
 --
 -- The C library layer
 --
@@ -678,15 +741,15 @@
 t_snmp_sess_synch_response sessp sptr pdu_req response_ptr = Trouble $ do
   success <- c_snmp_sess_synch_response sessp pdu_req response_ptr
   -- snmpSessError was giving bus errors on x86_64
-  -- if (success == snmp_stat_success)
-  --   then return (Right ())
-  --   else Left <$> snmpSessError sptr
-  return $ case () of
-    _ | success == snmp_stat_success -> Right ()
-      | success == snmp_stat_error   -> Left "snmp_sess_synch_response error"
-      | success == snmp_stat_timeout -> Left "snmp_sess_synch_response timeout"
-      | otherwise -> Left
-          ("snmp_sess_synch_response unknown error code " ++ show success)
+  if (success == snmp_stat_success)
+    then return (Right ())
+    else Left <$> snmpError sptr
+  -- return $ case () of
+  --   _ | success == snmp_stat_success -> Right ()
+  --     | success == snmp_stat_error   -> Left "snmp_sess_synch_response error"
+  --     | success == snmp_stat_timeout -> Left "snmp_sess_synch_response timeout"
+  --     | otherwise -> Left
+  --         ("snmp_sess_synch_response unknown error code " ++ show success)
 
 -- Deallocate PDU struct
 foreign import ccall unsafe "net-snmp/net-snmp-includes.h snmp_free_pdu"
@@ -862,4 +925,3 @@
 
 predToMaybe :: (a -> Bool) -> b -> a -> Maybe b
 predToMaybe p b a = if (p a) then Just b else Nothing
-
