# Buggy code
def _interfaces_ifconfig(out):
    """
    Uses ifconfig to return a dictionary of interfaces with various information
    about each (up/down state, ip address, netmask, and hwaddr)
    """
    ret = dict()

    piface = re.compile(r"^([^\s:]+)")
    pmac = re.compile(".*?(?:HWaddr|ether|address:|lladdr) ([0-9a-fA-F:]+)")
    if salt.utils.is_sunos():
        pip = re.compile(r".*?(?:inet\s+)([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(.*)")
        pip6 = re.compile(".*?(?:inet6 )([0-9a-fA-F:]+)")
        pmask6 = re.compile(r".*?(?:inet6 [0-9a-fA-F:]+/(\d+)).*")
    else:
        pip = re.compile(r".*?(?:inet addr:|inet )(.*?)\s")
        pip6 = re.compile(".*?(?:inet6 addr: (.*?)/|inet6 )([0-9a-fA-F:]+)")
        pmask6 = re.compile(
            r".*?(?:inet6 addr: [0-9a-fA-F:]+/(\d+)|prefixlen (\d+))(?: Scope:([a-zA-Z]+)| scopeid (0x[0-9a-fA-F]))?"
        )
    pmask = re.compile(r".*?(?:Mask:|netmask )(?:((?:0x)?[0-9a-fA-F]{8})|([\d\.]+))")
    pupdown = re.compile("UP")
    pbcast = re.compile(r".*?(?:Bcast:|broadcast )([\d\.]+)")

    groups = re.compile("\r?\n(?=\\S)").split(out)
    for group in groups:
        data = dict()
        iface = ""
        updown = False
        for line in group.splitlines():
            miface = piface.match(line)
            mmac = pmac.match(line)
            mip = pip.match(line)
            mip6 = pip6.match(line)
            mupdown = pupdown.search(line)
            if miface:
                iface = miface.group(1)
            if mmac:
                data["hwaddr"] = mmac.group(1)
            if mip:
                if "inet" not in data:
                    data["inet"] = list()
                addr_obj = dict()
                addr_obj["address"] = mip.group(1)
                mmask = pmask.match(line)
                if mmask:
                    if mmask.group(1):
                        mmask = _number_of_set_bits_to_ipv4_netmask(
                            int(mmask.group(1), 16)
                        )
                    else:
                        mmask = mmask.group(2)
                    addr_obj["netmask"] = mmask
                mbcast = pbcast.match(line)
                if mbcast:
                    addr_obj["broadcast"] = mbcast.group(1)
                data["inet"].append(addr_obj)
            if mupdown:
                updown = True
            if mip6:
                if "inet6" not in data:
                    data["inet6"] = list()
                addr_obj = dict()
                addr_obj["address"] = mip6.group(1) or mip6.group(2)
                mmask6 = pmask6.match(line)
                if mmask6:
                    addr_obj["prefixlen"] = mmask6.group(1) or mmask6.group(2)
                    if not salt.utils.is_sunos():
                        ipv6scope = mmask6.group(3) or mmask6.group(4)
                        addr_obj["scope"] = (
                            ipv6scope.lower() if ipv6scope is not None else ipv6scope
                        )
                data["inet6"].append(addr_obj)
        data["up"] = updown
        if iface in ret:
            # SunOS optimization, where interfaces occur twice in 'ifconfig -a'
            # output with the same name: for ipv4 and then for ipv6 addr family.
            # Every instance has it's own 'UP' status and we assume that ipv4
            # status determines global interface status.
            #
            # merge items with higher priority for older values
            # after that merge the inet and inet6 sub items for both
            ret[iface] = dict(list(data.items()) + list(ret[iface].items()))
            if "inet" in data:
                ret[iface]["inet"].extend(
                    x for x in data["inet"] if x not in ret[iface]["inet"]
                )
            if "inet6" in data:
                ret[iface]["inet6"].extend(
                    x for x in data["inet6"] if x not in ret[iface]["inet6"]
                )
        else:
            ret[iface] = data
        del data
    return ret


# Traceback (ValueError)
2015-12-18 11:03:40,410 [salt.scripts                             ][ERROR   ][18580] Minion failed to start:
Traceback (most recent call last):
File "/usr/pkg/lib/python2.7/site-packages/salt/scripts.py", line 81, in minion_process
minion.start()
File "/usr/pkg/lib/python2.7/site-packages/salt/cli/daemons.py", line 272, in start
self.prepare()
File "/usr/pkg/lib/python2.7/site-packages/salt/cli/daemons.py", line 254, in prepare
self.minion = salt.minion.Minion(self.config)
File "/usr/pkg/lib/python2.7/site-packages/salt/minion.py", line 708, in __init__
self.opts['grains'] = salt.loader.grains(opts)
File "/usr/pkg/lib/python2.7/site-packages/salt/loader.py", line 613, in grains
ret = fun()
File "/usr/pkg/lib/python2.7/site-packages/salt/grains/core.py", line 1430, in ip4
return {'ipv4': salt.utils.network.ip_addrs(include_loopback=True)}
File "/usr/pkg/lib/python2.7/site-packages/salt/utils/network.py", line 993, in ip_addrs
return _ip_addrs(interface, include_loopback, interface_data, 'inet')
File "/usr/pkg/lib/python2.7/site-packages/salt/utils/network.py", line 981, in _ip_addrs
addr = ipaddress.ip_address(addr.get('address'))
File "/usr/pkg/lib/python2.7/site-packages/salt/ext/ipaddress.py", line 117, in ip_address
address)
ValueError: 'alias' does not appear to be an IPv4 or IPv6 address
2015-12-18 11:03:40,420 [salt.scripts                             ][WARNING ][18580] ** Restarting minion **

# Fixed code
def _interfaces_ifconfig(out):
    """
    Uses ifconfig to return a dictionary of interfaces with various information
    about each (up/down state, ip address, netmask, and hwaddr)
    """
    ret = dict()

    piface = re.compile(r"^([^\s:]+)")
    pmac = re.compile(".*?(?:HWaddr|ether|address:|lladdr) ([0-9a-fA-F:]+)")
    if salt.utils.is_sunos():
        pip = re.compile(r".*?(?:inet\s+)([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(.*)")
        pip6 = re.compile(".*?(?:inet6 )([0-9a-fA-F:]+)")
        pmask6 = re.compile(r".*?(?:inet6 [0-9a-fA-F:]+/(\d+)).*")
    else:
        pip = re.compile(r".*?(?:inet addr:|inet [^\d]*)(.*?)\s")
        pip6 = re.compile(".*?(?:inet6 addr: (.*?)/|inet6 )([0-9a-fA-F:]+)")
        pmask6 = re.compile(
            r".*?(?:inet6 addr: [0-9a-fA-F:]+/(\d+)|prefixlen (\d+))(?: Scope:([a-zA-Z]+)| scopeid (0x[0-9a-fA-F]))?"
        )
    pmask = re.compile(r".*?(?:Mask:|netmask )(?:((?:0x)?[0-9a-fA-F]{8})|([\d\.]+))")
    pupdown = re.compile("UP")
    pbcast = re.compile(r".*?(?:Bcast:|broadcast )([\d\.]+)")

    groups = re.compile("\r?\n(?=\\S)").split(out)
    for group in groups:
        data = dict()
        iface = ""
        updown = False
        for line in group.splitlines():
            miface = piface.match(line)
            mmac = pmac.match(line)
            mip = pip.match(line)
            mip6 = pip6.match(line)
            mupdown = pupdown.search(line)
            if miface:
                iface = miface.group(1)
            if mmac:
                data["hwaddr"] = mmac.group(1)
            if mip:
                if "inet" not in data:
                    data["inet"] = list()
                addr_obj = dict()
                addr_obj["address"] = mip.group(1)
                mmask = pmask.match(line)
                if mmask:
                    if mmask.group(1):
                        mmask = _number_of_set_bits_to_ipv4_netmask(
                            int(mmask.group(1), 16)
                        )
                    else:
                        mmask = mmask.group(2)
                    addr_obj["netmask"] = mmask
                mbcast = pbcast.match(line)
                if mbcast:
                    addr_obj["broadcast"] = mbcast.group(1)
                data["inet"].append(addr_obj)
            if mupdown:
                updown = True
            if mip6:
                if "inet6" not in data:
                    data["inet6"] = list()
                addr_obj = dict()
                addr_obj["address"] = mip6.group(1) or mip6.group(2)
                mmask6 = pmask6.match(line)
                if mmask6:
                    addr_obj["prefixlen"] = mmask6.group(1) or mmask6.group(2)
                    if not salt.utils.is_sunos():
                        ipv6scope = mmask6.group(3) or mmask6.group(4)
                        addr_obj["scope"] = (
                            ipv6scope.lower() if ipv6scope is not None else ipv6scope
                        )
                data["inet6"].append(addr_obj)
        data["up"] = updown
        if iface in ret:
            # SunOS optimization, where interfaces occur twice in 'ifconfig -a'
            # output with the same name: for ipv4 and then for ipv6 addr family.
            # Every instance has it's own 'UP' status and we assume that ipv4
            # status determines global interface status.
            #
            # merge items with higher priority for older values
            # after that merge the inet and inet6 sub items for both
            ret[iface] = dict(list(data.items()) + list(ret[iface].items()))
            if "inet" in data:
                ret[iface]["inet"].extend(
                    x for x in data["inet"] if x not in ret[iface]["inet"]
                )
            if "inet6" in data:
                ret[iface]["inet6"].extend(
                    x for x in data["inet6"] if x not in ret[iface]["inet6"]
                )
        else:
            ret[iface] = data
        del data
    return ret