function ipValid(adr) {
  var oct,r,i;
  oct = adr.split(".");
  r = new Boolean(true);

  if (oct.length != 4) {
    r=false;
  } else {
    for (i=0; i<4; i++) {
      if (oct[i]<0 || oct[i]>255) {
        r=false;
  } } }
  return r;
}

function snValid(adr) {
  var oct,r,i;
  oct = adr.split(".");
  r = new Boolean(true);;

  for (i=0;i< 4; i++) {
    if ((Math.log(256 - oct[i]) / Math.log(2)) % 1 != 0) {
      r=false;
  } }
  return r;
}

function slValid(adr) {
  var r;
  if (isNaN(adr)) {
    r=false;
  } else {
    r=(adr>=0 && adr<33)
  }
  return r;
}


function sl2sn(adr) {
  var oct,t,i;
  oct = new Array(4);
  t = adr;

  for (i=3; i>=0; i--) {
    if ((t/8)>1) {
      oct[i]=255;
      t=t-8;
    } else {
      if (t==0) {
        oct[i]=0;
      } else {
        oct[i]=256-Math.pow(2,(8-(t%8))%8);
        t=0;
      }
    }
  }
  return oct[3]+"."+oct[2]+"."+oct[1]+"."+oct[0];
}



function sn2sl(adr) {
  var oct,r,t,i,j;
  oct = adr.split(".");
  r = 0;

  for (i=0; i<4; i++) {
    t = oct[i];
    for (j=7; j>=0; j--) {
      if (Math.floor(t/Math.pow(2,j))==1) {
        r++;
        t=t%Math.pow(2,j);
      } else {
        return r;
  } } }
  return r;
}

function d2o(dec) {
  var oct,i;

  if (dec<0 || dec>=Math.pow(256,4)) {
    return "invalid decimal number";
  }

  oct = new Array(4);
  for (i=0; i<4; i++) {
    oct[i]=dec%256;
    dec=Math.floor(dec/256);
  }
  return oct[3]+"."+oct[2]+"."+oct[1]+"."+oct[0];
}

function o2d(adr) {
  var oct,i,r;

  oct = adr.split(".");
  r = 0;

  if (oct.length == 4) {
    for (i=0; i<4; i++) {
      if (oct[i] > 255) {
        return "invalid ip";
      } else {
        r+=oct[3-i]*Math.pow(256,i);
      }
    }
  } else {
    return "invalid ip";
  }
  return r;

}

function adrand(adr1, adr2) {
  var oct1,oct2,oct3,i

  oct1 = adr1.split(".");
  oct2 = adr2.split(".");
  oct3 = new Array(4);

  for (i=0; i<4; i++) {
    oct3[i]=oct1[i]&oct2[i];
  }
  return oct3[0]+"."+oct3[1]+"."+oct3[2]+"."+oct3[3];

}


function doCalc() {
  var adr,msk,sub;
  var net,bro,hsf,hsl,hsc;

  adr=document.form.adr.value;
  msk=document.form.msk.value;

  document.form.sub.value="";
  document.form.bro.value=""
  document.form.hsf.value="";
  document.form.hsl.value="";
  document.form.hsc.value="";

  if (ipValid(adr)) {
    if (snValid(msk)) {
      msk = sn2sl(msk);
    } else {
      if (!slValid(msk)) {
        document.form.network.value = "invalid mask";
        return(false);
      }
    }
    hsc = Math.pow(2,32-msk)-2;
    document.form.hsc.value = hsc;
    sub = sl2sn(msk);
    document.form.sub.value = sub;
    if (msk != 32) {
      net = adrand(adr,sub);
      bro = d2o(o2d(net)+hsc+1);
      if (msk <= 30) {
        document.form.hsf.value = d2o(o2d(net)+1);
        document.form.hsl.value = d2o(o2d(bro)-1);
      }
    } else {
      net=adr;
    }

  } else {
    document.form.network.value="invalid ip";
    return(false);
  }
  document.form.net.value=net+"/"+msk;
  document.form.sub.value=sub;
  document.form.bro.value=bro;
  return(false);
}