@!@
from univention.config_registry.interfaces import Interfaces
from itertools import groupby
from operator import itemgetter


def auto(interface, start):
    """Print 'auto iface' statements only once."""
    print('')
    if not start:
        return
    if interface not in auto.printed_interfaces:
        print('auto %s' % (interface,))
        auto.printed_interfaces.add(interface)


auto.printed_interfaces = set()


def ipv4(ucr, interfaces):
    """Setup IPv4."""
    gateway = interfaces.ipv4_gateway
    if gateway is False:
        print('# WARNING: invalid IPv4 address in gateway')

    for name, iface in interfaces.all_interfaces:
        addr = iface.ipv4_address()
        if iface.type == 'dhcp':
            auto(iface.name, iface.start)
            print('iface %s inet dhcp' % (iface.name,))
        elif iface.type == 'manual':
            auto(iface.name, iface.start)
            print('iface %s inet manual' % (iface.name,))
        elif addr is False:
            print('# ERROR: invalid IPv4 address for interface %s' % (name,))
            continue
        elif addr:
            auto(iface.name, iface.start)
            print('iface %s inet static' % (iface.name,))
            print('\taddress %s' % (addr.ip,))
            print('\tnetmask %s' % (addr.netmask,))
            if iface.network:
                print('\tnetwork %s' % (iface.network,))
            if iface.broadcast:
                print('\tbroadcast %s' % (iface.broadcast,))
            if 'mtu' in iface:
                print('\tmtu %(mtu)s' % iface)
            if gateway:
                if addr.network.prefixlen == addr.max_prefixlen and interfaces.primary in (name, iface.name):
                    print('\tpointopoint %s' % (gateway,))
                    print('\tgateway %s' % (gateway,))
                    gateway = None
                elif gateway in addr.network:
                    print('\tgateway %s' % (gateway,))
                    gateway = None
        else:
            continue

        for route in iface.routes:
            print('\tup route add -%s dev %s' % (route, iface.name))

        for value in iface.options:
            print('\t%s' % (value,))


def ipv6(interfaces):
    """Setup IPv6."""
    gateway = interfaces.ipv6_gateway
    if gateway is False:
        print('# WARNING: invalid IPv6 address in ipv6/gateway')
    gateway_zoneindex = interfaces.ipv6_gateway_zone_index

    # Validate addresses
    interface_addresses = {}
    for _iface_name, iface in interfaces.all_interfaces:
        for name in iface.ipv6_names:
            addr = iface.ipv6_address(name)
            if not addr:
                print('# ERROR: incomplete/invalid IPv6 address in interfaces/%s/ipv6/%s/*' % (iface.name, name))
                continue
            addresses = interface_addresses.setdefault(iface.name, set())
            if addr.ip in addresses:
                print('# ERROR: duplicate IPv6 address in interfaces/%s/ipv6/%s/*' % (iface.name, name))
                continue
            addresses.add(addr.ip)

    # configure interface
    for iface, names in groupby(interfaces.ipv6_interfaces, itemgetter(0)):
        try:
            addresses = interface_addresses[iface.name]
        except KeyError:
            continue  # validation failed

        auto(iface.name, iface.start)
        print('iface %s inet6 static' % (iface.name,))

        if gateway and gateway_zoneindex == iface.name:
            print('\tgateway %s' % (gateway, ))
            gateway = None
        for i, (iface, name) in enumerate(names):
            addr = iface.ipv6_address(name)
            try:
                addresses.remove(addr.ip)
            except KeyError:
                continue  # invalid or duplicate
            print('# %s' % (name,))
            if i == 0:  # first
                print('\taddress %s' % (addr.ip,))
                print('\tnetmask %s' % (addr.network.prefixlen,))
            else:
                print('\tup   ip -6 addr add %s dev %s' % (addr, iface.name))
                print('\tdown ip -6 addr del %s dev %s' % (addr, iface.name))
            if 'mtu' in iface:
                print('\tmtu %(mtu)s' % iface)
            if gateway_zoneindex is None:
                # check if gateway is local on this interface
                if gateway:
                    if addr.network.prefixlen == addr.max_prefixlen and iface.name == interfaces.primary:
                        data = (gateway, iface.name)
                        print('\tup   ip -6 route add %s dev %s' % data)
                        print('\tup   ip -6 route add default via %s dev %s' % data)
                        print('\tdown ip -6 route del default via %s dev %s' % data)
                        print('\tdown ip -6 route del %s dev %s' % data)
                        gateway = None
                    elif gateway in addr.network:
                        print('\tgateway %s' % (gateway,))
                        gateway = None

        if not iface.ipv4_address():
            for value in iface.options:
                print('\t%s' % (value,))


def main():
    """Create configured interfaces."""
    interfaces = Interfaces(configRegistry)
    ipv4(configRegistry, interfaces)
    ipv6(interfaces)


main()
@!@
