diff options
Diffstat (limited to 'node-admin/scripts/pyroute2/netlink/ipq/__init__.py')
-rw-r--r-- | node-admin/scripts/pyroute2/netlink/ipq/__init__.py | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/node-admin/scripts/pyroute2/netlink/ipq/__init__.py b/node-admin/scripts/pyroute2/netlink/ipq/__init__.py new file mode 100644 index 00000000000..7408f50e877 --- /dev/null +++ b/node-admin/scripts/pyroute2/netlink/ipq/__init__.py @@ -0,0 +1,131 @@ +# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details. +''' +IPQ -- userspace firewall +========================= + +Netlink family for dealing with `QUEUE` iptables +target. All the packets routed to the target +`QUEUE` should be handled by a userspace program +and the program should response with a verdict. +E.g., the verdict can be `NF_DROP` and in that +case the packet will be silently dropped, or +`NF_ACCEPT`, and the packet will be pass the +rule. +''' +from pyroute2.netlink import NLM_F_REQUEST +from pyroute2.netlink import nlmsg +from pyroute2.netlink.nlsocket import NetlinkSocket +from pyroute2.netlink.nlsocket import Marshal +# constants +IFNAMSIZ = 16 +IPQ_MAX_PAYLOAD = 0x800 + +# IPQ messages +IPQM_BASE = 0x10 +IPQM_MODE = IPQM_BASE + 1 +IPQM_VERDICT = IPQM_BASE + 2 +IPQM_PACKET = IPQM_BASE + 3 + +# IPQ modes +IPQ_COPY_NONE = 0 +IPQ_COPY_META = 1 +IPQ_COPY_PACKET = 2 + +# verdict types +NF_DROP = 0 +NF_ACCEPT = 1 +NF_STOLEN = 2 +NF_QUEUE = 3 +NF_REPEAT = 4 +NF_STOP = 5 + + +class ipq_base_msg(nlmsg): + def decode(self): + nlmsg.decode(self) + self['payload'] = self.buf.read(self['data_len']) + + def encode(self): + init = self.buf.tell() + nlmsg.encode(self) + if 'payload' in self: + self.buf.write(self['payload']) + self.update_length(init) + + +class ipq_packet_msg(ipq_base_msg): + fields = (('packet_id', 'L'), + ('mark', 'L'), + ('timestamp_sec', 'l'), + ('timestamp_usec', 'l'), + ('hook', 'I'), + ('indev_name', '%is' % IFNAMSIZ), + ('outdev_name', '%is' % IFNAMSIZ), + ('hw_protocol', '>H'), + ('hw_type', 'H'), + ('hw_addrlen', 'B'), + ('hw_addr', '6B'), + ('__pad', '9x'), + ('data_len', 'I'), + ('__pad', '4x')) + + +class ipq_mode_msg(nlmsg): + pack = 'struct' + fields = (('value', 'B'), + ('__pad', '7x'), + ('range', 'I'), + ('__pad', '12x')) + + +class ipq_verdict_msg(ipq_base_msg): + pack = 'struct' + fields = (('value', 'I'), + ('__pad', '4x'), + ('id', 'L'), + ('data_len', 'I'), + ('__pad', '4x')) + + +class MarshalIPQ(Marshal): + + msg_map = {IPQM_MODE: ipq_mode_msg, + IPQM_VERDICT: ipq_verdict_msg, + IPQM_PACKET: ipq_packet_msg} + + +class IPQSocket(NetlinkSocket): + ''' + Low-level socket interface. Provides all the + usual socket does, can be used in poll/select, + doesn't create any implicit threads. + ''' + + def bind(self, mode=IPQ_COPY_PACKET): + ''' + Bind the socket and performs IPQ mode configuration. + The only parameter is mode, the default value is + IPQ_COPY_PACKET (copy all the packet data). + ''' + NetlinkSocket.bind(self, groups=0, pid=0) + self.register_policy(MarshalIPQ.msg_map) + msg = ipq_mode_msg() + msg['value'] = mode + msg['range'] = IPQ_MAX_PAYLOAD + msg['header']['type'] = IPQM_MODE + msg['header']['flags'] = NLM_F_REQUEST + msg.encode() + self.sendto(msg.buf.getvalue(), (0, 0)) + + def verdict(self, seq, v): + ''' + Issue a verdict `v` for a packet `seq`. + ''' + msg = ipq_verdict_msg() + msg['value'] = v + msg['id'] = seq + msg['data_len'] = 0 + msg['header']['type'] = IPQM_VERDICT + msg['header']['flags'] = NLM_F_REQUEST + msg.encode() + self.sendto(msg.buf.getvalue(), (0, 0)) |