; 
;;=====================================================================================----- 
; 
;FUNCTION      IsInSubnet() 
; 
;ACTION        Checks if a given IP address is in a specified subnet 
; 
;AUTHOR        Jens Meyer 
; 
;VERSION       2.2 -  
; 
;HISTORY       1.1 - 2001/12/03 - Initial Release 
;              2.0 - 2003/08/18 - Complete rewrite, removed all dependencies, 
;                                 added support for array of network IDs and 
;                                 subnet masks, added return options. Fully 
;                                 backward compatible with version 1.1. 
;              2.1 -            - Fixed a problem if only a single networkID/subnetmask 
;                                 combination was provided as the second parameter. 
;              2.2 -            - Fixed a problem with CIDRs smaller than 10, added 
;                                 IP address validation. 
; 
;SYNTAX        IsInSubnet(IPADDRESS, NETWORKID [,SUBNETMASK, RETURN]) 
; 
;PARAMETERS    IPADDRESS - Required - String  
;              - Contains the IP address 
; 
;              NETWORKID - Required - String  
;              - Contains a networkid or a string/array of network ID/subnet mask 
; 
;              SUBNETMASK - Optional - String  
;              - Contains a subnet mask (octets or CIDR) if the network 
;              ID is a string. The subnetmask is not rquired when providing a 
;              string/array of network ID/subnet mask 
; 
;              RETURN - Optional - Integer 
;              - Controls return options when providing an array of network 
;              IDs/subnet masks 
;              1 = IP address is in ANY of the provided networks 
;              2 = IP address is in ALL of the provided networks 
; 
;REMARKS       based on code provided in the KiXgolf MOAN() tournament on the KiXtart BBS 
; 
;DEPENDENCIES  none 
; 
;RETURNS       1 if IP address is part of any/all networks, otherwise 0. Alternatively, 
;              if an array of networks is provided, it returns an array of 1/0 corresponding 
;              to the input array of networks. 
; 
;EXAMPLES      $ip='10.10.10.1' 
;              $networkid='10.10.10.0' 
;              $subnetmask='255.255.255.0' 
;              $answer = isinsubnet($ip,$networkid,$subnetmask) 
;              ? 'Error = '+@ERROR+ ' - '+@SERROR 
;              ? 'IsInSubnet = '+$answer 
;              redim $networkid[2] 
;              $ip='10.10.10.1' 
;              $networkid[0]='10.10.10.0/24' 
;              $networkid[1]='10.10.10.0/27' 
;              $networkid[2]='10.10.0.0/255.255.0.0' 
;              $answer = isinsubnet($ip,$networkid) 
;              $answer = isinsubnet($ip,$networkid,,1) 
;              $answer = isinsubnet($ip,$networkid,,2) 
; 
;KIXTART BBS   http://www.kixtart.org/ubbthreads/showflat.php?Cat=&Number=81873 
; 
function isinsubnet($ip,$network, optional $subnetmask, optional $bin)
  dim $a, $b, $c, $, $e, $f, $g, $h, $m[32]
  
  ; convert IP address to array 
  if vartype($ip) & 8192
    exit 87
  endif
 
  ; check whether IP addresses are in correct format 
  if ubound(split($ip,'.'))<>3
    exit 87
  endif
  
  ; check for valid IP address range 
  $a=split($ip,'.')
  for each $b in $a
    if $b<>1*$b or 0>$b or 255<$b
      exit 87
    endif
  next
 
  ; check for network ID format and extract subnet masks if necessary 
  select
  case vartype($network) & 8192
    $subnetmask=$network
    for $a=0 to ubound($network)
      $b=split($network[$a],'/')
      if ubound($b)<>1
        exit 87
      endif
      if ubound(split($b[0],'.'))<>3
        exit 87
      endif
 
      $network[$a]=$b[0]
      $subnetmask[$a]=$b[1]
    next
  case instr($network,'/')
    $network=split($network,'/')
    $subnetmask=split($network[1],'')
    $network=split($network[0],'')
  case ubound(split($network,'.'))<>3
    exit 87
  case 1
    $network=split($network,'')
  endselect
 
  ; convert subnetmask address to array 
  if not (vartype($subnetmask) & 8192)
    $subnetmask=split($subnetmask,'')
  endif
 
  ;Begin build mask array (Howard Bullock) 
  $f=0,128,192,224,240,248,252,254,255
  for $e=0 to 32
    Dim $h
    $=$e
    for $g=1 to 4
      $h=''+$h+iif($/8,'255',$f[$ mod 8])+iif($g<4,'.','')
      $=iif($>8,$-8,0)
    next
    $m[$e]=$h
  next
  ;End build mask array 
 
  ; convert CIDR addresses into octets 
  for $a=0 to ubound($subnetmask)
    $b=$subnetmask[$a]
    if not instr($b,'.')
      if 0<=$b and 32>=$b
        $subnetmask[$a]=$m[$subnetmask[$a]]
      else
        exit 87
      endif
    endif
  next
 
  ; check whether IP & SubnetMask = NetworkID 
  $ = ubound($network)
  redim $isinsubnet[$]
  $b=split($ip,'.')
  for $c=0 to $
    $e=split($network[$c],'.')
    $f=split($subnetmask[$c],'.')
 
    $g=0
    for $h=0 to 3
      $g = $g + ((val($b[$h]) & val($f[$h]))=val($e[$h]))
    next
    $isinsubnet[$c]=($g=4) + $isinsubnet[$c]
  next
 
  ; convert array back to string value if only one networkid/subnetmask address provided 
  select
  case $=0
    $isinsubnet=$isinsubnet[0]
  case val($bin)=1
    $isinsubnet=(ascan($isinsubnet,1)>-1)
  case val($bin)=2
    $isinsubnet=(instr(join($isinsubnet,''),'0')=0)
  endselect
endfunction