From 6ed86650fa6420bd015ff615dfd3d51aaaeceb07 Mon Sep 17 00:00:00 2001
From: Phil <phil@secdev.org>
Date: Sun, 10 Aug 2008 20:22:17 +0200
Subject: [PATCH] Reintroduced lsc() command

---
 scapy/config.py           | 17 +++++++++++++++++
 scapy/layers/bluetooth.py |  4 ++++
 scapy/layers/dns.py       |  4 ++++
 scapy/layers/inet.py      |  4 ++++
 scapy/layers/l2.py        |  8 ++++++++
 scapy/modules/geoip.py    |  3 ++-
 scapy/modules/nmap.py     |  3 ++-
 scapy/modules/p0f.py      |  3 ++-
 scapy/modules/queso.py    |  1 +
 scapy/packet.py           |  8 +++++++-
 scapy/sendrecv.py         | 14 +++++++++++++-
 scapy/utils.py            | 13 +++++++++++++
 12 files changed, 77 insertions(+), 5 deletions(-)

diff --git a/scapy/config.py b/scapy/config.py
index 260019bd..6f241ee5 100644
--- a/scapy/config.py
+++ b/scapy/config.py
@@ -111,6 +111,22 @@ class LayersList(list):
     def register(self, layer):
         self.append(layer)
 
+class CommandsList(list):
+    def __repr__(self):
+        s=[]
+        for l in sorted(self,key=lambda x:x.__name__):
+            if l.__doc__:
+                doc = l.__doc__.split("\n")[0]
+            else:
+                doc = "--"
+            s.append("%-20s: %s" % (l.__name__,doc))
+        return "\n".join(s)
+    def register(self, cmd):
+        self.append(cmd)
+        return cmd # return cmd so that method can be used as a decorator
+
+def lsc():
+    print repr(conf.commands)
 
 class CacheInstance(dict):
     def __init__(self, name="noname", timeout=None):
@@ -211,6 +227,7 @@ extensions_paths: path or list of paths where extensions are to be looked for
     stealth = "not implemented"
     iface = arch.get_working_if()
     layers = LayersList()
+    commands = CommandsList()
     logLevel = LogLevel()
     checkIPID = 0
     checkIPsrc = 1
diff --git a/scapy/layers/bluetooth.py b/scapy/layers/bluetooth.py
index d48e2929..96ef5990 100644
--- a/scapy/layers/bluetooth.py
+++ b/scapy/layers/bluetooth.py
@@ -183,13 +183,17 @@ class BluetoothHCISocket(SuperSocket):
 ## Bluetooth
 
 
+@conf.commands.register
 def srbt(peer, pkts, inter=0.1, *args, **kargs):
+    """send and receive using a bluetooth socket"""
     s = conf.BTsocket(peer=peer)
     a,b,c=sndrcv(s,pkts,inter=inter,*args,**kargs)
     s.close()
     return a,b
 
+@conf.commands.register
 def srbt1(peer, pkts, *args, **kargs):
+    """send and receive 1 packet using a bluetooth socket"""
     a,b = srbt(peer, pkts, *args, **kargs)
     if len(a) > 0:
         return a[0][1]
diff --git a/scapy/layers/dns.py b/scapy/layers/dns.py
index 1ca3df0b..7ca570e1 100644
--- a/scapy/layers/dns.py
+++ b/scapy/layers/dns.py
@@ -255,6 +255,9 @@ class DNSRR(Packet):
 
 bind_layers( UDP,           DNS,           dport=53)
 bind_layers( UDP,           DNS,           sport=53)
+
+
+@conf.commands.register
 def dyndns_add(nameserver, name, rdata, type="A", ttl=10):
     """Send a DNS add message to a nameserver for "name" to have a new "rdata"
 dyndns_add(nameserver, name, rdata, type="A", ttl=10) -> result code (0=ok)
@@ -276,6 +279,7 @@ RFC2136
     
     
 
+@conf.commands.register
 def dyndns_del(nameserver, name, type="ALL", ttl=10):
     """Send a DNS delete message to a nameserver for "name"
 dyndns_del(nameserver, name, type="ANY", ttl=10) -> result code (0=ok)
diff --git a/scapy/layers/inet.py b/scapy/layers/inet.py
index 055b4918..ea802e2d 100644
--- a/scapy/layers/inet.py
+++ b/scapy/layers/inet.py
@@ -521,7 +521,9 @@ conf.neighbor.register_l3(Ether, IP, lambda l2,l3: getmacbyip(l3.dst))
 ## Fragmentation ##
 ###################
 
+@conf.commands.register
 def fragment(pkt, fragsize=1480):
+    """Fragment a big IP datagram"""
     fragsize = (fragsize+7)/8*8
     lst = []
     for p in pkt:
@@ -554,6 +556,7 @@ def overlap_frag(p, overlap, fragsize=8, overlap_fragsize=None):
     qfrag[-1][IP].flags |= 1
     return qfrag+fragment(p, fragsize)
 
+@conf.commands.register
 def defrag(plist):
     """defrag(plist) -> ([not fragmented], [defragmented],
                   [ [bad fragments], [bad fragments], ... ])"""
@@ -617,6 +620,7 @@ def defrag(plist):
         defrag2.append(p.__class__(str(p)))
     return nofrag,defrag2,missfrag
             
+@conf.commands.register
 def defragment(plist):
     """defrag(plist) -> plist defragmented as much as possible """
     frags = {}
diff --git a/scapy/layers/l2.py b/scapy/layers/l2.py
index 097efa66..16e8752f 100644
--- a/scapy/layers/l2.py
+++ b/scapy/layers/l2.py
@@ -38,7 +38,9 @@ conf.neighbor = Neighbor()
 conf.netcache.new_cache("arp_cache", 120) # cache entries expire after 120s
 
 
+@conf.commands.register
 def getmacbyip(ip, chainCC=0):
+    """Return MAC address corresponding to a given IP address"""
     tmp = map(ord, inet_aton(ip))
     if (tmp[0] & 0xf0) == 0xe0: # mcast @
         return "01:00:5e:%.2x:%.2x:%.2x" % (tmp[1]&0x7f,tmp[2],tmp[3])
@@ -397,6 +399,7 @@ conf.l3types.register(ETH_P_ARP, ARP)
 
 
 
+@conf.commands.register
 def arpcachepoison(target, victim, interval=60):
     """Poison target's cache with (your MAC,victim's IP) couple
 arpcachepoison(target, victim, [interval=60]) -> None
@@ -423,6 +426,7 @@ class ARPingResult(SndRcvList):
 
 
 
+@conf.commands.register
 def arping(net, timeout=2, cache=0, verbose=None, **kargs):
     """Send ARP who-has requests to determine which hosts are up
 arping(net, [cache=0,] [iface=conf.iface,] [verbose=conf.verb]) -> None
@@ -440,6 +444,7 @@ Set cache=True if you want arping to modify internal ARP-Cache"""
         ans.show()
     return ans,unans
 
+@conf.commands.register
 def is_promisc(ip, fake_bcast="ff:ff:00:00:00:00",**kargs):
     """Try to guess if target is in Promisc mode. The target is provided by its ip."""
 
@@ -447,6 +452,7 @@ def is_promisc(ip, fake_bcast="ff:ff:00:00:00:00",**kargs):
 
     return responses is not None
 
+@conf.commands.register
 def promiscping(net, timeout=2, fake_bcast="ff:ff:ff:ff:ff:fe", **kargs):
     """Send ARP who-has requests to determine which hosts are in promiscuous mode
     promiscping(net, iface=conf.iface)"""
@@ -492,7 +498,9 @@ class ARP_am(AnsweringMachine):
     def sniff(self):
         sniff(iface=self.iface, **self.optsniff)
 
+@conf.commands.register
 def etherleak(target, **kargs):
+    """Exploit Etherleak flaw"""
     return srpflood(Ether()/ARP(pdst=target), prn=lambda (s,r): Padding in r and hexstr(r[Padding].load),
                     filter="arp", **kargs)
 
diff --git a/scapy/modules/geoip.py b/scapy/modules/geoip.py
index b3ca97d4..e6359692 100644
--- a/scapy/modules/geoip.py
+++ b/scapy/modules/geoip.py
@@ -46,8 +46,9 @@ class CountryLocKnowledgeBase(KnowledgeBase):
             
         
 
-
+@conf.commands.register
 def locate_ip(ip):
+    """Get geographic coordinates from IP using geoip database"""
     ip=map(int,ip.split("."))
     ip = ip[3]+(ip[2]<<8L)+(ip[1]<<16L)+(ip[0]<<24L)
 
diff --git a/scapy/modules/nmap.py b/scapy/modules/nmap.py
index 211463e4..692e0730 100644
--- a/scapy/modules/nmap.py
+++ b/scapy/modules/nmap.py
@@ -110,7 +110,6 @@ def nmap_match_one_sig(seen, ref):
         return 1.0*c/len(seen.keys())
         
         
-
 def nmap_sig(target, oport=80, cport=81, ucport=1):
     res = {}
 
@@ -168,6 +167,7 @@ def nmap_search(sigs):
     return guess
     
     
+@conf.commands.register
 def nmap_fp(target, oport=80, cport=81):
     """nmap fingerprinting
 nmap_fp(target, [oport=80,] [cport=81,]) -> list of best guesses with accuracy
@@ -176,6 +176,7 @@ nmap_fp(target, [oport=80,] [cport=81,]) -> list of best guesses with accuracy
     return nmap_search(sigs)
         
 
+@conf.commands.register
 def nmap_sig2txt(sig):
     torder = ["TSeq","T1","T2","T3","T4","T5","T6","T7","PU"]
     korder = ["Class", "gcd", "SI", "IPID", "TS",
diff --git a/scapy/modules/p0f.py b/scapy/modules/p0f.py
index eb7aea04..28542edf 100644
--- a/scapy/modules/p0f.py
+++ b/scapy/modules/p0f.py
@@ -190,6 +190,7 @@ def p0f_correl(x,y):
     return d
 
 
+@conf.commands.register
 def p0f(pkt):
     """Passive OS fingerprinting: which OS emitted this TCP SYN ?
 p0f(packet) -> accuracy, [list of guesses]
@@ -234,7 +235,7 @@ def prnp0f(pkt):
         res += " (distance " + str(r[2]) + ")"
     print res
 
-
+@conf.commands.register
 def pkt2uptime(pkt, HZ=100):
     """Calculate the date the machine which emitted the packet booted using TCP timestamp
 pkt2uptime(pkt, [HZ=100])"""
diff --git a/scapy/modules/queso.py b/scapy/modules/queso.py
index bb3f8854..6284cd90 100644
--- a/scapy/modules/queso.py
+++ b/scapy/modules/queso.py
@@ -100,6 +100,7 @@ def queso_search(sig):
     return ret
         
 
+@conf.commands.register
 def queso(*args,**kargs):
     """Queso OS fingerprinting
 queso(target, dport=80, timeout=3)"""
diff --git a/scapy/packet.py b/scapy/packet.py
index 92fca3a5..cca42763 100644
--- a/scapy/packet.py
+++ b/scapy/packet.py
@@ -1059,7 +1059,9 @@ def bind_top_down(lower, upper, __fval=None, **fval):
     upper.overload_fields = upper.overload_fields.copy()
     upper.overload_fields[lower] = fval
     
+@conf.commands.register
 def bind_layers(lower, upper, __fval=None, **fval):
+    """Bind 2 layers on some specific fields' values"""
     if __fval is not None:
         fval.update(__fval)
     bind_top_down(lower, upper, **fval)
@@ -1088,13 +1090,16 @@ def split_top_down(lower, upper, __fval=None, **fval):
         upper.overload_fields = upper.overload_fields.copy()
         del(upper.overload_fields[lower])
 
+@conf.commands.register
 def split_layers(lower, upper, __fval=None, **fval):
+    """Split 2 layers previously bound"""
     if __fval is not None:
         fval.update(__fval)
     split_bottom_up(lower, upper, **fval)
     split_top_down(lower, upper, **fval)
 
 
+@conf.commands.register
 def ls(obj=None):
     """List  available layers, or infos on a given layer"""
     if obj is None:
@@ -1126,8 +1131,9 @@ def ls(obj=None):
 ## Fuzzing ##
 #############
 
-
+@conf.commands.register
 def fuzz(p, _inplace=0):
+    """Transform a layer into a fuzzy layer by replacing some default values by random objects"""
     if not _inplace:
         p = p.copy()
     q = p
diff --git a/scapy/sendrecv.py b/scapy/sendrecv.py
index 3e34010a..1d3d3a0e 100644
--- a/scapy/sendrecv.py
+++ b/scapy/sendrecv.py
@@ -227,12 +227,14 @@ def __gen_send(s, x, inter=0, loop=0, count=None, verbose=None, *args, **kargs):
     s.close()
     if verbose:
         print "\nSent %i packets." % n
-
+        
+@conf.commands.register
 def send(x, inter=0, loop=0, count=None, verbose=None, *args, **kargs):
     """Send packets at layer 3
 send(packets, [inter=0], [loop=0], [verbose=conf.verb]) -> None"""
     __gen_send(conf.L3socket(*args, **kargs), x, inter=inter, loop=loop, count=count,verbose=verbose)
 
+@conf.commands.register
 def sendp(x, inter=0, loop=0, iface=None, iface_hint=None, count=None, verbose=None, *args, **kargs):
     """Send packets at layer 2
 sendp(packets, [inter=0], [loop=0], [verbose=conf.verb]) -> None"""
@@ -240,6 +242,7 @@ sendp(packets, [inter=0], [loop=0], [verbose=conf.verb]) -> None"""
         iface = conf.route.route(iface_hint)[0]
     __gen_send(conf.L2socket(iface=iface, *args, **kargs), x, inter=inter, loop=loop, count=count, verbose=verbose)
 
+@conf.commands.register
 def sendpfast(x, pps=None, mbps=None, realtime=None, loop=0, iface=None):
     """Send packets at layer 2 using tcpreplay for performance
     pps:  packets per second
@@ -277,6 +280,7 @@ def sendpfast(x, pps=None, mbps=None, realtime=None, loop=0, iface=None):
 
         
     
+@conf.commands.register
 def sr(x,filter=None, iface=None, nofilter=0, *args,**kargs):
     """Send and receive packets at layer 3
 nofilter: put 1 to avoid use of bpf filters
@@ -294,6 +298,7 @@ iface:    listen answers only on the given interface"""
     s.close()
     return a,b
 
+@conf.commands.register
 def sr1(x,filter=None,iface=None, nofilter=0, *args,**kargs):
     """Send packets at layer 3 and return only the first answer
 nofilter: put 1 to avoid use of bpf filters
@@ -314,6 +319,7 @@ iface:    listen answers only on the given interface"""
     else:
         return None
 
+@conf.commands.register
 def srp(x,iface=None, iface_hint=None, filter=None, nofilter=0, type=ETH_P_ALL, *args,**kargs):
     """Send and receive packets at layer 2
 nofilter: put 1 to avoid use of bpf filters
@@ -333,6 +339,7 @@ iface:    work only on the given interface"""
     s.close()
     return a,b
 
+@conf.commands.register
 def srp1(*args,**kargs):
     """Send and receive packets at layer 2 and return only the first answer
 nofilter: put 1 to avoid use of bpf filters
@@ -402,11 +409,13 @@ def __sr_loop(srfunc, pkts, prn=lambda x:x[1].summary(), prnfail=lambda x:x.summ
         print ct.normal("\nSent %i packets, received %i packets. %3.1f%% hits." % (n,r,100.0*r/n))
     return plist.SndRcvList(ans),plist.PacketList(unans)
 
+@conf.commands.register
 def srloop(pkts, *args, **kargs):
     """Send a packet at layer 3 in loop and print the answer each time
 srloop(pkts, [prn], [inter], [count], ...) --> None"""
     return __sr_loop(sr, pkts, *args, **kargs)
 
+@conf.commands.register
 def srploop(pkts, *args, **kargs):
     """Send a packet at layer 2 in loop and print the answer each time
 srloop(pkts, [prn], [inter], [count], ...) --> None"""
@@ -466,6 +475,7 @@ def sndrcvflood(pks, pkt, prn=lambda (s,r):r.summary(), chainCC=0, store=1, uniq
             raise
     return received
 
+@conf.commands.register
 def srflood(x,filter=None, iface=None, nofilter=None, *args,**kargs):
     """Flood and receive packets at layer 3
 prn:      function applied to packets received. Ret val is printed if not None
@@ -479,6 +489,7 @@ iface:    listen answers only on the given interface"""
     s.close()
     return r
 
+@conf.commands.register
 def srpflood(x,filter=None, iface=None, iface_hint=None, nofilter=None, *args,**kargs):
     """Flood and receive packets at layer 2
 prn:      function applied to packets received. Ret val is printed if not None
@@ -497,6 +508,7 @@ iface:    listen answers only on the given interface"""
            
 
 
+@conf.commands.register
 def sniff(count=0, store=1, offline=None, prn = None, lfilter=None, L2socket=None, timeout=None, *arg, **karg):
     """Sniff packets
 sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2ListenSocket args) -> list of packets
diff --git a/scapy/utils.py b/scapy/utils.py
index bf3dab78..bb51a51b 100644
--- a/scapy/utils.py
+++ b/scapy/utils.py
@@ -46,6 +46,7 @@ def lhex(x):
     else:
         return x
 
+@conf.commands.register
 def hexdump(x):
     x=str(x)
     l = len(x)
@@ -63,6 +64,7 @@ def hexdump(x):
         print sane_color(x[i:i+16])
         i += 16
 
+@conf.commands.register
 def linehexdump(x, onlyasc=0, onlyhex=0):
     x = str(x)
     l = len(x)
@@ -86,7 +88,9 @@ def hexstr(x, onlyasc=0, onlyhex=0):
     return "  ".join(s)
 
 
+@conf.commands.register
 def hexdiff(x,y):
+    """Show differences between 2 binary strings"""
     x=str(x)[::-1]
     y=str(y)[::-1]
     SUBST=1
@@ -406,7 +410,9 @@ def save_object(fname, obj):
 def load_object(fname):
     return cPickle.load(gzip.open(fname,"rb"))
 
+@conf.commands.register
 def corrupt_bytes(s, p=0.01, n=None):
+    """Corrupt a given percentage or number of bytes from a string"""
     s = array.array("B",str(s))
     l = len(s)
     if n is None:
@@ -415,7 +421,9 @@ def corrupt_bytes(s, p=0.01, n=None):
         s[i] = random.randint(0,255)
     return s.tostring()
 
+@conf.commands.register
 def corrupt_bits(s, p=0.01, n=None):
+    """Flip a given percentage or number of bits from a string"""
     s = array.array("B",str(s))
     l = len(s)*8
     if n is None:
@@ -431,6 +439,7 @@ def corrupt_bits(s, p=0.01, n=None):
 ## pcap capture file stuff ##
 #############################
 
+@conf.commands.register
 def wrpcap(filename, pkt, *args, **kargs):
     """Write a list of packets to a pcap file
 gz: set to 1 to save a gzipped capture
@@ -438,6 +447,7 @@ linktype: force linktype value
 endianness: "<" or ">", force endianness"""
     PcapWriter(filename, *args, **kargs).write(pkt)
 
+@conf.commands.register
 def rdpcap(filename, count=-1):
     """Read a pcap file and return a packet list
 count: read only <count> packets"""
@@ -643,11 +653,14 @@ def import_hexcap():
         
 
 
+@conf.commands.register
 def wireshark(pktlist):
+    """Run wireshark on a list of packets"""
     f = os.tempnam("scapy")
     wrpcap(f, pktlist)
     os.spawnlp(os.P_NOWAIT, conf.prog.wireshark, conf.prog.wireshark, "-r", f)
 
+@conf.commands.register
 def hexedit(x):
     x = str(x)
     f = os.tempnam("scapy")
-- 
GitLab