///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2019 Ericsson Telecom AB
//
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v2.0
// which accompanies this distribution, and is available at
// https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
//                                                                           
///////////////////////////////////////////////////////////////////////////////
//
//  File:               IPL4asp_Functions.ttcn
//  Rev:                R29B
//  Prodnr:             CNL 113 531
//  Updated:            2010-06-09
//  Contact:            http://ttcn.ericsson.se
//  Reference:          

module IPL4asp_Functions {

  import from IPL4asp_Types all;
  import from IPL4asp_PortType all;
  import from TCCInterface_Functions all;    

  function f_setUpInterface(
    in charstring startIPAddress, 
    in charstring netmask, 
    in charstring broadcast, 
    in integer count,
    in charstring ifname,
    in integer virtualIfaceStart
  ) {
    var ro_integer startIPAddress_Record := f_splitIpAddress(startIPAddress);
//    var ro_integer netmask_Record := f_splitIpAddress(netmask);
//    var ro_integer broadcast_Record := f_splitIpAddress(broadcast);
    
    for (var integer i := virtualIfaceStart ;
         i < virtualIfaceStart + count; i := i + 1) {
      f_setIP(ifname & ":" & int2str(i),
        f_presentIpAddress(startIPAddress_Record), netmask, broadcast);      
      f_nextIpAddress(startIPAddress_Record);
    }
  } // function f_setUpInterface
  
  function f_setDownInterface(
    in charstring ifname,
    in integer count,
    in integer virtualIfaceStart
  ) {
    for (var integer i :=virtualIfaceStart;
         i < virtualIfaceStart + count; i := i + 1) {                       
      f_deleteIP(ifname & ":" & int2str(i));
    }
  } // function f_setDownInterface

function f_hasColon(in charstring str) return boolean{
  if (not isvalue(str)){return false};
  for (var integer i:=0;i<lengthof(str);i:=i+1){
    if (str[i] == ":"){return true;}
  }
  return false;
}

function f_tokenizeIP(in charstring addr) return ro_charstring{
  var ro_charstring tokens := {}
  var charstring l_delim := ".";
  if (f_hasColon(addr)){l_delim := ":"}
  var charstring l_token := "";
  var integer addrlen := lengthof(addr);
  for (var integer i:=0; i < addrlen; i:=i+1)
  {
    if (addr[i] == l_delim){
      tokens[sizeof(tokens)] := l_token;
      l_token := "";
    }else{
      l_token := l_token & addr[i];
    }
  }
  if (l_token != "") {
    tokens[sizeof(tokens)] := l_token;
  }
  return tokens;
}

function f_splitIpAddress(
  in charstring addr
) return ro_integer {
  var ro_integer segAddr := {};
  var ro_charstring ip := f_tokenizeIP(addr);
  if (f_hasColon(addr)){
    // assume IPv6
    var integer i:=0;
    while (ip[i] != ""){
      segAddr[i] := hex2int(str2hex(ip[i]));
      i := i+1;
      if(i==sizeof(ip)){
        return segAddr;
      }
    }
    var integer memo := i+1;
    var integer zs := 8-sizeof(ip)+1;
    for (var integer k:=i;k<zs+i;k:=k+1){
      segAddr[k] := 0;
    }
    i:=i+zs;
    while(i<8 and memo<sizeof(ip)){
      segAddr[i] := hex2int(str2hex(ip[memo]));
      i:= i+1; memo := memo+1;
    }
  } else {
    // assume IPv4
    for (var integer i := 0; i < 4; i := i + 1) {
      segAddr[i] := str2int(ip[i]);
    }
  }
  
  return segAddr;
}   
  
  function f_presentIpAddress(in ro_integer addr) return charstring {
    if (sizeof(addr) == 4) { // IPv4
      return int2str(addr[0]) & "." &
             int2str(addr[1]) & "." &
             int2str(addr[2]) & "." &
             int2str(addr[3]);
    } else { // IPv6
      return hex2str(int2hex(addr[0], 4)) & ":" &
             hex2str(int2hex(addr[1], 4)) & ":" &
             hex2str(int2hex(addr[2], 4)) & ":" &
             hex2str(int2hex(addr[3], 4)) & ":" &    
             hex2str(int2hex(addr[4], 4)) & ":" &    
             hex2str(int2hex(addr[5], 4)) & ":" &    
             hex2str(int2hex(addr[6], 4)) & ":" &    
             hex2str(int2hex(addr[7], 4));
    }
  } // f_presentIpAddress
  
  
  
  function f_nextIpAddress(
    inout ro_integer addr
  ) { // BEWARE: The caller is responsible that the resulting address makes sense!!!
    var integer n := sizeof(addr);
    var integer segMax := 255;
    if (n == 8) {
      segMax := 65535;
    }

    for (var integer i := n - 1; i >= 0; i := i - 1) {
      if (addr[i] < segMax) {
        addr[i] := addr[i] + 1;
        goto ConvertAddressDone;
      } else {
        addr[i] := 0;
      }
    }    
    label ConvertAddressDone;
  } // function f_nextAddress


  external function f_findIpAddressesWithDhcp (
    inout IPL4asp_PT portRef,
    in charstring expIfName,
    in charstring expIfIpAddress,
    in charstring exclIfIpAddress,
    in charstring ethernetAddress,
    in integer leaseTime,
    in charstring leaseFile,
    in integer nOfAddresses,
    out ro_charstring ipAddresses,
    out charstring netMask,
    out charstring broadcastAddr,
    out charstring ifName
    ) return boolean;

  external function f_releaseIpAddressesFromDhcp (
    inout IPL4asp_PT portRef
    ) return boolean;

  external function f_findIpAddressesWithARP (
    inout IPL4asp_PT portRef,
    in charstring expIfName,
    in charstring expIfIpAddress,
    in charstring exclIfIpAddress,
    in integer nOfAddresses,
    out ro_charstring ipAddresses,
    out charstring netMask,
    out charstring broadcastAddr,
    out charstring ifName
    ) return boolean;

  external function f_findIpAddresses (
    inout IPL4asp_PT portRef,
    out ro_charstring ipAddresses,
    out charstring netMask,
    out charstring broadcastAddr,
    out charstring ifName
    ) return boolean;

} // module IPL4asp_Functions