hsns (empty) → 0.5
raw patch · 6 files changed
+292/−0 lines, 6 filesdep +basedep +networkdep +pcapbuild-type:Customsetup-changed
Dependencies added: base, network, pcap
Files
- Hsns.hs +127/−0
- LICENSE +31/−0
- Options.hs +43/−0
- README +71/−0
- Setup.lhs +3/−0
- hsns.cabal +17/−0
+ Hsns.hs view
@@ -0,0 +1,127 @@+--run as root, otherwise you'll fail with an device error+module Main where+import System.Console.GetOpt+import System.Environment+import System.Process+import qualified Network.Pcap as PCap+import Control.Monad+import Text.Printf+import System.Exit+import Data.Maybe+import System.IO+import Data.List+import Data.Char+import Options+import Foreign++++-- our packet output format+data PacketFmt = PacketFmt {+ ascii :: String,+ hexadecimal :: [Word8]+ }+ deriving (Eq,Show)++initPktFmt a h = + PacketFmt {+ ascii = a,+ hexadecimal = h+}++hsnsVersion = "hsns: the haskell network sniffer, version 0.5"++formatData :: PacketFmt -> IO ()+formatData pf = do+ let (x,x') = splitAt 10 a+ (y,y') = splitAt 10 h+ unless (x' == [] && y' == []) $ do+ mapM_ (printf "%02.2x ") (fmtHex y)+ printf "\t\t%s\n" x+ formatData (initPktFmt x' y')+ return ()+ where+ a = ascii pf+ h = hexadecimal pf+ fmtHex :: [Word8] -> [Int]+ fmtHex bytes = [ (read $ show y) | y <- bytes] :: [Int]+ +captcha :: PCap.PktHdr -> Ptr Word8 -> IO ()+captcha pkth datap = do+ a <- peekArray (fromIntegral (PCap.caplen pkth)) datap+ s <- return $ map (\x -> if (x >= 32 && x <= 126) then x else 46) a+ s' <- return $ map (\x -> chr (read $ show x)) s+ formatData (initPktFmt s' a)+ printf "\n"+ hFlush stdout++starter :: HsnsOpts -> IO ()+starter o = do++ -- options that don't depend on anything else+ if (help o) == "True" then putStrLn (usageInfo "hsns: \"filter program\" [OPTIONS]..." options) >> exitWith ExitSuccess + else return ()+ if (version o) == "True" then (putStrLn hsnsVersion >> (exitWith ExitSuccess)) else return () + if (buffered o) == "True" then hSetBuffering stdout LineBuffering else return ()++ -- our variables, the interface-listing option depends on these and therefore root access+ devs <- PCap.findAllDevs+ let devnames = map (\i -> (PCap.ifName i)) devs+ let dev = (interface o)+ net <- PCap.lookupNet dev+ spy <- PCap.openLive dev (read $ snarflen o) (if (nopromiscuous o) == "True" then True else False) 100000++ if (iflist o) == "True" then do+ putStrLn "interfaces:" + mapM_ (printf " -- %s\n") devnames+ exitWith ExitSuccess+ else return ()+ + withForeignPtr spy $ \ptr -> do+ -- set our filter, it must happen in this context as spy is+ -- a ForeignPtr, rather than a Ptr like we need for+ -- setFilter/loop++ if (bpf o) == "" then return () else PCap.setFilter ptr (bpf o) False (PCap.netMask net)+ -- loop and capture+ PCap.loop ptr (read $ count o) captcha+ --print statistics+ s <- PCap.statistics ptr+ putStrLn ("Packets recieved: " ++ (show $ PCap.recv s))+ putStrLn ("Packets dropped: " ++ (show $ PCap.drop s))+ putStrLn ("Packets dropped by interface: " ++ (show $ PCap.ifdrop s))++++main = do+ (o,n) <- parseOpts -- our options and filter in a pair, we assume the filter is the first thing+ -- on the command line++ starter (create o n)+ return ()+ where+ parseOpts = (getArgs >>= hsnsOptions)+ create x f =+ let y = construct x in+ Opts {count = fromMaybe "5" (lookup "count" y),+ snarflen = fromMaybe "68" (lookup "snarf" y),+ interface = fromMaybe "eth0" (lookup "listen" y),+ version = fromMaybe "False" (lookup "version" y),+ nopromiscuous = fromMaybe "False" (lookup "nopromisc" y),+ iflist = fromMaybe "False" (lookup "ifList" y),+ buffered = fromMaybe "False" (lookup "buffered" y),+ help = fromMaybe "False" (lookup "help" y),+ bpf = if f == [] then "" else (f !! 0)+ }++ construct f = map construct' f+ where+ construct' x = case x of+ Help -> ("help","True")+ Count s -> ("count",s)+ SnarfLen s -> ("snarf",s)+ Listen s -> ("listen",s)+ NoPromiscuous -> ("nopromisc","True")+ IfList -> ("ifList","True")+ LineBuffered -> ("buffered","True")+ Version -> ("version","True")
+ LICENSE view
@@ -0,0 +1,31 @@+Copyright Austin Seipp 2007++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 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 Austin Seipp nor the names of other+ 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+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+
+ Options.hs view
@@ -0,0 +1,43 @@+module Options where+import System.Console.GetOpt+import Data.Maybe++data HsnsOpts = Opts {+ count :: String, --done+ snarflen :: String, --done+ interface :: String, --done+ version :: String, --done+ nopromiscuous :: String, --done+ iflist :: String, --done+ buffered :: String, --done+ help :: String, --done+ bpf :: String -- filter string that will be passed to setfilter+}++data Flags =+ Count String | -- amount of packets to take, must be String in constructor, that's how getOpt returns it+ IfList | -- List the available interfaces+ Listen String | -- Listen on the specified interface+ LineBuffered | -- Turn on Line buffering+ NoPromiscuous | -- Don't go into promiscuous mode.+ SnarfLen String | -- Amount of data to snarf, default is 68+ Version | -- version number+ Help -- help info++options :: [OptDescr Flags]+options = [ Option ['h','?'] ["help"] (NoArg Help) "print this help information"+ ,Option ['c'] ["count"] (ReqArg Count "NUM") "take in NUM packets, default is 5, 0 means unlimited"+ ,Option ['D'] ["iflist"] (NoArg IfList) "list interfaces that can be captured upon"+ ,Option ['i'] ["interface"] (ReqArg Listen "INT") "listen on interface INT, defaults to eth0"+ ,Option ['l'] ["linebuffered"] (NoArg LineBuffered) "make output line-buffered"+ ,Option ['p'] ["nopromiscuous"] (NoArg NoPromiscuous) "do not go into promiscuous mode"+ ,Option ['s'] ["snarf"] (ReqArg SnarfLen "LEN") "change snarf length from default 68 to LEN"+ ,Option ['V'] ["version"] (NoArg Version) "output version number and exit"]++hsnsOptions :: [String] -> IO ([Flags],[String])+hsnsOptions av = do+ case getOpt Permute options av of+ (o,n,[]) -> return (o,n)+ (_,_,e) -> ioError (userError (concat e ++ usageInfo header options))+ where+ header = "usage: hsns \"[PACKET FILTER]\" [OPTIONS...]"
+ README view
@@ -0,0 +1,71 @@+hsns: the haskell network sniffer.++* What is Hsns?+* Installation+* Packet filters+* Options+++What is Hsns?+=============+hsns is a packet sniffer for unicies written totally+in Haskell (http://www.haskell.org) Currently, hsns +has only been tested to work on Linux. +++Installation+============+To install, you need to have a haskell compiler such as the+Glasgow Haskell Compiler installed, the Pcap library to be+installed, and the Network.Pcap libraries for GHC.+You may obtain Network.Pcap from http://hackage.haskell.org++To install, run the Setup.lhs script like so (you can skip+the chmod part if you have pulled hsns from the darcs+repository with the --set-scripts-executable flag):++[austin@continuum hsns]$ chmod +x ./Setup.lhs+[austin@continuum hsns]$ ./Setup.lhs configure+...+[austin@continuum hsns]$ ./Setup.lhs build+...+[austin@continuum hsns]$ su -c './Setup.lhs install'+Password: +...+[austin@continuum hsns]$ ++hsns is now installed.+++Packet filters+==============+hsns can receive a berkeley packet filter+in it's command line (anywhere) that can+be used to filter packets in the same style+as Tcpdump. For a reference on bpf's, see the+tcpdump man page.+++Options+=======++Currently, hsns accepts the following options:++ -h,-? --help Display help++ -c[COUNT] --count=COUNT Exit after receiving COUNT packets.+ 0 is receive forever, default is 5.++ -D --iflist List interfaces that can be captured+ on++ -i INT --interface=INT Listen on interface INT.+ + -l --linebuffered Make output line buffered.++ -p --nopromiscuous Do not go into promiscuous mode+ + -s LEN --snarf=LEN change snarf length from 68 (default)+ to LEN.++ -V --version Display version and exit.
+ Setup.lhs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ hsns.cabal view
@@ -0,0 +1,17 @@+Name: hsns+Version: 0.5+Description: a network sniffer written in a purely fun language+Synopsis: the haskell network sniffer+Category: Network+License: BSD3+License-file: LICENSE+Author: Austin Seipp +Maintainer: austin@youareinferior.net+Build-Depends: base,network,pcap+Extra-source-files: README,+ Options.hs++ +Executable: hsns+Main-is: Hsns.hs+ghc-options: -O -lpcap