blob: 09c7d44c157a43117b450e26f77e324b641befae [file] [log] [blame]
Phil3e4ead42008-07-28 16:13:01 +02001## This file is part of Scapy
2## See http://www.secdev.org/projects/scapy for more informations
3## Copyright (C) Philippe Biondi <phil@secdev.org>
4## This program is published under a GPLv2 license
5
Dirk Loss0ce149b2010-06-16 22:47:55 +02006"""
7Answering machines.
8"""
9
Philbb2ddd82008-05-23 02:47:47 +020010########################
11## Answering machines ##
12########################
13
gpotter222a55b62017-06-27 18:31:14 +020014from __future__ import absolute_import
gpotter2b72a0b52017-06-27 23:43:42 +020015from __future__ import print_function
Robin Jarry60579062016-06-01 16:17:07 +020016from scapy.sendrecv import send,sendp,sniff
17from scapy.config import conf
18from scapy.error import log_interactive
gpotter222a55b62017-06-27 18:31:14 +020019import scapy.modules.six as six
Philbb2ddd82008-05-23 02:47:47 +020020
21class ReferenceAM(type):
22 def __new__(cls, name, bases, dct):
23 o = super(ReferenceAM, cls).__new__(cls, name, bases, dct)
24 if o.function_name:
25 globals()[o.function_name] = lambda o=o,*args,**kargs: o(*args,**kargs)()
26 return o
27
28
gpotter222a55b62017-06-27 18:31:14 +020029class AnsweringMachine(six.with_metaclass(ReferenceAM, object)):
Philbb2ddd82008-05-23 02:47:47 +020030 function_name = ""
31 filter = None
32 sniff_options = { "store":0 }
zer0@platinume27e4b62009-12-29 19:30:38 +010033 sniff_options_list = [ "store", "iface", "count", "promisc", "filter", "type", "prn", "stop_filter" ]
Philbb2ddd82008-05-23 02:47:47 +020034 send_options = { "verbose":0 }
35 send_options_list = ["iface", "inter", "loop", "verbose"]
36 send_function = staticmethod(send)
37
38
39 def __init__(self, **kargs):
40 self.mode = 0
41 if self.filter:
42 kargs.setdefault("filter",self.filter)
43 kargs.setdefault("prn", self.reply)
44 self.optam1 = {}
45 self.optam2 = {}
46 self.optam0 = {}
47 doptsend,doptsniff = self.parse_all_options(1, kargs)
48 self.defoptsend = self.send_options.copy()
49 self.defoptsend.update(doptsend)
50 self.defoptsniff = self.sniff_options.copy()
51 self.defoptsniff.update(doptsniff)
52 self.optsend,self.optsniff = [{},{}]
53
54 def __getattr__(self, attr):
55 for d in [self.optam2, self.optam1]:
56 if attr in d:
57 return d[attr]
gpotter2f8fe5252017-08-22 20:33:04 +020058 raise AttributeError(attr)
Philbb2ddd82008-05-23 02:47:47 +020059
60 def __setattr__(self, attr, val):
61 mode = self.__dict__.get("mode",0)
62 if mode == 0:
63 self.__dict__[attr] = val
64 else:
65 [self.optam1, self.optam2][mode-1][attr] = val
66
67 def parse_options(self):
68 pass
69
70 def parse_all_options(self, mode, kargs):
71 sniffopt = {}
72 sendopt = {}
Pierre LALETa65ddc72017-09-29 22:44:22 +020073 for k in list(kargs): # use list(): kargs is modified in the loop
Philbb2ddd82008-05-23 02:47:47 +020074 if k in self.sniff_options_list:
75 sniffopt[k] = kargs[k]
76 if k in self.send_options_list:
77 sendopt[k] = kargs[k]
78 if k in self.sniff_options_list+self.send_options_list:
Pierre LALET241e2c42016-04-27 16:41:43 +020079 del kargs[k]
Philbb2ddd82008-05-23 02:47:47 +020080 if mode != 2 or kargs:
81 if mode == 1:
82 self.optam0 = kargs
83 elif mode == 2 and kargs:
84 k = self.optam0.copy()
85 k.update(kargs)
86 self.parse_options(**k)
87 kargs = k
88 omode = self.__dict__.get("mode",0)
89 self.__dict__["mode"] = mode
90 self.parse_options(**kargs)
91 self.__dict__["mode"] = omode
92 return sendopt,sniffopt
93
94 def is_request(self, req):
95 return 1
96
97 def make_reply(self, req):
98 return req
99
100 def send_reply(self, reply):
101 self.send_function(reply, **self.optsend)
102
103 def print_reply(self, req, reply):
gpotter2b72a0b52017-06-27 23:43:42 +0200104 print("%s ==> %s" % (req.summary(),reply.summary()))
Philbb2ddd82008-05-23 02:47:47 +0200105
106 def reply(self, pkt):
107 if not self.is_request(pkt):
108 return
109 reply = self.make_reply(pkt)
110 self.send_reply(reply)
111 if conf.verb >= 0:
112 self.print_reply(pkt, reply)
113
114 def run(self, *args, **kargs):
Guillaume Valadoned95a6a2016-11-15 12:40:56 +0100115 log_interactive.warning("run() method deprecated. The instance is now callable")
Philbb2ddd82008-05-23 02:47:47 +0200116 self(*args,**kargs)
117
118 def __call__(self, *args, **kargs):
119 optsend,optsniff = self.parse_all_options(2,kargs)
120 self.optsend=self.defoptsend.copy()
121 self.optsend.update(optsend)
122 self.optsniff=self.defoptsniff.copy()
123 self.optsniff.update(optsniff)
124
125 try:
126 self.sniff()
127 except KeyboardInterrupt:
gpotter2b72a0b52017-06-27 23:43:42 +0200128 print("Interrupted by user")
Philbb2ddd82008-05-23 02:47:47 +0200129
130 def sniff(self):
131 sniff(**self.optsniff)
132