# Path: shapy/framework/netlink/connection.py
# class Connection(object):
#     """
#     Object representing Netlink socket connection to the kernel.
#     """
#     def __init__(self, nlservice=socket.NETLINK_ROUTE, groups=0):
#         # nlservice = Netlink IP service
#         self.fd = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, nlservice)
#         self.fd.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 65536)
#         self.fd.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
#         self.fd.bind((0, groups)) # pid=0 lets kernel assign socket PID
#         self.pid, self.groups = self.fd.getsockname()
#         self._seq = 0
#     
#     def send(self, msg):
#         if isinstance(msg, Message):
#             if msg.seq == -1: 
#                 msg.seq = self.seq()
#             msg.pid = self.pid
#             msg = msg.pack()
#         self.fd.send(msg)
#     
#     def recv(self):
#         contents, (nlpid, nlgrps) = self.fd.recvfrom(16384)
#         msg = Message.unpack(contents)
#         
#         if msg.type == NLMSG_ERROR:
#             errno = -msg.service_template.error_code
#             #errno = -struct.unpack("i", msg.payload[:4])[0]
#             if errno != 0:
#                 err = OSError("Netlink error: %s (%d) | msg: %s" % (
#                     os.strerror(errno), errno, msg.service_template.old_message))
#                 err.errno = errno
#                 raise err
#         return msg
#     
#     def seq(self):
#         self._seq += 1
#         return self._seq
# 
# Path: shapy/framework/utils.py
# def nl_us2ticks(delay):
#     """Convert microseconds to timer ticks."""
#     return int(ticks_per_usec * delay)


import os
import unittest
import socket
import struct
from struct import Struct
from shapy.framework.netlink.constants import *
from shapy.framework.netlink.message import *
from shapy.framework.netlink.tc import *
from shapy.framework.netlink.connection import Connection
from shapy.framework.netlink.netem import *
from shapy.framework.netlink.filter import *
from shapy.framework.utils import nl_us2ticks
from tests.utils import *
        from shapy.framework.netlink.htb import tc_calc_rtable
            index 2 ref 1 bind 1
        """
        data = "\x94\x00\x00\x00\x2c\x00\x05\x06\x4f\x21\xda\x4d\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x08\x00\x03\x00\x08\x00\x01\x00\x75\x33\x32\x00\x68\x00\x02\x00\x08\x00\x01\x00\x01\x00\x01\x00\x38\x00\x07\x00\x34\x00\x01\x00\x0b\x00\x01\x00\x6d\x69\x72\x72\x65\x64\x00\x00\x24\x00\x02\x00\x20\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\x24\x00\x05\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x7f\x00\x00\x04\x10\x00\x00\x00\x00\x00\x00\x00"
        msg = Message.unpack(data)
        st = msg.service_template
        attr = st.attributes
        
        tc_u32_sel = Struct("BBBHHhhI")
        tc_u32_key = Struct("IIii")
        filter_opt = list(unpack_attrs(attr[1].payload)) # TCA_KIND, TCA_OPTIONS
        action = list(unpack_attrs(filter_opt[1].payload)) # TCA_EGRESS_REDIR
        mirred = list(unpack_attrs(action[0].payload)) # TCA_ACT_KIND, TCA_ACT_OPTIONS
        mirred_parms = list(unpack_attrs(mirred[1].payload))
        
        tc_mirred = Struct("IIiiiiI")
        #print tc_mirred.unpack(mirred_parms[0].payload)
    
    
    def test_unpack_add_netem(self):
        """tc qdisc add dev lo root handle 1: netem delay 10ms"""
        data = "\x4c\x00\x00\x00\x24\x00\x05\x06\x07\x1b\xcc\x4d\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\xff\xff\xff\xff\x00\x00\x00\x00\x0a\x00\x01\x00\x6e\x65\x74\x65\x6d\x00\x00\x00\x1c\x00\x02\x00\x5a\x62\x02\x00\xe8\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
        msg = Message.unpack(data)
        self.assertEqual(msg.type, RTM_NEWQDISC)
        self.assertEqual(msg.flags, 0x605)

        st = msg.service_template
        self.assertAlmostEqual(st.tcm_handle, 0x10000)
        self.assertAlmostEqual(st.tcm_parent, 0xffffffff)
        
        attr, data = NetemOptions.unpack(data[-28:])

# Path: shapy/framework/netlink/connection.py
# class Connection(object):
#     """
#     Object representing Netlink socket connection to the kernel.
#     """
#     def __init__(self, nlservice=socket.NETLINK_ROUTE, groups=0):
#         # nlservice = Netlink IP service
#         self.fd = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, nlservice)
#         self.fd.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 65536)
#         self.fd.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
#         self.fd.bind((0, groups)) # pid=0 lets kernel assign socket PID
#         self.pid, self.groups = self.fd.getsockname()
#         self._seq = 0
#     
#     def send(self, msg):
#         if isinstance(msg, Message):
#             if msg.seq == -1: 
#                 msg.seq = self.seq()
#             msg.pid = self.pid
#             msg = msg.pack()
#         self.fd.send(msg)
#     
#     def recv(self):
#         contents, (nlpid, nlgrps) = self.fd.recvfrom(16384)
#         msg = Message.unpack(contents)
#         
#         if msg.type == NLMSG_ERROR:
#             errno = -msg.service_template.error_code
#             #errno = -struct.unpack("i", msg.payload[:4])[0]
#             if errno != 0:
#                 err = OSError("Netlink error: %s (%d) | msg: %s" % (
#                     os.strerror(errno), errno, msg.service_template.old_message))
#                 err.errno = errno
#                 raise err
#         return msg
#     
#     def seq(self):
#         self._seq += 1
#         return self._seq
# 
# Path: shapy/framework/utils.py
# def nl_us2ticks(delay):
#     """Convert microseconds to timer ticks."""
#     return int(ticks_per_usec * delay)


# Path: tests/netlink/test_unpack.py
import os
import unittest
import socket
import struct
from struct import Struct
from shapy.framework.netlink.constants import *
from shapy.framework.netlink.message import *
from shapy.framework.netlink.tc import *
from shapy.framework.netlink.connection import Connection
from shapy.framework.netlink.netem import *
from shapy.framework.netlink.filter import *
from shapy.framework.utils import nl_us2ticks
from tests.utils import *
        from shapy.framework.netlink.htb import tc_calc_rtable

            index 2 ref 1 bind 1
        """
        data = "\x94\x00\x00\x00\x2c\x00\x05\x06\x4f\x21\xda\x4d\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x08\x00\x03\x00\x08\x00\x01\x00\x75\x33\x32\x00\x68\x00\x02\x00\x08\x00\x01\x00\x01\x00\x01\x00\x38\x00\x07\x00\x34\x00\x01\x00\x0b\x00\x01\x00\x6d\x69\x72\x72\x65\x64\x00\x00\x24\x00\x02\x00\x20\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\x24\x00\x05\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x7f\x00\x00\x04\x10\x00\x00\x00\x00\x00\x00\x00"
        msg = Message.unpack(data)
        st = msg.service_template
        attr = st.attributes
        
        tc_u32_sel = Struct("BBBHHhhI")
        tc_u32_key = Struct("IIii")
        filter_opt = list(unpack_attrs(attr[1].payload)) # TCA_KIND, TCA_OPTIONS
        action = list(unpack_attrs(filter_opt[1].payload)) # TCA_EGRESS_REDIR
        mirred = list(unpack_attrs(action[0].payload)) # TCA_ACT_KIND, TCA_ACT_OPTIONS
        mirred_parms = list(unpack_attrs(mirred[1].payload))
        
        tc_mirred = Struct("IIiiiiI")
        #print tc_mirred.unpack(mirred_parms[0].payload)
    
    
    def test_unpack_add_netem(self):
        """tc qdisc add dev lo root handle 1: netem delay 10ms"""
        data = "\x4c\x00\x00\x00\x24\x00\x05\x06\x07\x1b\xcc\x4d\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\xff\xff\xff\xff\x00\x00\x00\x00\x0a\x00\x01\x00\x6e\x65\x74\x65\x6d\x00\x00\x00\x1c\x00\x02\x00\x5a\x62\x02\x00\xe8\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
        msg = Message.unpack(data)
        self.assertEqual(msg.type, RTM_NEWQDISC)
        self.assertEqual(msg.flags, 0x605)

        st = msg.service_template
        self.assertAlmostEqual(st.tcm_handle, 0x10000)
        self.assertAlmostEqual(st.tcm_parent, 0xffffffff)
        
        attr, data = NetemOptions.unpack(data[-28:])

        self.assertEqual(attr.data.latency, nl_us2ticks(10*1000))