Source code for linuxnet.iptables.targets.logtarget

# Copyright (c) 2021, 2022, 2023, 2024, 2025, Panagiotis Tsirigotis

# This file is part of linuxnet-iptables.
#
# linuxnet-iptables is free software: you can redistribute it and/or
# modify it under the terms of version 3 of the GNU Affero General Public
# License as published by the Free Software Foundation.
#
# linuxnet-iptables is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General
# Public License along with linuxnet-iptables. If not, see
# <https://www.gnu.org/licenses/>.

"""
This module provides the LogTarget class which provides access to
the iptables LOG target.
"""

from typing import List, Optional

from ..deps import get_logger
from ..exceptions import IptablesParsingError

from .target import Target, TargetParser

_logger = get_logger("linuxnet.iptables.targets.logtarget")


[docs]class LogTarget(Target): """This class provides access to the ``LOG`` target """ __OPT_MAP = { '--log-tcp-sequence' : 0x1, '--log-tcp-options' : 0x2, '--log-ip-options' : 0x4, '--log-uid' : 0x8, '--log-macdecode' : 0x20, } __ALL_FLAGS = sum(__OPT_MAP.values()) def __init__(self, # pylint: disable=too-many-arguments log_prefix: Optional[str] =None, log_level: Optional[str] =None, *, log_tcp_sequence=False, log_tcp_options=False, log_ip_options=False, log_uid=False, log_macdecode=False): """ :param log_prefix: prefix to include in every log message :param log_level: log level; see **syslog(3)** for possible values, e.g. ``info`` (note that the **LOG_** prefix is stripped); numbers in string form (e.g. "5") are also accepted :param log_tcp_sequence: optional boolean (see **iptables(8)** **LOG** target) :param log_tcp_options: optional boolean (see **iptables(8)** **LOG** target) :param log_ip_options: optional boolean (see **iptables(8)** **LOG** target) :param log_uid: optional boolean (see **iptables(8)** **LOG** target) :param log_macdecode: optional boolean (see **iptables(8)** **LOG** target) """ super().__init__('LOG', terminates=False) self.__log_prefix = log_prefix self.__log_level = log_level self.__log_flags = 0 if log_tcp_sequence: self.log_tcp_sequence() if log_tcp_options: self.log_tcp_options() if log_ip_options: self.log_ip_options() if log_uid: self.log_uid() if log_macdecode: self.log_macdecode() def _set_log_flags(self, flags: int) -> None: """Helper method used by the parsing code """ self.__log_flags = flags
[docs] def get_log_prefix(self) -> Optional[str]: """Returns the log prefix """ return self.__log_prefix
[docs] def get_log_level(self) -> Optional[str]: """Returns the log level """ return self.__log_level
[docs] def is_logging_tcp_sequence(self) -> bool: """Returns ``True`` if the ``--log-tcp-sequence`` option is set. """ return (self.__log_flags & self.__OPT_MAP['--log-tcp-sequence']) != 0
[docs] def log_tcp_sequence(self) -> Target: """Set the ``--log-tcp-sequence`` option. """ self.__log_flags |= self.__OPT_MAP['--log-tcp-sequence'] return self
[docs] def is_logging_tcp_options(self) -> bool: """Returns ``True`` if the ``--log-tcp-options`` option is set. """ return (self.__log_flags & self.__OPT_MAP['--log-tcp-options']) != 0
[docs] def log_tcp_options(self) -> Target: """Set the ``--log-tcp-options`` option. """ self.__log_flags |= self.__OPT_MAP['--log-tcp-options'] return self
[docs] def is_logging_ip_options(self) -> bool: """Returns ``True`` if the ``--log-ip-options`` option is set. """ return (self.__log_flags & self.__OPT_MAP['--log-ip-options']) != 0
[docs] def log_ip_options(self) -> Target: """Set the ``--log-ip-options`` option. """ self.__log_flags |= self.__OPT_MAP['--log-ip-options'] return self
[docs] def is_logging_uid(self) -> bool: """Returns ``True`` if the ``--log-uid`` option is set. """ return (self.__log_flags & self.__OPT_MAP['--log-uid']) != 0
[docs] def log_uid(self) -> Target: """Set the ``--log-uid`` option. """ self.__log_flags |= self.__OPT_MAP['--log-uid'] return self
[docs] def log_macdecode(self) -> Target: """Set the ``--log-macdecode`` option. """ self.__log_flags |= self.__OPT_MAP['--log-macdecode'] return self
[docs] def to_iptables_args(self) -> List[str]: """Returns a list of **iptables(8)** arguments """ retval = super().to_iptables_args() if self.__log_prefix: retval += ['--log-prefix', self.__log_prefix] if self.__log_level: retval += ['--log-level', self.__log_level] for option, flag in self.__OPT_MAP.items(): if self.__log_flags & flag: retval.append(option) return retval
@classmethod def parse(cls, parser: TargetParser) -> Target: """Parse the LOG target options :meta private: """ log_level = None log_prefix = None log_flags = 0 field_iter = parser.get_field_iter() for val in field_iter: if val == 'flags': flags = int(field_iter.next_value(val)) unknown_flags = flags & ~cls.__ALL_FLAGS if unknown_flags: raise IptablesParsingError( f'unknown LOG target flags: {unknown_flags:#x}') log_flags = flags elif val == 'level': log_level = field_iter.next_value(val) elif val == 'prefix': # Consume the rest of the fields val = ' '.join(field_iter) # Backquote used by iptables 1.4.7, double quote used # by iptables 1.8.4 if val[0] in ("`", '"'): val = val[1:-1] log_prefix = val else: raise IptablesParsingError(f'unknown target option: {val}') target = LogTarget(log_prefix, log_level) target._set_log_flags(log_flags) return target
TargetParser.register_target('LOG', LogTarget, 'LOG')