# Copyright (c) 2019, Stefan Grönke
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted providing that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
"""Types used by jail (2)."""
import typing
import ctypes
import ipaddress
import struct

MAX_INT = 2 ** (8 * ctypes.sizeof(ctypes.c_int)) // 2 - 1
MIN_INT = - 2 ** (8 * ctypes.sizeof(ctypes.c_int)) // 2

in_addr_t = ctypes.c_uint32


class in_addr(ctypes.BigEndianStructure):
    """Internet IPv4 address."""
    _fields_ = [('s_addr', in_addr_t)]


class in6_addr_U(ctypes.Union):
    """Internet IPv6 address."""
    _fields_ = [
        ('__u6_addr8', ctypes.c_uint8 * 16),
        ('__u6_addr16', ctypes.c_uint16 * 8),
        ('__u6_addr32', ctypes.c_uint32 * 4),
    ]


class in6_addr(ctypes.Structure):
    """Internet IPv6 address."""
    _fields_ = [
        ('__in6_u', in6_addr_U),
    ]


def in6_addr_U_from_ip(ip6_address: ipaddress.IPv6Address) -> in6_addr_U:
    """Return in7_addr_U from ipaddress.IPv6Address."""
    return in6_addr_U(struct.unpack(
        "B"*16,
        bytes.fromhex(ip6_address.exploded.replace(":",""))
    ))
