Skip to content

Commit

Permalink
nftables: Add more operations and raise errors reported by kernel
Browse files Browse the repository at this point in the history
This commit adds more nftables operations and uses `nlm_request_batch`
to raise errors that are reported by the kernel. With this commit,
errors, e.g. caused by invalid rule expressions or missing NLAs, will no
longer go unnoticed.
  • Loading branch information
blechschmidt committed Apr 23, 2022
1 parent 39741a4 commit 729de2d
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 13 deletions.
37 changes: 33 additions & 4 deletions pyroute2.core/pr2modules/netlink/nfnetlink/nftsocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"""

import threading
from pr2modules.netlink import NLM_F_REQUEST
from pr2modules.netlink import NLM_F_REQUEST, NLM_F_ACK, NLM_F_CREATE, NLM_F_APPEND, NLM_F_EXCL, NLM_F_REPLACE
from pr2modules.netlink import NLM_F_DUMP
from pr2modules.netlink import NETLINK_NETFILTER
from pr2modules.netlink import nla
Expand Down Expand Up @@ -1096,7 +1096,17 @@ def request_put(self, msg, msg_type, msg_flags=NLM_F_REQUEST):
if one_shot:
self.commit()

def _command(self, msg_class, commands, cmd, kwarg, flags=NLM_F_REQUEST):
def _command(self, msg_class, commands, cmd, kwarg):
flags = kwarg.pop('flags', NLM_F_ACK)
cmd_name = cmd
cmd_flags = {
'add': NLM_F_CREATE | NLM_F_APPEND,
'create': NLM_F_CREATE | NLM_F_APPEND | NLM_F_EXCL,
'insert': NLM_F_CREATE,
'replace': NLM_F_REPLACE
}
flags |= cmd_flags.get(cmd, 0)
flags |= NLM_F_REQUEST
cmd = commands[cmd]
msg = msg_class()
msg['attrs'] = []
Expand All @@ -1115,5 +1125,24 @@ def _command(self, msg_class, commands, cmd, kwarg, flags=NLM_F_REQUEST):
for key, value in kwarg.items():
nla = msg_class.name2nla(key)
msg['attrs'].append([nla, value])
#
return self.request_put(msg, msg_type=cmd, msg_flags=flags)
msg['header']['type'] = (NFNL_SUBSYS_NFTABLES << 8) | cmd
msg['header']['flags'] = flags | NLM_F_REQUEST
msg['nfgen_family'] = self._nfgen_family

if cmd_name != 'get':
trans_start = nfgen_msg()
trans_start['res_id'] = NFNL_SUBSYS_NFTABLES
trans_start['header']['type'] = 0x10
trans_start['header']['flags'] = NLM_F_REQUEST

trans_end = nfgen_msg()
trans_end['res_id'] = NFNL_SUBSYS_NFTABLES
trans_end['header']['type'] = 0x11
trans_end['header']['flags'] = NLM_F_REQUEST

messages = [trans_start, msg, trans_end]
self.nlm_request_batch(messages, noraise=(flags & NLM_F_ACK) == 0)
# Only throw an error when the request fails. For now,
# do not return anything.
else:
return self.request_get(msg, msg['header']['type'], flags)[0]
31 changes: 22 additions & 9 deletions pyroute2.nftables/pr2modules/nftables/main.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'''
'''
from pr2modules.netlink import NLM_F_REQUEST, NLM_F_ACK, NLM_F_CREATE, NLM_F_APPEND, NLM_F_REPLACE, NLM_F_EXCL
from pr2modules.netlink.nfnetlink import nfgen_msg
from pr2modules.netlink.nfnetlink.nftsocket import (
NFTSocket,
Expand Down Expand Up @@ -49,10 +50,12 @@ def table(self, cmd, **kwarg):
nft.table('add', name='test0')
'''
commands = {'add': NFT_MSG_NEWTABLE, 'del': NFT_MSG_DELTABLE}
# fix default kwargs
if 'flags' not in kwarg:
kwarg['flags'] = 0
commands = {
'add': NFT_MSG_NEWTABLE,
'create': NFT_MSG_NEWTABLE,
'del': NFT_MSG_DELTABLE,
'get': NFT_MSG_GETTABLE
}
return self._command(nft_table_msg, commands, cmd, kwarg)

def chain(self, cmd, **kwarg):
Expand All @@ -69,7 +72,12 @@ def chain(self, cmd, **kwarg):
type='filter',
policy=0)
'''
commands = {'add': NFT_MSG_NEWCHAIN, 'del': NFT_MSG_DELCHAIN}
commands = {
'add': NFT_MSG_NEWCHAIN,
'create': NFT_MSG_NEWCHAIN,
'del': NFT_MSG_DELCHAIN,
'get': NFT_MSG_GETCHAIN
}
# TODO: What about 'ingress' (netdev family)?
hooks = {
'prerouting': 0,
Expand Down Expand Up @@ -103,13 +111,18 @@ def rule(self, cmd, **kwarg):
expressions=(ipv4addr(src='192.168.0.0/24'),
verdict(code=1)))
'''
# TODO: more operations
commands = {'add': NFT_MSG_NEWRULE, 'del': NFT_MSG_DELRULE}
commands = {
'add': NFT_MSG_NEWRULE,
'create': NFT_MSG_NEWRULE,
'insert': NFT_MSG_NEWRULE,
'replace': NFT_MSG_NEWRULE,
'del': NFT_MSG_DELRULE,
'get': NFT_MSG_GETRULE
}

if 'expressions' in kwarg:
expressions = []
for exp in kwarg['expressions']:
expressions.extend(exp)
kwarg['expressions'] = expressions
# FIXME: flags!!!
return self._command(nft_rule_msg, commands, cmd, kwarg, flags=3585)
return self._command(nft_rule_msg, commands, cmd, kwarg)

0 comments on commit 729de2d

Please sign in to comment.