#!/usr/bin/env python

import sys
import os
import re
import subprocess
import logging, logging.handlers

# log_level can be set to one of (prefixed by logging.)
# DEBUG, INFO, WARNING, ERROR, CRITICAL
log_level = logging.WARNING

DEFAULT_DEVICE_IP = "169.254.2.1"
DEFAULT_LOCAL_IP = "169.254.2.2"
DEFAULT_NETMASK = "255.255.255.0"
DEFAULT_BROADCAST = "169.254.2.255"

global device_ip
global local_ip

device_ip = False
local_ip = False

logger = None

#
# fall back to static config
#
def RunIfconfig(iface):

    logger.debug("attempting static ip configuration")
    cmd_list = ["ifconfig",iface,DEFAULT_LOCAL_IP,"netmask",DEFAULT_NETMASK,"broadcast",DEFAULT_BROADCAST]

    global device_ip
    global local_ip

    # returns a Popen object
    proc = subprocess.Popen(cmd_list, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    output_text = proc.communicate()[0]
    rc = proc.returncode

    if rc != 0:
        logger.debug("ifconfig failed with return code %d",rc)
        return False

    logger.debug("ifconfig succeeded")

    device_ip = DEFAULT_DEVICE_IP
    local_ip = DEFAULT_LOCAL_IP

    return


#
# try to contact device's dhcp server
#
def RunDhclient(iface):

    logger.debug("attempting dynamic ip configuration")
    cmd_list = ["dhclient",iface]

    global device_ip
    global local_ip

    # returns a Popen object
    proc = subprocess.Popen(cmd_list, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    output_text = proc.communicate()[0]
    rc = proc.returncode

    if rc != 0:
        logger.debug("dhclient failed with return code %d",rc)
        return False

    output_list = output_text.split('\n')

    dhcp_ack_re = re.compile('DHCPACK from (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
    dhcp_bound_re = re.compile('bound to (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')

    for line in output_list:
        logger.debug("dhclient output: "+line)

        match_obj = dhcp_ack_re.match(line)
        if match_obj != None:
            device_ip = match_obj.group(1)
            logger.debug("dhclient returned device address "+device_ip)

        match_obj = dhcp_bound_re.match(line)
        if match_obj != None:
            local_ip = match_obj.group(1)
            logger.debug("dhclient returned local address "+local_ip)

    return


#
# run dccm after the interface is configured
#
def RunDccm(py_log_level):

    logger.debug("starting hal-dccm ...")

    log_level = "1"

    if py_log_level <= logging.DEBUG:
        log_level = "6"
    elif py_log_level <= logging.INFO:
        log_level = "4"
    elif py_log_level <= logging.WARNING:
        log_level = "3"

    cmd_list = ["/usr/libexec/hal-dccm","--rndis","--device-ip="+device_ip, "--local-ip="+local_ip, "--log-level="+log_level]

    logger.debug(cmd_list)

    os.execv("/usr/libexec/hal-dccm", cmd_list)
    logger.error("failed to exec hal-dccm !!")

    return


#
# main()
#
if __name__ == '__main__':

    log_facility = logging.handlers.SysLogHandler.LOG_DAEMON

    logging.basicConfig(level=log_level,
                        format='%(asctime)s %(name)s %(levelname)s : %(message)s')
    logger = logging.getLogger("hal-synce-rndis")
    sys_log = logging.handlers.SysLogHandler("/dev/log", log_facility)
    logger.addHandler(sys_log)

    if os.environ.has_key("HAL_PROP_NET_INTERFACE"):
        iface = os.environ["HAL_PROP_NET_INTERFACE"]
    else:
        logger.warning("Hal environment not set")
        sys.exit(1)

    logger.debug("running as addon for interface "+iface)

    RunDhclient(iface)

    if device_ip == False or local_ip == False:
        logger.info("error running dhclient, trying static config")

        RunIfconfig(iface)
        if device_ip == False or local_ip == False:
            logger.warning("failed to configure interface")
            sys.exit(1)

    logger.debug("successfully configured interface")

    RunDccm(log_level)

    logger.error("exiting ...")

    sys.exit(0)
