13e4ead4b7b6d9ae5ac4b4cf4c1333a116f8a2d15Phil## This file is part of Scapy
23e4ead4b7b6d9ae5ac4b4cf4c1333a116f8a2d15Phil## See http://www.secdev.org/projects/scapy for more informations
33e4ead4b7b6d9ae5ac4b4cf4c1333a116f8a2d15Phil## Copyright (C) Philippe Biondi <phil@secdev.org>
43e4ead4b7b6d9ae5ac4b4cf4c1333a116f8a2d15Phil## This program is published under a GPLv2 license
53e4ead4b7b6d9ae5ac4b4cf4c1333a116f8a2d15Phil
60ce149b41a10223c75f33a135d0a7ddc6bd2e022Dirk Loss"""
70ce149b41a10223c75f33a135d0a7ddc6bd2e022Dirk LossLogging subsystem and basic exception class.
80ce149b41a10223c75f33a135d0a7ddc6bd2e022Dirk Loss"""
9bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil
10bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil#############################
11bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil##### Logging subsystem #####
12bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil#############################
13bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil
14bb2ddd8ef0416706e645595b6b5484ee4f409ad3Philclass Scapy_Exception(Exception):
15bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil    pass
16bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil
172a54fe68cadcb2b75c9c31244499c2b21f385eb4gpotterimport logging, traceback, time
18bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil
19bb2ddd8ef0416706e645595b6b5484ee4f409ad3Philclass ScapyFreqFilter(logging.Filter):
20bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil    def __init__(self):
21bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil        logging.Filter.__init__(self)
22bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil        self.warning_table = {}
232a54fe68cadcb2b75c9c31244499c2b21f385eb4gpotter    def filter(self, record):
246057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        from scapy.config import conf
25bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil        wt = conf.warning_threshold
26bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil        if wt > 0:
27bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil            stk = traceback.extract_stack()
28bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil            caller=None
29bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil            for f,l,n,c in stk:
30bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil                if n == 'warning':
31bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil                    break
32bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil                caller = l
33bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil            tm,nb = self.warning_table.get(caller, (0,0))
34bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil            ltm = time.time()
35bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil            if ltm-tm > wt:
36bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil                tm = ltm
37bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil                nb = 0
38bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil            else:
392a54fe68cadcb2b75c9c31244499c2b21f385eb4gpotter                if conf.warning_next_only_once:
402a54fe68cadcb2b75c9c31244499c2b21f385eb4gpotter                    conf.warning_next_only_once = False
412a54fe68cadcb2b75c9c31244499c2b21f385eb4gpotter                    return 0
42bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil                if nb < 2:
43bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil                    nb += 1
44bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil                    if nb == 2:
45bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil                        record.msg = "more "+record.msg
46bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil                else:
47bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil                    return 0
48bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil            self.warning_table[caller] = (tm,nb)
49bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil        return 1
50bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil
514d31afe7796aa20d0fdc28a5873882ff20059074Robin Jarrytry:
524d31afe7796aa20d0fdc28a5873882ff20059074Robin Jarry    from logging import NullHandler
534d31afe7796aa20d0fdc28a5873882ff20059074Robin Jarryexcept ImportError:
544d31afe7796aa20d0fdc28a5873882ff20059074Robin Jarry    # compat for python 2.6
554d31afe7796aa20d0fdc28a5873882ff20059074Robin Jarry    from logging import Handler
564d31afe7796aa20d0fdc28a5873882ff20059074Robin Jarry    class NullHandler(Handler):
574d31afe7796aa20d0fdc28a5873882ff20059074Robin Jarry        def emit(self, record):
584d31afe7796aa20d0fdc28a5873882ff20059074Robin Jarry            pass
59bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phillog_scapy = logging.getLogger("scapy")
604d31afe7796aa20d0fdc28a5873882ff20059074Robin Jarrylog_scapy.addHandler(NullHandler())
61bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phillog_runtime = logging.getLogger("scapy.runtime")          # logs at runtime
62bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phillog_runtime.addFilter(ScapyFreqFilter())
63bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phillog_interactive = logging.getLogger("scapy.interactive")  # logs in interactive functions
64ed95a6a3cea25583d339e564b7c93bdbcbbf9483Guillaume Valadonlog_loading = logging.getLogger("scapy.loading")          # logs when loading Scapy
65bb2ddd8ef0416706e645595b6b5484ee4f409ad3Phil
6690da76f56bc90a7165f586c0fa89352c6f7ea784gpotter
6774216229338d7c293371435cc4bb752b04af871aPierre LALETdef warning(x, *args, **kargs):
682a54fe68cadcb2b75c9c31244499c2b21f385eb4gpotter    """
692a54fe68cadcb2b75c9c31244499c2b21f385eb4gpotter    Prints a warning during runtime.
7036869f465fea712f09b3a9bf9bbd50dd0550f04ePhil
712a54fe68cadcb2b75c9c31244499c2b21f385eb4gpotter    onlyOnce - if True, the warning will never be printed again.
722a54fe68cadcb2b75c9c31244499c2b21f385eb4gpotter    """
7374216229338d7c293371435cc4bb752b04af871aPierre LALET    if kargs.pop("onlyOnce", False):
742a54fe68cadcb2b75c9c31244499c2b21f385eb4gpotter        from scapy.config import conf
752a54fe68cadcb2b75c9c31244499c2b21f385eb4gpotter        conf.warning_next_only_once = True
7674216229338d7c293371435cc4bb752b04af871aPierre LALET    log_runtime.warning(x, *args, **kargs)
77