# Path: shapy/framework/netlink/message.py
# class Message(object):
#     """Object representing the entire Netlink message."""
#     #0                   1                   2                   3
#     #0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
#     #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#     #|                          Length                             |
#     #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#     #|            Type              |           Flags              |
#     #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#     #|                      Sequence Number                        |
#     #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#     #|                      Process ID (PID)                       |
#     #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#     
#     #struct nlmsghdr {
#     #   __u32 nlmsg_len;    /* Length of message including header. */
#     #   __u16 nlmsg_type;   /* Type of message content. */
#     #   __u16 nlmsg_flags;  /* Additional flags. */
#     #   __u32 nlmsg_seq;    /* Sequence number. */
#     #   __u32 nlmsg_pid;    /* PID of the sending process. */
#     #};
#     
#     nlmsghdr = Struct("IHHII")
#     
#     @classmethod
#     def unpack(cls, msg):
#         """Unpack raw bytes into a Netlink message."""
#         mlength, type, flags, seq, pid = cls.nlmsghdr.unpack(msg[:cls.nlmsghdr.size])
#         st = None
#         if msg[cls.nlmsghdr.size:] > 0:
#             st_cls = ServiceTemplate.select(type)
#             st = st_cls.unpack(msg[cls.nlmsghdr.size:])
#         return Message(type, flags, seq, service_template=st)
#     
#     def __init__(self, type, flags=0, seq=-1, service_template=None):
#         """Used for creating Netlink messages."""
#         self.type = type
#         self.flags = flags
#         self.seq = seq
#         self.pid = 0
#         self.service_template = service_template
#         self.service_template.message = self
# 
#     def __len__(self):
#         """Aligned length of service template message + attributes."""
#         return align(self.nlmsghdr.size + len(self.payload))
#     
#     def pack_header(self):
#         return self.nlmsghdr.pack(len(self), self.type, self.flags, self.seq, self.pid)
# 
#     def pack(self):
#         return self.pack_header() + self.payload
# 
#     @property
#     def payload(self):
#         return self.service_template.pack()
#     
#     def __repr__(self):
#         return '<netlink message type=%s, pid=%s, seq=%s, flags=0x%x>' % (
#             self.type, self.pid, self.seq, self.flags)


import os
import socket
import struct
from .constants import *
from .message import Message

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)

# Path: shapy/framework/netlink/message.py
# class Message(object):
#     """Object representing the entire Netlink message."""
#     #0                   1                   2                   3
#     #0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
#     #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#     #|                          Length                             |
#     #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#     #|            Type              |           Flags              |
#     #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#     #|                      Sequence Number                        |
#     #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#     #|                      Process ID (PID)                       |
#     #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#     
#     #struct nlmsghdr {
#     #   __u32 nlmsg_len;    /* Length of message including header. */
#     #   __u16 nlmsg_type;   /* Type of message content. */
#     #   __u16 nlmsg_flags;  /* Additional flags. */
#     #   __u32 nlmsg_seq;    /* Sequence number. */
#     #   __u32 nlmsg_pid;    /* PID of the sending process. */
#     #};
#     
#     nlmsghdr = Struct("IHHII")
#     
#     @classmethod
#     def unpack(cls, msg):
#         """Unpack raw bytes into a Netlink message."""
#         mlength, type, flags, seq, pid = cls.nlmsghdr.unpack(msg[:cls.nlmsghdr.size])
#         st = None
#         if msg[cls.nlmsghdr.size:] > 0:
#             st_cls = ServiceTemplate.select(type)
#             st = st_cls.unpack(msg[cls.nlmsghdr.size:])
#         return Message(type, flags, seq, service_template=st)
#     
#     def __init__(self, type, flags=0, seq=-1, service_template=None):
#         """Used for creating Netlink messages."""
#         self.type = type
#         self.flags = flags
#         self.seq = seq
#         self.pid = 0
#         self.service_template = service_template
#         self.service_template.message = self
# 
#     def __len__(self):
#         """Aligned length of service template message + attributes."""
#         return align(self.nlmsghdr.size + len(self.payload))
#     
#     def pack_header(self):
#         return self.nlmsghdr.pack(len(self), self.type, self.flags, self.seq, self.pid)
# 
#     def pack(self):
#         return self.pack_header() + self.payload
# 
#     @property
#     def payload(self):
#         return self.service_template.pack()
#     
#     def __repr__(self):
#         return '<netlink message type=%s, pid=%s, seq=%s, flags=0x%x>' % (
#             self.type, self.pid, self.seq, self.flags)


# Path: shapy/framework/netlink/connection.py
import os
import socket
import struct
from .constants import *
from .message import Message


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)