#!/bin/bash

#### SOME DEFAULTS ONE MIGHT OVERRIDE //start
DEBUG_ALLOW_DUMMY_INTERFACES=0
DEBUG_DNS=''
YMC_SIMPLE_CALC_DIGITS=5
ALLOW_NETWORK_DISRUPTION=0
#### SOME DEFAULTS ONE MIGHT OVERRIDE //end


################

function ymc_simple_calc
{
  experssion=$*
  result=$(echo "scale=$YMC_SIMPLE_CALC_DIGITS; $experssion" | LC_ALL=C bc 2>/dev/null | sed -r 's/^\./0./' |sed -r 's/([0-9]+\..*)[0]+$/\1/' | sed -r 's/[.]+$//')
  if [ "$result" != '' ]; then
    echo $result
    return 0
  else
    return 1
  fi
}

function ymc_dec2hex
{
  decimal=$1
  ymc_simple_calc "obase=16; $decimal"
}

function ymc_hex2dec
{
  hex=$(ymc_str_to_upper $1)
  ymc_simple_calc "ibase=16; $hex"
}

################

function ymc_str_to_lower()
{
  string=$1
  echo $string | tr '[:upper:]' '[:lower:]'
}

ymc_str_to_upper()
{
  string=$1
  echo $string | tr '[:lower:]' '[:upper:]'
}

################

function ymc_get_harddrives
{
  return_code=1
  #ls /sys/block/ | grep -E -e '^[hsv]d[a-z]'
  #fdisk -l 2>/dev/null | grep -E -e "Disk /dev/[hsv]d[a-z]" | sed -r 's/.*\/dev\/([hsv]d[a-z]).*/\1/'
  #cat /proc/partitions 2>/dev/null | grep -E -e '[ \t]+[hsv]d[a-z]$' | sed -r 's/.*[ \t]+([hsv]d[a-z])$/\1/'

  min_clean=$(cat /proc/partitions 2>/dev/null | sed -r 's/^[0-9 ]+ //' | grep -v -E -e '(major minor)|(^[ ]*$|^dm-[0-9]+)|(^md[0-9]+)|(^sr[0-9]+)')
  block_devices=$(ls /sys/block/ | sed -r 's|cciss!c|cciss/c|g')
  for possible_disk in $min_clean
  do
    if [ $(ymc_contains $possible_disk $block_devices) -eq 1 ]; then
      return_code=0
      echo $possible_disk
    fi
  done
  return $return_code
}

function ymc_get_partition_for_drive_by_num
{
  whished_drive=$1
  partition_number=$2
  return_code=1
  min_clean=$(cat /proc/partitions 2>/dev/null | sed -r 's/^[0-9 ]+ //' | grep -v -E -e '(major minor)|(^[ ]*$|^dm-[0-9]+)|(^md[0-9]+)' | grep -E -e "^$whished_drive")
  counter=0
  for partitions_infos in $min_clean
  do
    if [ "$counter" == "$partition_number" ]; then
      return_code=0
      echo $partitions_infos
    fi
    counter=$(expr $counter + 1)
  done
  return $return_code
}

function ymc_get_disk_size
{
  drive=$1
  disk_info=$(fdisk -l /dev/$drive 2>/dev/null | grep -E -e '^Disk /dev/.*: .*, .*bytes$')
  disk_size=$(echo $disk_info | grep -E -e '^Disk /dev/.*: .*, .*bytes$' | sed -r 's/.*, ([0-9]+) bytes$/\1/' )
  if [ "$disk_size" != "$disk_info" ]; then
    echo $disk_size
    return 0
  else
    return 1
  fi
}

################

function ymc_get_hostname_from_dns_txt
{
  ip_to_look_up=$1
  zone_to_search_in=$2

  ymc_get_config_from_dns $ip_to_look_up"."$zone_to_search_in
  if [ $(echo $variables_set | wc -w) -eq 1 ]; then
    name=$(ymc_var_value $variables_set)
  else
    return 1
  fi

  if [ "$name" != '' ]; then
    echo $name
  else
    return 1
  fi
}

function ymc_validate_host_for_ip
{
  record_to_look_up=$1
  ip_to_search_for=$2
  if [ $(dig ${DEBUG_DNS:+@$DEBUG_DNS} "$record_to_look_up" +short 2>/dev/null | grep -c -F "$ip_to_search_for") -ne 1 ]; then
    echo 0
    return 1
  else
    echo 1
    return 0
  fi
}

function ymc_validate_ip_for_host
{
  ip_to_search_for=$1
  record_to_look_up=$2
  if [ $(dig ${DEBUG_DNS:+@$DEBUG_DNS} -x "$ip_to_search_for" +short 2>/dev/null | grep -c -F "$record_to_look_up") -ne 1 ]; then
    echo 0
    return 1
  else
    echo 1
    return 0
  fi
}

################

function ymc_is_host_alive
{
  ip_target=$1
  if [ "$ip_target" == '' ]; then
    echo 0
    return 1
  fi
  if [ $(LC_ALL=C ping -c 3 -W 1 -w 6 -i 0.3 -n $1 | grep -c " 0% packet loss") -ne 1 ]; then
    echo 0
    return 1
  else
    echo 1
    return 0
  fi
}


################

function ymc_get_primary_ip_for_network
{
  network=$1
  ip=$(LC_ALL=C /sbin/ifconfig | grep -A 1 -E -e '^'$network'[^:]+' | grep 'inet addr:' | sed -r 's/.*inet addr:([0-9.]+).*/\1/')
  if [ "$ip" != '' ]; then
    echo $ip
    return 0
  else
    return 1
  fi
}

function ymc_get_ptr_full_hostname_for_ip
{
  ip=$1
  full_ptr_hostname=$(dig -x "$ip" +short 2>/dev/null | sed -r 's/\.$//')

  if [ "$full_ptr_hostname" != '' ]; then
    echo $full_ptr_hostname
    return 0
  else
    return 1
  fi
}

function ymc_get_all_configured_ips
{
  LC_ALL=C /sbin/ifconfig | grep 'inet addr:' | sed -r 's/.*inet addr:([0-9.]+).*/\1/'
}

function ymc_get_all_configured_service_aliases
{
  network="$1"
  if [ -z "$network" ]; then
    network="lan"
  fi
  service_aliases=$(LC_ALL=C /sbin/ifconfig | grep -E -e '^'$network':S[0-9A-F]{8} ' | sed -r 's/^'$network':(S[0-9A-F]{8}).*/\1/')
  for service_alias in $service_aliases
  do
    if [ $(echo -n "$service_alias" | wc -c) -eq 9 ]; then
      echo $service_alias
    fi
  done
}

function ymc_get_all_configured_virtual_aliases
{
  virtual_aliases=$(LC_ALL=C /sbin/ifconfig | grep -E -e '^lo:V[0-9A-F]{8} ' | sed -r 's/^lo:(V[0-9A-F]{8}).*/\1/')
  for virtual_alias in $virtual_aliases
  do
    if [ $(echo -n "$virtual_alias" | wc -c) -eq 9 ]; then
      echo $virtual_alias
    fi
  done
}

### DEPRECATED - DO NOT USE 'ymc_get_all_configured_service_ids' ANY LONGER!
function ymc_get_all_configured_service_ids
{
  service_ids=$(LC_ALL=C /sbin/ifconfig | grep -E -e '^lan:[0-9]+ ' | sed -r 's/^lan:([1-9][0-9]*).*/\1/')
  for service_id in $service_ids
  do
    if [ $service_id -ge 1 ] && [ $service_id -le 199 ]; then
      echo $service_id
    fi
  done
}

### DEPRECATED - DO NOT USE 'ymc_get_all_configured_virtual_ids' ANY LONGER!
function ymc_get_all_configured_virtual_ids
{
  virtual_ids=$(LC_ALL=C /sbin/ifconfig | grep -E -e '^lo:' | sed -r 's/^lo:([A-F0-9]+) .*/\1/')
  for virtual_id in $virtual_ids
  do
    virtual_id=$(echo $virtual_id | sed -r 's/[^0-9ABCDEF]//g')
    if [ $(echo -n "$virtual_id" | wc -m) -ne 8 ]; then
      continue
    fi

    virtal_id_hex_parts=$(echo $virtual_id | sed -r 's/(..)/\1 /g')
    if [ $(echo -n "$virtal_id_hex_parts" | wc -w) -ne 4 ]; then
      continue
    fi

    valid_one=1

    for virtal_id_hex_part in $virtal_id_hex_part
    do
      virtal_id_dec_part=$(ymc_hex2dec $virtal_id_hex_part)
      if [ $virtal_id_dec_part -lt 0 ] || [ $virtal_id_dec_part -gt 255 ]; then
        valid_one=0
        break
      fi
    done
    if [ $valid_one -eq 1 ]; then
      echo $virtual_id
    fi
  done
}

################

function ymc_calculate_interface_alias_from_ipv4
{
  local ip="$1"
  local prefix="$2"
  local alias=''
  local alias_parts=$(echo $ip | cut -d '.' -f 1-4 --output-delimiter=' ')
  for alias_part in $alias_parts
  do
    if [ "$alias_part" == '' ] || [ $alias_part -lt 0 ] || [ $alias_part -gt 255 ]; then
      echo "ERROR: Could not calculate interface alias from IP '$ip'" 1>&2
      return 1
    else
      hex_alias_part=$(ymc_dec2hex $alias_part)
      if [ $(echo -n $hex_alias_part | wc -m) -lt 2 ]; then
        hex_alias_part='0'$hex_alias_part
      fi
      alias=$alias''$hex_alias_part
    fi
  done

  if [ -z "$alias" ] || \
     [ $(echo -n $alias | wc -c) -ne 8 ]; then
    echo "ERROR: Calculated an invalid alias '$prefix$alias' from IP '$ip' using prefix '$prefix'" 1>&2
    return 1
  fi

  echo $prefix$alias
  return 0
}

function ymc_calculate_service_alias
{
  ymc_calculate_interface_alias_from_ipv4 "$1" "S"
  return $?
}

function ymc_calculate_virtual_alias
{
  ymc_calculate_interface_alias_from_ipv4 "$1" "V"
  return $?
}

function ymc_calculate_heartbeat_alias
{
  ymc_calculate_interface_alias_from_ipv4 "$1" "H"
  return $?
}

### DEPRECATED - DO NOT USE 'ymc_caluclated_virtual_id' ANY LONGER!
function ymc_caluclated_virtual_id
{
  ymc_calculate_interface_alias_from_ipv4 "$1" ""
  return $?
}

### DEPRECATED - DO NOT USE 'ymc_caluclated_cluster_id' ANY LONGER!
function ymc_caluclated_cluster_id
{
  ### Get the cluster-id
  cluster_id=$(ymc_get_primary_ip_for_network lan | cut -d '.' -f 2)
  if [ "$cluster_id" == '' ] || [ $cluster_id -lt 100 ] || [ $cluster_id -gt 154 ]; then
    echo "ERROR: Could not calculate the cluster-id!" 1>&2
    return 1
  else
    echo $cluster_id
    return 0
  fi
}

### DEPRECATED - DO NOT USE 'ymc_caluclated_cluster_vpn_id' ANY LONGER!
function ymc_caluclated_cluster_vpn_id
{
  cluster_id=$(ymc_caluclated_cluster_id)
  if [ $? -ne 0 ] || [ "$cluster_id" == '' ]; then
    return 1
  fi

  ### ToDo: It's pretty evil to assume the $cluster_vpn_id is "$cluster_id + 100"...
  cluster_vpn_id=$(expr $cluster_id + 100)
  if [ $? -ne 0 ] || [ "$cluster_vpn_id" == '' ] || [ $cluster_vpn_id -gt 254 ]; then
    echo "WARNING: Could not calculate the cluster-vpn-id!" 1>&2
    return 1
  else
    echo $cluster_vpn_id
    return 0
  fi
}
################

function ymc_is_valid_cluster_hostname
{
  is_valid=$(echo $1 | grep -c -E -e '^[a-z]+[0-9]+-[a-z]+[0-9]+$')
  if [ $is_valid -ne 1 ]; then
   echo 0
   return 1
 else
   echo 1
   return 0
 fi
}

################

function ymc_get_host_password
{
  if [ ! -e "/boot/ymccluster/host.password" ]; then
    return 1
  fi
  host_password=$(cat /boot/ymccluster/host.password)
  if [ "$host_password" == "" ]; then
    return 1
  else
    echo -n -E "$host_password"
    return 0
  fi
}

function ymc_generate_new_host_password
{
  host_password=$(makepasswd --minchars=8 --maxchars=12 --count=1 --nocrypt --noverbose --string='abcdefghijklmnopqrstuvwxyz0123456789!.-_')
  if [ $? -ne 0 ] || [ "$host_password" == "" ]; then
    return 1
  else
    if [ ! -d "/boot/ymccluster" ]; then
      mkdir /boot/ymccluster
      if [ $? -ne 0 ]; then
        return 1
      fi
    fi
    echo -n -E "$host_password" > /boot/ymccluster/host.password
    if [ $? -ne 0 ]; then
      return 1
    fi
    ymc_get_host_password
    return $?
  fi
}

################

function ymc_get_config_from_dns
{
  variables_set=""
  config_key=$1             #REQUIRED
  if [ "$config_key" == '' ]; then
    return 1
  fi

  config_var_prefix=$(echo -n $config_key | sed -r 's/\./_dot_/g' | sed -r 's/-/_dash_/g')
  if [ "$config_var_prefix" == '' ]; then
    return 1
  fi

  if [ $(echo $config_var_prefix | grep -c -i -E -e "^[^a-z]") -ne 0 ]; then
    config_var_prefix="ymcvar_"$config_var_prefix
  fi

  if [ "$(ymc_var_value ymc_get_config_from_dns_caches_$config_var_prefix)" != '' ]; then
    txt_string=$(ymc_var_value "ymc_get_config_from_dns_caches_$config_var_prefix")
  else
    txt_string=$(dig ${DEBUG_DNS:+@$DEBUG_DNS} TXT "$config_key" +time=2 +short 2>/dev/null | sed -r 's/\\//g' | sed -r 's/^(.{256})" "/\1/' && exit ${PIPESTATUS[0]})
    if [ $? -ne 0 ] ||
       [ -z "$txt_string" ]; then
      return 1
    fi
    eval $(echo ymc_get_config_from_dns_caches_$config_var_prefix"='"$txt_string"'")
  fi

  infos=$(echo $txt_string | sed -r 's/^[^"]*"/"/' | sed -r 's/"[ ]+"/|/g' | sed -r 's/^"//' | sed -r 's/"$//')
  ymc_get_config_from_dns_org_IFS=$IFS
  IFS='|'
  for entries in $infos
  do
    ### replace ';' with ','
    entries=$(echo $entries | sed -r 's/;/,/g')

    ### wash the result before doing an 'eval'
    entries=$(ymc_wash $(ymc_trim $entries))
    if [  $(echo $entries | grep -c '=') -gt 0 ]; then
      eval $(echo $config_var_prefix"_"$entries"'" | sed -r "s/=/='/")
      variables_set=$variables_set" "$(echo $config_var_prefix"_"$entries | sed -r "s/=.*//")
    else
      if [ $(ymc_contains $config_var_prefix $variables_set) -eq 0 ]; then
        variables_set=$variables_set" "$(echo $config_var_prefix)
        eval $(echo $config_var_prefix'="''"')
      fi
      last_entries=$(ymc_var_value $config_var_prefix)
      eval $(echo $config_var_prefix'="'$last_entries' '$entries'"')
    fi
  done
  IFS=$ymc_get_config_from_dns_org_IFS
}

function ymc_var_value
{
  eval echo \$$(ymc_trim $(ymc_wash $1))
}

function ymc_set_var_content
{
  eval $(ymc_trim $(ymc_wash $1))="'"$2"'"
}

function ymc_get_local_short_hostname
{
  local_short_hostname=$(hostname -s 2>/dev/null)
  exit_code=0
  if [ $? -ne 0 ]; then
    echo "WARNING: Short hostname could not be determined - falling back to result of command hostname" 1>&2
    local_short_hostname=$(hostname)
    if [ $? -ne 0 ]; then
      echo "WARNING: Command hostname failed - falling back to content of /etc/hostname" 1>&2
      local_short_hostname=$(cat /etc/hostname)
      exit_code=$?
    fi
  fi
  echo $local_short_hostname
  return $exit_code
}

function ymc_get_local_full_hostname
{
  local_full_hostname=$(hostname -f 2>/dev/null)
  exit_code=0
  if [ $? -ne 0 ]; then
    echo "WARNING: Long hostname could not be determined - falling back to result of command hostname with appended '.cluster'" 1>&2
    local_full_hostname=$(hostname)'.cluster'
    if [ $? -ne 0 ]; then
      echo "WARNING: Command hostname failed - falling back to content of /etc/hostname with appended '.cluster'" 1>&2
      local_full_hostname=$(cat /etc/hostname)'.cluster'
      exit_code=$?
    fi
  fi
  echo $local_full_hostname
  return $exit_code
}

function ymc_get_network_config_from_dns
{
  hostname_to_lookup=$1     #OPTIONAL
  if [ "$hostname_to_lookup" == '' ]; then
    hostname_to_lookup=$(ymc_get_local_short_hostname)
  fi

  ymc_get_config_from_dns $hostname_to_lookup".network"
  if [ $? -ne 0 ]; then
    return 1
  fi
  hostname_to_lookup=$(echo $hostname_to_lookup | sed -r 's/\./_dot_/g' | sed -r 's/-/_dash_/g')
  for variable_set in $variables_set
  do
    eval $(echo $variable_set | sed -r "s/"$hostname_to_lookup"_dot_network_//")="$(eval 'echo \$$variable_set')"
  done
}

function ymc_get_all_networks_from_dns
{
  ymc_get_hostname_from_dns_txt networks cluster
  return $?
}

function ymc_get_mac_addresses_common
{
  interfaces=$1
  dashes=$2
  macs=''
  for interface in $interfaces
  do
    if [ -f "/sys/class/net/$interface/address" ]; then
      mac=$(cat /sys/class/net/$interface/address)
      if [ "$dashes" == '--dashes' ]; then
        mac=$(echo $mac | sed -r 's/:/-/g')
      fi
      macs=$macs"\n"$mac
    fi
  done
  if [ $(echo $macs | wc -w) -gt 0 ]; then
    echo -e $macs | grep -v -E -e "^[ ]*$" | sort | uniq | grep -v '00:00:00:00:00:00'
    return 0
  else
    return 1
  fi
}

function ymc_get_all_mac_addresses
{
  ymc_get_mac_addresses_common "$(ls /sys/class/net/)" $1
}

function ymc_get_real_mac_addresses
{
  ymc_get_mac_addresses_common "$(ymc_get_real_interfaces)" $1
}


function ymc_get_interfaces_common
{
  search_type=$1                       #Might be "address, device", "bonding" or "bridge"
  if [ -d "/sys/class/net" ]; then
    result=""
    for path in $(find /sys/class/net/*/$search_type -maxdepth 0 2>/dev/null)
    do
      result=$result" "$(basename $(dirname $path))
    done
    echo $result
    return 0
  else
    return 1
  fi
}


function ymc_get_all_interfaces
{
  echo $(ymc_get_interfaces_common address)
  return $?
}


function ymc_get_loopback_interfaces
{
  all_interfaces_with_type=$(ymc_get_interfaces_common type)
  return_code=$?
  result=""
  for interface in $all_interfaces_with_type
  do
    if [ $(cat /sys/class/net/$interface/type) -eq 772 ]; then
      result="$result $interface"
      return_code=0
    fi
  done
  echo $result
  return $return_code
}


function ymc_get_real_interfaces
{
  if [ $DEBUG_ALLOW_DUMMY_INTERFACES -ne 1 ]; then
    echo $(ymc_get_interfaces_common device)
    return $?
  else
    all_interfaces_with_type=$(ymc_get_interfaces_common type)
    return_code=$?
    result=""
    for interface in $all_interfaces_with_type
    do
      if [ $(cat /sys/class/net/$interface/type) -eq 1 ] && \
         [ $(ymc_contains $interface $(ymc_get_bridge_interfaces) $(ymc_get_bonding_interfaces)) -eq 0 ]; then
        result="$result $interface"
        return_code=0
      fi
    done
    echo $result
    return $return_code
  fi
}


function ymc_get_bonding_interfaces
{
  echo $(ymc_get_interfaces_common bonding)
  return $?
}


function ymc_get_bridge_interfaces
{
  echo $(ymc_get_interfaces_common bridge)
  return $?
}


function ymc_interface_exists
{
  interface=$1
  if [ -e "/sys/class/net/$interface/address" ]; then
    echo 1
    return 0
  else
    echo 0
    return 1
  fi
}


function ymc_get_field_from_ifconfig
{
  interface=$1
  field=$2
  result=''
  ifconfig_string=$(LC_ALL=C /sbin/ifconfig $interface 2>/dev/null)
  return_code=$?
  if [ $return_code -eq 0 ]; then
    ifconfig_string=$(echo $ifconfig_string)
    result=$(echo "$ifconfig_string"  | grep "$field" | perl -pi -e "s/.*$field([^\s]+).*/\$1/")
    if [ "$result" == '' ] || [ "$result" == "$ifconfig_string" ]; then
      result=""
      return_code=2
    fi
  fi
  echo -n "$result";
  return $return_code
}


##########################


function ymc_add_static_ip_entry_for_network
{
  interface_name=$1
  interface_address=$(eval "echo \$"$interface_name"_ip")
  interface_netmask=$(eval "echo \$"$interface_name"_netmask")
  interface_gateway=$(eval "echo \$"$interface_name"_gateway")
  interface_gateway_metric=$(eval "echo \$"$interface_name"_gateway_metric")
  interface_mtu=$(eval "echo \$"$interface_name"_mtu")
  echo "" >> /etc/network/interfaces
  echo "auto $interface_name" >> /etc/network/interfaces
  if [ "$interface_address" != 'dhcp' ] && \
     [ "$interface_netmask" != 'dhcp' ] && \
     [ "$interface_gateway" != 'dhcp' ]; then
    echo "iface $interface_name inet static" >> /etc/network/interfaces
    echo "  address $interface_address" >> /etc/network/interfaces
    echo "  netmask $interface_netmask" >> /etc/network/interfaces
    if [ "$interface_gateway" != '' ]; then
      echo "  gateway $interface_gateway" >> /etc/network/interfaces
      if [ -n "$interface_gateway_metric" ]; then
        echo "  metric $interface_gateway_metric" >> /etc/network/interfaces
      fi
    fi
    echo "  mtu $interface_mtu" >> /etc/network/interfaces
  else
    echo "iface $interface_name inet dhcp" >> /etc/network/interfaces
    if [ -n "$interface_gateway_metric" ]; then
      echo "  metric $interface_gateway_metric" >> /etc/network/interfaces
    fi
    echo "  post-up /usr/sbin/fliwi-update-resolvconf" >> /etc/network/interfaces
    echo "  post-down /usr/sbin/fliwi-update-resolvconf" >> /etc/network/interfaces
  fi
}

function ymc_add_vlan_id_for_interface
{
  local network_name=$1
  local interface_name=$2
  local vlan_id=$(eval "echo \$"$network_name"_vlan_id")
  local vlan_raw_device=$(eval "echo \$"$network_name"_vlan_raw_device_"$interface_name)
  if [ -n "$vlan_id" ] && \
     [ -n "$vlan_raw_device" ]; then
    echo "  fliwi-vlan-id $vlan_id" >> /etc/network/interfaces
    echo "  fliwi-vlan-raw-device $vlan_raw_device" >> /etc/network/interfaces
  fi
}


function ymc_rename_interfaces
{
  temp_if_rename_info=$(echo $*"," | sed -r 's/,+$/,/')
  if [ "$temp_if_rename_info" != '' ]; then
    echo "# Dynamic iftab(5) file for ifrename(8) generated by $(basename $0)" > /etc/iftab
    echo "#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN" >> /etc/iftab
    if [ $DEBUG_ALLOW_DUMMY_INTERFACES -eq 1 ]; then
      echo -e $temp_if_rename_info | sed -r "s/,/\n/g" >> /etc/iftab
    else
      echo -e $temp_if_rename_info | sed -r "s/,/ SYSFS{device\/driver} *\n/g" >> /etc/iftab
    fi
    if_rename_dry_run=$(LC_ALL=C ifrename -c /etc/iftab  -D 2>&1 | grep "Would rename" |sed -r 's/ /;/g')
    for if_rename_dry_run_item in $if_rename_dry_run
    do
      interface_to_rename=$(ymc_trim $(echo $if_rename_dry_run_item | sed -r 's/Dry-run;:;Would;rename;//' | sed -r 's/;to;.*$//'))
      if [ "$interface_to_rename" == '' ] || [ ! -d "/sys/class/net/$interface_to_rename" ]; then
        echo "ERROR: Tried to rename a none existing interface..."
        return 1
      fi

      if [ $ALLOW_NETWORK_DISRUPTION -eq 1 ]; then
        echo -n "Shutting down $interface_to_rename for rename operation..."
        /sbin/ifconfig $interface_to_rename down
        echo "DONE"
      else
        echo "INFO: Not shutting down '$interface_to_rename'. A renaming of this interface will not be possible..."
      fi
    done

    if [ $ALLOW_NETWORK_DISRUPTION -eq 1 ]; then
      echo -n "Renaming real interfaces..."
      ifrename -c /etc/iftab
      echo "DONE"
    else
      echo -n "Trying to rename real interfaces..."
      ifrename -c /etc/iftab
      if [ $? -eq 0 ]; then
        echo "DONE"
      else
        echo "FAILED"
      fi
    fi
      return 0
  else
    echo "Nothing done, as there are no renaming informations!"
    return 1
  fi
}


### LEGACY function - will be dropped out soon
function ymc_activate_interfaces
{
  networks=$*         #REQUIRED

  echo "# Dynamic interfaces(5) configuration for ifup(8) generated by $(basename $0)" > /etc/network/interfaces
  echo "#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN" >> /etc/network/interfaces
  echo "" >> /etc/network/interfaces
  echo "# The loopback network interface" >> /etc/network/interfaces
  echo "auto lo" >> /etc/network/interfaces
  echo "iface lo inet loopback" >> /etc/network/interfaces

  ymc_activate_vlan_raw_interfaces

  for network in $networks
  do
    network_layout=$(eval "echo \$"$network"_layout")
    if [ "$network_layout" == 'single' ]; then
      ymc_add_static_ip_entry_for_network $network
      ymc_add_vlan_id_for_interface $network $network
    else
      for interface in $(eval "echo \$"$network"_interfaces")
      do
        echo "" >> /etc/network/interfaces
        echo "auto $interface" >> /etc/network/interfaces
        echo "iface $interface inet manual" >> /etc/network/interfaces
        ymc_add_vlan_id_for_interface $network $interface
      done
    fi
  done
}

function ymc_write_interfaces_header
{
  echo "# Dynamic interfaces(5) configuration for ifup(8) generated by $(basename $0)" > /etc/network/interfaces
  echo "#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN" >> /etc/network/interfaces
  echo "" >> /etc/network/interfaces
  echo "# The loopback network interface" >> /etc/network/interfaces
  echo "auto lo" >> /etc/network/interfaces
  echo "iface lo inet loopback" >> /etc/network/interfaces
}

function ymc_activate_vlan_raw_interfaces
{
  if [ -n "$vlan_raw_interfaces" ]; then
    for vlan_raw_interface in $vlan_raw_interfaces
    do
      echo "" >> /etc/network/interfaces
      echo "auto $vlan_raw_interface" >> /etc/network/interfaces
      echo "iface $vlan_raw_interface inet manual" >> /etc/network/interfaces
    done
  fi
}

function ymc_activate_non_single_interfaces
{
  networks=$*         #REQUIRED

  for network in $networks
  do
    network_layout=$(eval "echo \$"$network"_layout")
    if [ "$network_layout" != 'single' ]; then
      for interface in $(eval "echo \$"$network"_interfaces")
      do
        echo "" >> /etc/network/interfaces
        echo "auto $interface" >> /etc/network/interfaces
        echo "iface $interface inet manual" >> /etc/network/interfaces
        ymc_add_vlan_id_for_interface $network $interface
      done
    fi
  done
}

function ymc_activate_single_interfaces
{
  networks=$*         #REQUIRED

  for network in $networks
  do
    network_layout=$(eval "echo \$"$network"_layout")
    if [ "$network_layout" == 'single' ]; then
      # Note: For single interfaces the network name is equal to the interface name
      ymc_add_static_ip_entry_for_network $network
      ymc_add_vlan_id_for_interface $network $network
    fi
  done
}



function ymc_preload_network_layouts
{
  network_name=$1     #required
  ymc_get_config_from_dns "$network_name.bonding"
  ymc_get_config_from_dns "$network_name.bonding.bridge"
}


function ymc_activate_bonding
{
  networks=$*         #REQUIRED

  if [ "$(ymc_get_bonding_interfaces)" != '' ] || \
     [ $(lsmod | grep -c -E -e '^bonding [0-9 ]+$') -gt 0 ]; then
    rmmod bonding
  fi

  if [ "$(ymc_get_bonding_interfaces)" != '' ]; then
    echo "ERROR: Couldn't configure bonding, as there seems to be already some kind of bonding set up..." 1>&2
    return 1
  fi

  valid_bondings_count=-1
  required_bondings_count=$valid_bondings_count
  bonding_options=''
  bonding_renames=''
  for network in $networks
  do
    network_layout=$(eval "echo \$"$network"_layout")
    if [ "$network_layout" != 'bonding' ] && \
       [ "$network_layout" != 'bonding_bridge' ]; then
      echo "Note: Not configuring any bonding for the '$network'-network, as the layout neither is 'bonding' nor 'bonding_bridge'..."
      continue
    else
      required_bondings_count=$(expr $required_bondings_count + 1)
    fi
    echo -n "Looking up basic bonding configuration for the '$network'-network..."
    if [ "$network_layout" == "bonding_bridge" ]; then
      ymc_get_config_from_dns "$network.bonding.bridge"
    else
      ymc_get_config_from_dns "$network.bonding"
    fi
    if [ $? -eq 0 ]; then
      echo "DONE"
      valid_bondings_count=$(expr $valid_bondings_count + 1)
      bonding_options[$valid_bondings_count]=''
      for variable_set in $variables_set
      do
        bonding_option=$(ymc_trim $(echo $variable_set"="$(eval "echo \$$variable_set") | sed -r "s/"$network"_dot_bonding_//" | sed -r "s/dot_bridge_//"))
        if [ $(echo "$bonding_option" | grep -c 'arp_ip_target') -gt 0 ]; then
          bonding_option=$(echo "$bonding_option" | sed -r 's/'$(eval "echo \$"$network"_ip" )'//' | sed -r 's/[,]+/,/g' | sed -r 's/=,+/=/' | sed -r 's/,$//' )
          echo "test|$bonding_option|"
        fi
        bonding_options[$valid_bondings_count]=${bonding_options[$valid_bondings_count]}" "$bonding_option
        if [ "$bonding_option" == 'mode=active-backup' ]; then
          active_backup_additional_options="primary="$(ymc_trim $(eval "echo \$"$network"_interfaces" | sed -r 's/ .*//'))
          active_backup_additional_options=$active_backup_additional_options" fail_over_mac=0"
          bonding_options[$valid_bondings_count]=${bonding_options[$valid_bondings_count]}" "$active_backup_additional_options
        fi
        bonding_options[$valid_bondings_count]=$(ymc_trim ${bonding_options[$valid_bondings_count]})
      done
      bonding_renames[$valid_bondings_count]=$network
    else
      echo "FAILED"
    fi
  done

  if [ $required_bondings_count -ne $valid_bondings_count ]; then
    echo "ERROR: Not all bondings have been configured, as there seems to be an invalid bonding configuration..." 1>&2
    return 1
  elif [ $valid_bondings_count -ge 0 ]; then
    if [ -f "/etc/modprobe.d/bonding" ]; then
      rm -f /etc/modprobe.d/bonding
    fi
    echo "# Dynamic bonding configuration for modprobe(8) generated by $(basename $0)" > /etc/modprobe.d/bonding.conf
    echo "#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN" >> /etc/modprobe.d/bonding.conf
    echo "options bonding max_bonds=$(expr $valid_bondings_count + 1)" >> /etc/modprobe.d/bonding.conf

    if [ $(lsmod | grep -c -E -e '^bonding [0-9 ]+$') -le 0 ]; then
      modprobe bonding
    fi

    i=0
    while [ $i -le $valid_bondings_count ]
    do
      network=${bonding_renames[i]}
      network_layout=$(eval "echo \$"$network"_layout")
      if [ "$network_layout" == 'bonding' ]; then
        interface_name=$network
        ymc_add_static_ip_entry_for_network $interface_name
      else
        interface_name=$network"_bond"
        echo "" >> /etc/network/interfaces
        echo "auto $interface_name" >> /etc/network/interfaces
        echo "iface $interface_name inet manual" >> /etc/network/interfaces
      fi

      echo "  slaves "$(eval "echo \$"${bonding_renames[i]}"_interfaces") >> /etc/network/interfaces
      for bonding_option in ${bonding_options[$i]}
      do
        echo '  bond_'"$(echo $bonding_option | sed -r 's/[=,]/ /g')" >> /etc/network/interfaces
      done

      ### Add rename info for bonding
      echo "$interface_name prevname bond$i" >> /etc/iftab
      i=$(expr $i + 1)
    done

    echo -n "Renaming bonding interfaces..."
    ifrename -c /etc/iftab
    echo "DONE"
  fi

  return 0
}

function ymc_activate_bridging
{
  networks=$*         #REQUIRED

  network_layout=$(eval "echo \$"$network"_layout")

  if [ $(lsmod | grep -c -E -e '^bridge [0-9 ]+$') -le 0 ]; then
    modprobe bridge
  fi

  if [ $ALLOW_NETWORK_DISRUPTION -eq 1 ]; then
    if [ "$(ymc_get_bridge_interfaces)" != '' ]; then
      for interface in $(ymc_get_bridge_interfaces)
      do
        /sbin/ifconfig $interface down
        brctl delbr $interface
      done
    fi

    if [ "$(ymc_get_bridge_interfaces)" != '' ]; then
      echo "ERROR: Couldn't configure bridging, as there seems to be already some kind of bridging set up..." 1>&2
      return 1
    fi
  elif [ "$(ymc_get_bridge_interfaces)" != '' ]; then
    echo "INFO: Not shutting down existing bridge-interfaces '$(ymc_get_bridge_interfaces)'..." 1>&2
  fi

  for network in $networks
  do
    network_layout=$(eval "echo \$"$network"_layout")

    if [ "$network_layout" != 'single_bridge' ] && \
       [ "$network_layout" != 'bonding_bridge' ]; then
      echo "Note: Not configuring any bridging for the '$network'-network, as the layout neither is 'single_bridge' nor 'bonding_bridge'..."
      continue
    fi

    interface_name=$network

    ymc_add_static_ip_entry_for_network $interface_name

    interfaces_var_name=$network'_interfaces'
    interfaces_to_use=$(ymc_var_value $interfaces_var_name)
    if [ "$network_layout" == 'bonding_bridge' ]; then
      echo "  bridge_ports "$interface_name"_bond" >> /etc/network/interfaces
    elif [ $(echo $interfaces_to_use | wc -w ) -gt 0 ]; then
      echo "  bridge_ports "$interfaces_to_use >> /etc/network/interfaces
    else
      echo "  bridge_ports none" >> /etc/network/interfaces
    fi
    echo "  bridge_stp off" >> /etc/network/interfaces
    echo "  bridge_maxwait 5" >> /etc/network/interfaces
  done
  return 0
}

##########################


function ymc_contains
{
  ymc_contains_org_IFS=$IFS
  IFS=' '
  needle=$1
  items=$*
  first_done=0
  for item in $items
  do
    if [ $first_done -eq 0 ]; then
      first_done=1
      continue
    fi
    if [ "$item" == "$needle" ]; then
      echo 1
      IFS=$ymc_contains_org_IFS
      return 0
    fi
  done
  echo 0
  IFS=$ymc_contains_org_IFS
  return 1
}

function ymc_trim
{
  echo "$*" | sed -r 's/^[ ]+//' | sed -r 's/[ ]+$//'
}


function ymc_wash
{
  ### Note: 'a-z' and 'A-Z' is not sufficient (as it might contains special-chars like german umlauts, too)
  echo "$*" | sed -r 's/[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0-9=_ .,:@#/!-]//g'
}

function ymc_is_chroot
{
  ### Borrowed from the postinst of the udev-package
  if [ "$(stat -c %d/%i /)" = "$(stat -Lc %d/%i /proc/1/root 2>/dev/null)" ];
  then
    # the devicenumber/inode pair of / is the same as that of /sbin/init's
    # root, so we're *not* in a chroot and hence return false.
    echo 0
    return 1
  fi
  echo 1
  return 0
}



##########################
function ymc_get_auto_network_config
{
  ### Get possibly existing config from dns...
  temp_valid_auto_config_found=0

  if [ $(lsof -i :53 | grep -c -E -e "^dnsmasq") -gt 0 ]; then
    echo "Found local DNS-server - trying to get configuration from this one..."
    DEBUG_DNS_ORG=$DEBUG_DNS
    DEBUG_DNS="127.0.0.1"
    echo -n "Looking up network-config from local DNS..."
    ymc_get_network_config_from_dns "$hostname"
    if [ $? -eq 0 ]; then
      all_networks=$(ymc_get_all_networks_from_dns)
      if [ $? -eq 0 ]; then
        echo "DONE"
        for all_network in $all_networks
        do
          ymc_preload_network_layouts $all_network
        done
        temp_valid_auto_config_found=1
      else
        echo "FAILED"
        DEBUG_DNS=$DEBUG_DNS_ORG
      fi
    else
      echo "FAILED"
      DEBUG_DNS=$DEBUG_DNS_ORG
    fi
  fi

  local is_installing_hostname=0

  if [ $temp_valid_auto_config_found -ne 1 ]; then
    echo -n "Looking up network-config..."
    ymc_get_network_config_from_dns "$hostname"
    if [ $? -ne 0 ]; then
      echo "FAILED"

      # Prefix lan before all other interfaces (if needed)
      all_real_interfaces="$(ymc_get_real_interfaces | sed -r 's/(.*) (lan[0-9]*)(.*)/\2 \1 \3/' | sed -r 's/ +/ /g' | sed -r 's/ $//')"

      if [ $ALLOW_NETWORK_DISRUPTION -eq 1 ]; then
        echo -n "Taking all real interfaces offline..."
        ### Take all real interfaces offline
        for interface in $all_real_interfaces
        do
          /sbin/ifconfig $interface down
        done
        echo "DONE"

        ### Try to get DHCP via each real interface
        for interface in $all_real_interfaces
        do
          echo -n "Trying to configure interface $interface using DHCP..."
          /sbin/ifconfig $interface 0.0.0.0 up
          /sbin/ip -family inet6 addr flush dev $interface
          dhclient -1 $interface 2>&1 | awk '{ printf "."; system("sleep 0.75"); }'
          if [ ${PIPESTATUS[0]} -eq 0 ]; then
            echo -ne "DONE"

            if [ "$hostname" = "installing-host" ]; then
              echo "INFO: Detected an installing host - updating hostname" 1>&2
              is_installing_hostname=1
              /usr/sbin/fliwi-update-hostname
              hostname=$(ymc_get_local_short_hostname)
            fi

            echo -n "Looking up network-config via $interface..."
            ymc_get_network_config_from_dns "$hostname"
            if [ $? -eq 0 ]; then
              all_networks=$(ymc_get_all_networks_from_dns)
              if [ $? -eq 0 ]; then
                for all_network in $all_networks
                do
                  ymc_preload_network_layouts $all_network
                done
                temp_valid_auto_config_found=1
              fi
              echo -n "Deconfiguring interface $interface..."
              /sbin/ifconfig $interface 0.0.0.0 up
              /sbin/ip -family inet6 addr flush dev $interface
              echo "DONE"

              echo -n "Taking interface $interface offline..."
              /sbin/ifconfig $interface down
              echo "DONE"
              break
            fi
            echo "FAILED"

            if [ $is_installing_hostname -eq 1 ]; then
              is_installing_hostname=0
              hostname="installing-host"
            fi

          else
            echo "FAILED"
          fi

          echo -n "Deconfiguring interface $interface..."
          /sbin/ifconfig $interface 0.0.0.0 up
          /sbin/ip -family inet6 addr flush dev $interface
          echo "DONE"

          echo -n "Taking interface $interface offline..."
          /sbin/ifconfig $interface down
          echo "DONE"
        done

        if [ $(ps -Af | grep dhclient | grep -v grep | wc -l) -gt 0 ]; then
          echo -n  "Stopping possibly running dhclient..."
          killall dhclient
          if [ $? -eq 0 ]; then
            echo "DONE"
          else
            echo "FAILED"
            echo -n  "KILLING still running dhclient..."
            killall -9 dhclient
            if [ $? -eq 0 ]; then
              echo "DONE"
            else
              echo "FAILED"
            fi
          fi
        fi
      fi
    else
      all_networks=$(ymc_get_all_networks_from_dns)
      if [ $? -eq 0 ]; then
        for all_network in $all_networks
        do
          ymc_preload_network_layouts $all_network
        done
        temp_valid_auto_config_found=1
      fi
    fi
  fi

  if [ $temp_valid_auto_config_found -ne 1 ]; then
    echo "ERROR: Stopping further processing, as no valid network configuration could be" 1>&2
    echo "       found and a local DNS-server isn't running..." 1>&2
    exit 1
  fi
  echo "DONE"
}
