Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > dca483b59ba61f3fa092de932ddd570e > files > 799

nuface-2.0.14-2mdv2009.1.i586.rpm

# Copyright(C) 2005 INL
# Written by Jean Gillaux <jean@inl.fr>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
#  This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.

from os import linesep
from IPy import IP
from nupyf.ipt_func import gen_rule, gen_rule_list, make_target, _make_syn
from nupyf.ipt_nat import SnatIpt, DnatIpt, PnatIpt
import re

USE_PROXY = 1
OVERRIDE_PROXY = 2

TRANSPARENT_PROXY_PORT = 3128

def formatProtocol(protocol):
    args = []
    proto = protocol.get('proto')
    if proto:
        args.extend(['-p',proto])

    icmptype = protocol.get('icmptype')
    if icmptype:
        args.extend(['--icmp-type',icmptype])

    dport = protocol.get('dport')
    if dport:
        args.extend(['--dport',dport])

    sport = protocol.get('sport')
    if sport:
        args.extend(['--sport',sport])
    return args

def formatIP(rule):
    args = []
    if rule.src():
        ip = IP(rule.elt_src().get('numnet'))
        if ip.prefixlen():
            args.append('-s %s' % ip)
    if rule.dest():
        ip = IP(rule.elt_dest().get('numnet'))
        if ip.prefixlen():
            args.append('-d %s' % ip)
    return args

def formatInterface(rule):
    args = []
    if rule.input_iface:
        args.append('-i %s' % rule.input_iface.name())
    return args

def formatRule(rule, table, target, *more_args):
    args = ['-A %s' % table]
    args.extend(formatIP(rule))
    args.extend(formatProtocol(rule.proto()))
    args.extend(formatInterface(rule))
    args.append('-j %s' % target)
    args.extend(more_args)
    args.append(linesep)
    return gen_rule(*args)

def logMessage(command, text):
    if command == '--ulog-prefix':
        max_length = 31
    else:
        max_length = 28

    if max_length < len(text):
        full_text = text
        text = text[:max_length]
        print "WARNING: Truncate log prefix %r to %s characters: %r" % (
            full_text, max_length, text)

    if command == '--log-prefix':
        text += ' '

    text = text.replace('"', '\\"')
    return '%s "%s"' % (command, text)

class FWipt:
    """Used to generate iptables rules from a firewall object that contains rules
    """
    def __init__(self,thefw,logtype='log', queue=None):
        self.__fw = thefw
        self.__logtype = 'LOG'
        self.__logprefix = '--log-prefix'
        self.queue_type = 'QUEUE'
        self.queue_num = None
        if thefw.queue:
            queue = thefw.queue
        if queue:
            self.queue_type = 'NFQUEUE'
            self.queue_num = queue
        if logtype == 'ulog':
            self.__logtype = 'ULOG'
            self.__logprefix = '--ulog-prefix'

    def dumb_rules(self, rules, chain_obj):
        chain = chain_obj['name']
        res = ['#ERROR_DISPATCH %s' % chain + linesep]
        sacl = ''
        for r in rules:
            stmp = r.aclname
            if(stmp != sacl):
                sacl = stmp
                sc = '#%s (acl %s)' % (sacl, r.aclid) + linesep
                res.append(sc)
            rule_print = RulePrintIptSimple(r, fw=self.__fw, chain=chain_obj,
                add=_make_syn(make_target(r.decision), {'proto':r.proto().get('proto')}),
                target=make_target(r.decision),
                ulog_prefix=r.ulog_prefix,
                logtype=self.__logtype)
            res.append('#%s' % rule_print + linesep)
        return res

    def create_ipt_chains(self):
        """Generate rules to create firewall chains: DMZ-LAN
        """
        l = self.__fw.chains(all=1,inout=1)
        s = ''
        acc=[]
        for n in l:
            st = ':%s -' % n['name'] + linesep

            # Hack for multiple INTERNET (external zones)
            if not st in acc:
                s+=st
            acc.append(st)
        return s

    def __gen_global_accept(self, *where):
        state = 'RELATED'
        res = ''
        state = 'ESTABLISHED,%s' % state
        for ch in where:
            res = res + gen_rule('-A %s -m state --state %s -j ACCEPT' % (ch,state)) + linesep
        return res

    def __gen_default_log_drop(self, *where):
        res = ''
        for ch in where:
            message = logMessage(self.__logprefix, "DFT_%s_DROP" % ch)
            res = res + gen_rule('-A %s -j %s' % (ch, self.__logtype), message)+ linesep
            res = res + gen_rule('-A %s -j DROP' % (ch))+linesep
        return res

    def __gen_default_invalid_drop(self, *where):
        res = ''
        for ch in where:
            res = res + gen_rule('-A %s -m state --state INVALID -j DROP' % (ch)) + linesep
        return res

    def gen_loopback_default_rules(self):
        s = ''
        s += gen_rule('-A INPUT -i lo -j ACCEPT%s' % linesep)
        s += gen_rule('-A OUTPUT -o lo -j ACCEPT%s' % linesep)
        return s

    def connect_chains(self):
        """Generate rules that connect firewall streams into chains
           => dispatch rules
        """
        l = self.__fw.chains(all=1,inout=1)
        s = ''
        sinternet = sinout_internet = ''
        sinput = ''
        soutput = ''
        lwhere = ['FORWARD']
        lwhere.append('INPUT')
        lwhere.append('OUTPUT')
        estrel = self.__gen_global_accept(*lwhere)
        h_vpn = {}
        h_forward = {}
        h_input = {}
        l_output = []
        h_internet = {}
        h_ininternet = {}
        l_outinternet = []
        for n in l:
            has_vpn = False
            has_internet = False
            # INPUT/OUTPUT INTEGRATION: change chain name here -> OK
            where = 'FORWARD'
            input = output = False
            if self.__fw.chain_input(n):
                where = 'INPUT'
                input = True
            if self.__fw.chain_output(n):
                where = 'OUTPUT'
                output = True
            t=['-A %s' % (where)]
            if n['type'] != "output" and not self.__fw.is_default_net(n['net_src']):
                t.append('-s %s' % n['net_src'].ip())
                sort_net_src = n['net_src'].addr()
            else:
                sort_net_src = IP('0.0.0.0/0')

            # TODO: why also output and not just forward ???
            if n['type'] != "input" and not self.__fw.is_default_net(n['net_dst']):
                t.append('-d %s' % n['net_dst'].ip())
                sort_net_dst = n['net_dst'].addr()
            else:
                sort_net_dst = IP('0.0.0.0/0')

            # vpn rules
            if (not input and not output) and (n['net_src'].is_vpn() or n['net_dst'].is_vpn()):
                has_vpn = True
                t.extend(['-m policy --pol ipsec --mode tunnel'])

                #remote vpn network is source of the connexion

                # net_dst:
                conn = n['net_dst'].get_conn(self.__fw.id())
                iface = self.__fw.get_iface_by_id(int(conn['iface']))
                if conn['addr']:
                    ndst_iface_addr = iface.get_addr_by_id(conn['addr'])
                else:
                    ndst_iface_addr = iface.addr()

                # net_src:
                conn = n['net_src'].get_conn(self.__fw.id())
                iface = self.__fw.get_iface_by_id(int(conn['iface']))
                if conn['addr']:
                    nsrc_iface_addr = iface.get_addr_by_id(conn['addr'])
                else:
                    nsrc_iface_addr = iface.addr()

                tunnelsrc = n['net_src'].remote()
                tunneldst = nsrc_iface_addr

                #remote vpn network is destination of the connexion
                dir = 'in'
                if n['net_dst'].is_vpn():
                    tunnelsrc = ndst_iface_addr
                    tunneldst = n['net_dst'].remote()
                    dir = 'out'
                t.extend(['--dir',dir, '--tunnel-src', tunnelsrc, '--tunnel-dst', tunneldst])
            if (n.get('net_src') is not None \
            and self.__fw.is_default_net(n['net_src'])) or (n.get('net_dst') is not None \
            and self.__fw.is_default_net(n['net_dst'])):
                has_internet = True

            #for INPUT/OUTPUT, don't put -i -o
            if not output:
                t.extend(['-i',n['if_src'].name().split(':')[0]])
            if not input:
                t.extend(['-o',n['if_dst'].name().split(':')[0]])
            t.extend(['-j',n['name']])

            st = gen_rule_list(t)+linesep
            if n.get('net_src') is not None \
            and n.get('net_dst') is not None \
            and n['net_src'].is_vpn() \
            and n['net_dst'].is_vpn():
                st = ''
            if has_vpn:
                # We need vpn related flux to be first
                self.insert_hash_net_chains(h_vpn, sort_net_src, sort_net_dst, st)
            else:
                if has_internet and has_vpn is False:
                    if input:
                        sinout_internet += st
                        h_ininternet[n['net_src'].addr()] = st
                    elif output:
                        sinout_internet += st
                        l_outinternet.append(st)
                    else:
                        sinternet+=st
                        self.insert_hash_net_chains(h_internet, sort_net_src, sort_net_dst, st)
                else:
                    # Put rules in order: forward, input, output
                    if input:
                        sinput += st
                        h_input[n['net_src'].addr()] = st
                    elif output:
                        soutput += st
                        l_output.append(st)
                    else:
                        s+=st
                        self.insert_hash_net_chains(h_forward, sort_net_src, sort_net_dst, st)

        # Rules for INVALID state
        invalid = self.__gen_default_invalid_drop(*lwhere)+linesep

        # LOG and DROP end rules
        default_log_drop = self.__gen_default_log_drop(*lwhere)
        sloopback = self.gen_loopback_default_rules()

        # Get sorted rules for FORWARD, INPUT and OUTPUT
        s_sorted_vpn = self.get_ipt_string(h_vpn)
        s_sorted_forward = self.get_ipt_string(h_forward)
        input_keys = h_input.keys()
        input_keys.sort()
        s_sorted_input = ""
        for input_key in input_keys:
            s_sorted_input += h_input[input_key]
        s_sorted_output = ''.join(l_output)
        s_sorted_internet = self.get_ipt_string(h_internet)
        ininternet_keys = h_ininternet.keys()
        ininternet_keys.sort()
        s_sorted_ininternet = ""
        for ininternet_key in ininternet_keys:
            s_sorted_ininternet += h_ininternet[ininternet_key]
        s_sorted_outinternet = ''.join(l_outinternet)
	rules = [ estrel, invalid, s_sorted_vpn, s_sorted_forward, s_sorted_input, s_sorted_output, s_sorted_ininternet, \
		  s_sorted_outinternet, s_sorted_internet + linesep, sloopback + linesep, default_log_drop + linesep ]
        return rules

    def insert_hash_net_chains(self, hash, src, dst, mystring):
        """hash indexed by src network, dst network"""
        key = (src, dst)
        if key in hash:
            raise KeyError("Duplicate key! %s" % key)
        hash[key] = mystring

    def networkKey(self, src_dst):
        src, dst = src_dst
        return (-src.prefixlen() - dst.prefixlen(), src, dst)

    def get_ipt_string(self, hash):
        """get iptables commandes stored in hash
           commands are sorted by src_addr, dst_addr
        """
        keys = hash.keys()
        keys.sort(key=self.networkKey)
        ret = ''
        for key in keys:
            line = hash[key]
            ret += line
        return ret


    def gen_rules_chain(self,chain_obj,rescue=0):
        """Generate rules in one bichain"""
        chain = chain_obj['name']
        l=[]
        l2=[] #rules syn, rescue: put after new/rst/fin (l list)
        l_eld = []
        rl = self.__fw.hrules()[chain]
        lch = rl.ordered_rules()
        if rl.is_bad():
            return self.dumb_rules(lch,chain_obj)
        sacl = ''
        stmp = ''
        comment = 0
        has_rules = False
        queue_num = None
        # Set queue_num if queue type is NFQUEUE
        if self.queue_type == 'NFQUEUE' and self.queue_num:
            queue_num = self.queue_num
        previous_line = None
        for (rule_order, r) in lch:
            if r.acl.transparent_proxy == USE_PROXY:
                continue
            stmp = r.aclname; has_rules = True
            comment_rule = ''
            if(stmp != sacl):
                sacl = stmp
                sc = '%s#%s (acl %s)%s' % (linesep, sacl, r.aclid, linesep)
                comment = 1
            else:
                comment = 0
            iface = ''
            if r.dest() and r.elt_dest().get('is_local'):
                iface = self.__fw.get_local_ip_connected_to(r.netsrc.addr())['iface']

            if r.use_nufw():
                proto = r.proto().get('proto')
                if proto and proto not in ('tcp', 'udp'):
                    raise ValueError('ACL %s: the protocol "%s" cannot be authenticated' %(r.aclid, proto))
                if rescue == 0:
                    if comment == 1:
                        l.append(sc)
                    if r.is_auto == 1:
                        l.append('#rules is auto' + linesep)
                    syn_str = "--syn"
                    if r.proto().get('proto') != 'tcp':
                        syn_str = ""
                    ript = RulePrintIptSimple(r, fw=self.__fw, chain=chain_obj,
                        target=self.queue_type, iface=iface,
                        add='-m state --state NEW %s' % (syn_str),
                        ulog_prefix=r.ulog_prefix,
                        logtype=self.__logtype)
                    if queue_num:
                        ript.set_queue_num(queue_num)
                    ssyn = str(ript)+linesep
                    if comment == 1:
                        l2.append(sc)
                    l7connmark = r.proto().get('l7connmark')
                    if l7connmark and not r.elt_dest().get('is_local'):
                        ript.target = 'CONNMARK'
                        ript.connmark = l7connmark
                        l2.append(str(ript)+linesep)
                    line = comment_rule+ssyn
                    without_comment = line.split('#', 1)[0].rstrip()
                    if without_comment != previous_line:
                        l2.append(line)
                        previous_line = without_comment
                else:
                    rescue = RulePrintIptSimple(r, fw=self.__fw, chain=chain_obj, iface=iface,
                        add=_make_syn(make_target(r.decision), {'proto': r.proto().get('proto')}),
                        target=make_target(r.decision),
                        ulog_prefix=r.ulog_prefix,
                        logtype=self.__logtype)
                    srescue = str(rescue)+linesep
                    if comment == 1:
                        l2.append(sc)
                    if r.is_auto == 1: l2.append('#rules is auto' + linesep)
                    l7connmark = r.proto().get('l7connmark')
                    if l7connmark and not r.elt_dest().get('is_local'):
                        rescue.target = 'CONNMARK'
                        rescue.connmark = l7connmark
                        l2.append(str(rescue)+linesep)
                    l2.append(srescue)
            else:
                # Generate normal iptables cmds: target depends on _decision_ attribut
                rstd = RulePrintIptSimple(r, fw=self.__fw, chain=chain_obj, iface=iface,
                    add=_make_syn(make_target(r.decision), {'proto': r.proto().get('proto')}),
                    target=make_target(r.decision),
                    ulog_prefix=r.ulog_prefix,
                    logtype=self.__logtype)
                std = str(rstd)
                if comment == 1:
                    l2.append(sc)
                l7connmark = r.proto().get('l7connmark')
                if l7connmark and not r.elt_dest().get('is_local'):
                   rstd.target = 'CONNMARK'
                   rstd.connmark = l7connmark
                   l2.append(str(rstd)+linesep)
                l2.append(std+linesep)
        relaccept = ''

        prefix = ''
        if self.__logtype == 'ULOG':
                if self.__fw.chain_input(chain_obj):
                        prefix = "I"
                elif self.__fw.chain_output(chain_obj):
                        prefix = 'O'
                else:
                        prefix = 'F'
                prefix += '0D:'

        message = logMessage(self.__logprefix, "%s%s DROP" % (prefix, chain))
        log = gen_rule('-A',chain,'-j',self.__logtype, message)+linesep
        drop = gen_rule('-A',chain,'-j DROP')

        if has_rules:
            l.append(2*linesep)
            l.extend(l2)
        l_eld.extend([relaccept,log,drop])
        return (l,l_eld)

    def gen_rules(self,rescue=0):
        """Generate rules for all bichains"""
        sep = linesep*2
        forward=[]
        forward_end = []
        linput = []
        linput_eld = []
        loutput = []
        loutput_eld = [] # End Log Drop

        # We make INPUT,OUTPUT and FORWARD rules in one step
        seen_chains = set()
        for chain in self.__fw.chains(all=1, inout=1):
            # Don't generate log/drop rules twice
            # for a chain that exist with iface addr and broadcast
            if chain['name'] in seen_chains:
                continue
            seen_chains.add(chain['name'])

            do_input = False
            do_output = False
            (rule, rule_end) = self.gen_rules_chain(chain,rescue=rescue)

            if self.__fw.chain_input(chain):
                if rule:
                    linput.extend(rule)
                    linput.append(sep)

                linput_eld.extend(rule_end)
                linput_eld.append(sep)
                do_input = True

            if self.__fw.chain_output(chain):
                if rule:
                    loutput.extend(rule)
                    loutput.append(sep)
                loutput_eld.extend(rule_end); loutput_eld.append(sep)
                do_output = True

            if not do_input and not do_output:
                if rule:
                    forward.extend(rule)
                    forward.append(sep)
                forward_end.extend(rule_end)
                forward_end.append(sep)

        linput.extend(linput_eld)
        loutput.extend(loutput_eld)
        forward.extend(forward_end)
        return (linput, loutput, forward)


    def gen_vpn_rules(self):
        l = []
        for iface in self.__fw.ifaces():
            for n in iface.allnets():
                if n.is_vpn():
                    l.append('#%s%s' % (n.name(),linesep))
                    text = gen_rule('-A PREROUTING', '-t mangle', '-i',iface.name(),
                        '-p 50','-s', n.remote(), '-j MARK --set-mark', n.mark())
                    l.append(text+linesep)
                    text = gen_rule('-A PREROUTING', '-t mangle', '-d %s' % n.addr(),
                        '-j MARK --set-mark', n.mark())
                    l.append(text+linesep)
        return l

    def transparent_proxy_rules(self, only_proxy):
        rules = []
        text_rules = set()
        allrules = self.__fw.allrules()
        allrules.sort(key=lambda rule: (rule.acl.id, rule.cpt))
        previous_acl = None
        for rule in allrules:
            acl = rule.acl
            proxy = acl.transparent_proxy
            if proxy != only_proxy:
                continue
            if proxy == OVERRIDE_PROXY:
                target = 'ACCEPT'
            else:
                target = self.queue_type
            if acl != previous_acl:
                rules.append('# %s (ACL #%s)' % (acl.name(), acl.id) + linesep)
                previous_acl = acl
            line = formatRule(rule, 'PREROUTING', target)
            if line in text_rules:
                continue
            text_rules.add(line)
            rules.append(line)
        return rules

    def gen_nat_rules(self):
        """Generate SNAT, DNAT and PNAT iptables rules
        """
        l = []
        snat,dnat,pnat = self.__fw.get_nat_rules()
        l.append('# SNAT%s' % linesep)
        def cmp_id(r1, r2):
            return cmp(r1.id, r2.id)
        snat.sort(cmp_id)
        dnat.sort(cmp_id)
        pnat.sort(cmp_id)
        for r in snat:
            l.append('# rule %s %s%s' % (r.id, r._name, linesep))
            l.append(str(SnatIpt(r))+linesep)
        l.append('# DNAT%s' % linesep)
        for r in dnat:
            l.append('# rule %s %s%s' % (r.id, r._name, linesep))
            l.append(str(DnatIpt(r))+linesep)
        l.append('# PNAT%s' % linesep)
        for r in pnat:
            l.append('# rule %s %s%s' % (r.id, r._name, linesep))
            l.append(str(PnatIpt(r))+linesep)

        # Transparent proxy rule
        for rule in self.__fw.allrules():
            if rule.acl.transparent_proxy != USE_PROXY:
                continue
            args = (
                '-A PREROUTING',
                '-p tcp',
                '-m mark', '!', '--mark 0',
                '-j REDIRECT',
                '--to-ports %s' % TRANSPARENT_PROXY_PORT,
                linesep,
            )
            l.append(gen_rule(*args))
            break

        return l

    def mangle_rules(self):
        """Create mangle rules for firewall"""
        # List of rules
        lrules = []
        """iptables -A PREROUTING -t mangle -j CONNMARK --restore-mark
> iptables -A POSTROUTING -t mangle -m mark ! --mark 0 -j CONNMARK
> --save-mark
>
>
        """
        if self.__fw.queue is not None:
            lrules.append(gen_rule('-A PREROUTING','-j CONNMARK --restore-mark',linesep))
            lrules.append(gen_rule('-A POSTROUTING', '-m mark', '! --mark 0', '-j CONNMARK --save-mark --mask 0x0000ffff', linesep))

        lrules.extend(self.transparent_proxy_rules(OVERRIDE_PROXY))
        lrules.extend(self.transparent_proxy_rules(USE_PROXY))

        return lrules

class RulePrint:
    def __init__(self,r,fw=''):
        self.rule = r
        self.fw = fw
        if  self.rule.src():
            self.ef = self.rule.elt_src()
        else:
            self.ef = None
        if self.rule.dest():
            self.et = self.rule.elt_dest()
        else:
            self.et = None
        self.do_vpn = True

    def __str__(self):
        pass

class RulePrintIptSimple(RulePrint):
    """produces a iptables command form an acl rule
    """
    #TODO: take chain and target in argument
    def __init__(self, r, fw='', chain=None, target='DROP',
    add='', insert='', iface='', connmark='',
    ulog_prefix='', logtype='LOG'):
        RulePrint.__init__(self, r, fw)
        self.target = target
        self.chain_obj = chain
        self.chain = chain['name']
        self.add = add
        self.insert = '-A'
        self.queue_num = None
        if insert != '':
            self.insert = insert
        self.netsrc = self.rule.netsrc
        self.netdst = self.rule.netdst
        self.iface = iface
        self.connmark = connmark
        self.logtype = logtype

        # Create log prefix
        if ulog_prefix:
            log_prefix = str(ulog_prefix).strip()
        else:
            log_prefix = str(self.chain)
        if self.fw.chain_input(self.chain_obj):
            direction = 'I'
        elif self.fw.chain_output(self.chain_obj):
            direction = 'O'
        else:
            direction = 'F'
        self.ulog_prefix = "%s%s%s:%s" % (direction, self.rule.aclid, self.target[0], log_prefix)

    def _net_is_inclued_in(self,inner,net):
        """check if inner is inclued in net
        """
        if net is None: return False
        if inner.find('/')==-1: return False
        if net.zone()=='external': return False
        if net.zone()=='vpn': return False
        ntest = IP(inner)
        if ntest == net.addr(): return False
        conn = net.get_conn(self.fw.id())
        if ntest != IP('0.0.0.0/0') and "dftgateway" in conn:
            return True
        if ntest in net.addr():
            return True
        return False

    def set_queue_num(self, queue_num):
        self.queue_num = queue_num

    def __str__(self):
        if self.rule.src():
            ef = self.rule.src().elts[0]
        else:
            ef = None
        if self.rule.dest():
            et = self.rule.dest().elts[0]
        else:
            et = None
        pr = self.rule.proto()
        t = [self.insert, self.chain]

        t.extend(formatProtocol(pr))

        mark = ''
        if et and et.get('mark'):
            mark = et.get('mark')
        if ef and ef.get('mark'):
            mark = ef.get('mark')


        if self.iface:
            t.extend(['-i', self.iface.name()])

        #do we need to print the src/dst ip or dst/src net?
        sip = ''
        dip = ''

        chain = self.chain.split("-", 1)
        same_iface = (chain[0] == chain[1])
        local_rule = "IF" in (chain[0], chain[1])

        print_sip = same_iface or local_rule
        print_dip = True
        if ef and ef.get('numnet'):
            sip = ef.get('numnet')
        if et and et.get('numnet'):
            dip = et.get('numnet')
        if sip and sip.find('/')==-1:
            print_sip = True
        if dip and dip.find('/')==-1:
            print_dip = True
        if sip.find('/')!=-1:
            if IP(sip) != self.netsrc.addr():
                if self._net_is_inclued_in(sip,self.netsrc):
                    print_sip = True
            else:
                print_sip = False
        if dip.find('/')!=-1:
            if IP(dip) != self.netdst.addr():
                if self._net_is_inclued_in(dip,self.netdst):
                    print_dip = True
            else:
                print_dip = False

        if mark and self.do_vpn:
            t.extend(['-m mark','--mark',mark])
        if print_sip and sip:
            t.extend(['-s',sip])
        if print_dip and dip \
        and not(dip.endswith("/0") or dip.endswith("/0.0.0.0")):
            t.extend(['-d',dip])

        t.extend([self.add,'-j',self.target])
        if self.target == 'ULOG' and self.ulog_prefix:
            t.append(logMessage('--ulog-prefix', self.ulog_prefix))
        if self.target == 'LOG' and self.ulog_prefix:
            t.append(logMessage('--log-prefix', self.ulog_prefix))
        if self.target == 'CONNMARK':
            t.extend(['--set-mark', '%s' % (self.connmark)])

        if self.target == 'NFQUEUE' and self.queue_num:
            # Set queue num if NFQUEUE is used
            t.append('--queue-num %s' % self.queue_num)

        t.append(' # %s' % self.rule.aclid)
        t.append(str(self.rule.cpt))
        t = gen_rule_list(t)
        if (not self.rule.use_nufw()) and self.rule.log != "no":
            t = self.createLogRule(t, self.rule.log) + linesep + t
        return t

    def createLogRule(self, text, log_limit):
        iptables = '-j %s ' % self.logtype
        if self.logtype == 'ULOG':
            iptables += logMessage('--ulog-prefix', self.ulog_prefix)
        else:
            iptables += logMessage('--log-prefix', self.ulog_prefix)
        if log_limit != "unlimited":
            iptables += "-m limit --limit %s " % log_limit

        text = re.sub(' --queue-num [0-9]+', '', text)
        text = re.sub(' --set-mark [^ ]+', '', text)
        text = text.replace('-j %s ' % self.target, iptables)
        text += ' (log)'
        return text