This here is a collection of tools that a Network Administrator will
find useful. It calculates subnet masks, IP address ranges and number
of hosts that the subnet can have. One that does IPv4 address and
another that does IPv6 addresses.
It uses win32 api functions to convert IP addresses into their
integer form and back into a string. The IPv6 will require windows xp
or higher
More free tools available at http://www.delphijustin.biz
program ipcalc; //IPv4 Calculator {$APPTYPE Console} {$RESOURCE ipcalc32.res} uses SysUtils, windows, winsock, math, Classes; var ip,subnet:string; dummy1:twsadata; aip,asubnet,wildcard,sip,eip,cip:dword; nip1,nip2:array[1..4]of byte; i:integer; label TryAgain,validmask; begin if wsastartup($101,dummy1)<>0 then begin writeln('Error initializing winsock'); exitprocess(1); end; TryAgain: write('Enter IP Address:');readln(ip); aip := inet_addr(pchar(ip)); write('Enter subnet mask or prefix:'); readln(subnet); asubnet:=inet_addr(pchar(subnet)); //write('Enter prefix or leave blank:'); //readln(range); if strscan(Pchar(subnet),'.')=nil then begin copymemory(@nip1,@asubnet,4); asubnet:=Trunc(IntPower(2,nip1[4])-1); end else begin for i:= 7 to 31 do if intpower(2,i)-1=asubnet then goto validmask; write('Invalid Subnet mask! Try again(Yes/No)?'); readln(ip); if strscan(pchar(uppercase(ip)),'Y')<>nil then goto tryagain; end; validmask: writeln('Subnet Mask:',inet_ntoa(in_addr(asubnet))); wildcard:=not asubnet; copymemory(@nip1,@wildcard,4); nip2[4]:=nip1[1]; nip2[3]:=nip1[2]; nip2[2]:=nip1[3]; nip2[1]:=nip1[4]; copymemory(@cip,@nip2,4); sip:=aip and asubnet; eip:=sip+wildcard; writeln('Wildcard Mask:',inet_ntoa(in_addr(wildcard))); writeln('Starting Address:',inet_ntoa(in_addr(sip))); writeln('Ending Address:',inet_ntoa(in_addr(eip))); writeln('Max. Hosts:',cip); //writeln('Class: ',getipclass(sip)); write('Try again(Yes/No)?'); readln(ip); if strscan(PChar(Uppercase(ip)),'Y')<>nil then goto TryAgain; wsacleanup; end.
program ipcalc6; //IPv6 Calculator {$APPTYPE Console} {$RESOURCE ipcalc632.res} uses SysUtils, windows, Classes; type TIN6_ADDR=array[0..15]of byte; function RtlIpv6StringToAddressExA(astr:pchar;var address:tin6_addr;scope, port:pointer):longint;stdcall;external 'ntdll.dll'; function RtlIpv6AddressToStringExA(var address:tin6_addr;scope,port:integer; astr:pchar;len:PDWord):longint;stdcall;external 'ntdll.dll'; var ip,swcint:string; aip,subnet,sip,eip,wildcard:tin6_addr; bip,sSubnet,sSip,sEip,sWildcard:array[0..255] of char; scope,cb,sum:dword; i,prefix:integer; port:word; ce:byte; wcint:int64; function AddWithCarry(a,b:byte;var c:byte):byte; begin result:=(a xor b)xor c; c:=(a and b)or(c and(a xor b)); end; begin ce:=0; write('Enter IPv6 Address:'); //ask for a ip address readln(ip); write('Enter Subnet Prefix:'); //ask for the subnet prefix readln(prefix); zeromemory(@subnet,16); if prefix>0 then subnet[0]:=subnet[0] or 128;//1 //bit setting on subnet mask if prefix>1 then subnet[0]:=subnet[0] or 64;//2 if prefix>2 then subnet[0]:=subnet[0] or 32;//3 if prefix>3 then subnet[0]:=subnet[0] or 16;//4 if prefix>4 then subnet[0]:=subnet[0] or 8;//5 if prefix>5 then subnet[0]:=subnet[0] or 4;//6 if prefix>6 then subnet[0]:=subnet[0] or 2;//7 if prefix>7 then subnet[0]:=subnet[0] or 1;//8 if prefix>8 then subnet[1]:=subnet[1] or 128;//1 if prefix>9 then subnet[1]:=subnet[1] or 64;//2 if prefix>10 then subnet[1]:=subnet[1] or 32;//3 if prefix>11 then subnet[1]:=subnet[1] or 16;//4 if prefix>12 then subnet[1]:=subnet[1] or 8;//5 if prefix>13 then subnet[1]:=subnet[1] or 4;//6 if prefix>14 then subnet[1]:=subnet[1] or 2;//7 if prefix>15 then subnet[1]:=subnet[1] or 1;//8 if prefix>16 then subnet[2]:=subnet[2] or 128;//1 if prefix>17 then subnet[2]:=subnet[2] or 64;//2 if prefix>18 then subnet[2]:=subnet[2] or 32;//3 if prefix>19 then subnet[2]:=subnet[2] or 16;//4 if prefix>20 then subnet[2]:=subnet[2] or 8;//5 if prefix>21 then subnet[2]:=subnet[2] or 4;//6 if prefix>22 then subnet[2]:=subnet[2] or 2;//7 if prefix>23 then subnet[2]:=subnet[2] or 1;//8 if prefix>24 then subnet[3]:=subnet[3] or 128;//1 if prefix>25 then subnet[3]:=subnet[3] or 64;//2 if prefix>26 then subnet[3]:=subnet[3] or 32;//3 if prefix>27 then subnet[3]:=subnet[3] or 16;//4 if prefix>28 then subnet[3]:=subnet[3] or 8;//5 if prefix>29 then subnet[3]:=subnet[3] or 4;//6 if prefix>30 then subnet[3]:=subnet[3] or 2;//7 if prefix>31 then subnet[3]:=subnet[3] or 1;//8 if prefix>32 then subnet[4]:=subnet[4] or 128;//1 if prefix>33 then subnet[4]:=subnet[4] or 64;//2 if prefix>34 then subnet[4]:=subnet[4] or 32;//3 if prefix>35 then subnet[4]:=subnet[4] or 16;//4 if prefix>36 then subnet[4]:=subnet[4] or 8;//5 if prefix>37 then subnet[4]:=subnet[4] or 4;//6 if prefix>38 then subnet[4]:=subnet[4] or 2;//7 if prefix>39 then subnet[4]:=subnet[4] or 1;//8 if prefix>40 then subnet[5]:=subnet[5] or 128;//1 if prefix>41 then subnet[5]:=subnet[5] or 64;//2 if prefix>42 then subnet[5]:=subnet[5] or 32;//3 if prefix>43 then subnet[5]:=subnet[5] or 16;//4 if prefix>44 then subnet[5]:=subnet[5] or 8;//5 if prefix>45 then subnet[5]:=subnet[5] or 4;//6 if prefix>46 then subnet[5]:=subnet[5] or 2;//7 if prefix>47 then subnet[5]:=subnet[5] or 1;//8 if prefix>48 then subnet[6]:=subnet[6] or 128;//1 if prefix>49 then subnet[6]:=subnet[6] or 64;//2 if prefix>50 then subnet[6]:=subnet[6] or 32;//3 if prefix>51 then subnet[6]:=subnet[6] or 16;//4 if prefix>52 then subnet[6]:=subnet[6] or 8;//5 if prefix>53 then subnet[6]:=subnet[6] or 4;//6 if prefix>54 then subnet[6]:=subnet[6] or 2;//7 if prefix>55 then subnet[6]:=subnet[6] or 1;//8 if prefix>56 then subnet[7]:=subnet[7] or 128;//1 if prefix>57 then subnet[7]:=subnet[7] or 64;//2 if prefix>58 then subnet[7]:=subnet[7] or 32;//3 if prefix>59 then subnet[7]:=subnet[7] or 16;//4 if prefix>60 then subnet[7]:=subnet[7] or 8;//5 if prefix>61 then subnet[7]:=subnet[7] or 4;//6 if prefix>62 then subnet[7]:=subnet[7] or 2;//7 if prefix>63 then subnet[7]:=subnet[7] or 1;//8 if prefix>64 then subnet[8]:=subnet[8] or 128;//1 if prefix>65 then subnet[8]:=subnet[8] or 64;//2 if prefix>66 then subnet[8]:=subnet[8] or 32;//3 if prefix>67 then subnet[8]:=subnet[8] or 16;//4 if prefix>68 then subnet[8]:=subnet[8] or 8;//5 if prefix>69 then subnet[8]:=subnet[8] or 4;//6 if prefix>70 then subnet[8]:=subnet[8] or 2;//7 if prefix>71 then subnet[8]:=subnet[8] or 1;//8 if prefix>72 then subnet[9]:=subnet[9] or 128;//1 if prefix>73 then subnet[9]:=subnet[9] or 64;//2 if prefix>74 then subnet[9]:=subnet[9] or 32;//3 if prefix>75 then subnet[9]:=subnet[9] or 16;//4 if prefix>76 then subnet[9]:=subnet[9] or 8;//5 if prefix>77 then subnet[9]:=subnet[9] or 4;//6 if prefix>78 then subnet[9]:=subnet[9] or 2;//7 if prefix>79 then subnet[9]:=subnet[9] or 1;//8 if prefix>80 then subnet[10]:=subnet[10] or 128;//1 if prefix>81 then subnet[10]:=subnet[10] or 64;//2 if prefix>82 then subnet[10]:=subnet[10] or 32;//3 if prefix>83 then subnet[10]:=subnet[10] or 16;//4 if prefix>84 then subnet[10]:=subnet[10] or 8;//5 if prefix>85 then subnet[10]:=subnet[10] or 4;//6 if prefix>86 then subnet[10]:=subnet[10] or 2;//7 if prefix>87 then subnet[10]:=subnet[10] or 1;//8 if prefix>88 then subnet[11]:=subnet[11] or 128;//1 if prefix>89 then subnet[11]:=subnet[11] or 64;//2 if prefix>90 then subnet[11]:=subnet[11] or 32;//3 if prefix>91 then subnet[11]:=subnet[11] or 16;//4 if prefix>92 then subnet[11]:=subnet[11] or 8;//5 if prefix>93 then subnet[11]:=subnet[11] or 4;//6 if prefix>94 then subnet[11]:=subnet[11] or 2;//7 if prefix>95 then subnet[11]:=subnet[11] or 1;//8 if prefix>96 then subnet[12]:=subnet[12] or 128;//1 if prefix>97 then subnet[12]:=subnet[12] or 64;//2 if prefix>98 then subnet[12]:=subnet[12] or 32;//3 if prefix>99 then subnet[12]:=subnet[12] or 16;//4 if prefix>100 then subnet[12]:=subnet[12] or 8;//5 if prefix>101 then subnet[12]:=subnet[12] or 4;//6 if prefix>102 then subnet[12]:=subnet[12] or 2;//7 if prefix>103 then subnet[12]:=subnet[12] or 1;//8 if prefix>104 then subnet[13]:=subnet[13] or 128;//1 if prefix>105 then subnet[13]:=subnet[13] or 64;//2 if prefix>106 then subnet[13]:=subnet[13] or 32;//3 if prefix>107 then subnet[13]:=subnet[13] or 16;//4 if prefix>108 then subnet[13]:=subnet[13] or 8;//5 if prefix>109 then subnet[13]:=subnet[13] or 4;//6 if prefix>110 then subnet[13]:=subnet[13] or 2;//7 if prefix>111 then subnet[13]:=subnet[13] or 1;//8 if prefix>112 then subnet[14]:=subnet[14] or 128;//1 if prefix>113 then subnet[14]:=subnet[14] or 64;//2 if prefix>114 then subnet[14]:=subnet[14] or 32;//3 if prefix>115 then subnet[14]:=subnet[14] or 16;//4 if prefix>116 then subnet[14]:=subnet[14] or 8;//5 if prefix>117 then subnet[14]:=subnet[14] or 4;//6 if prefix>118 then subnet[14]:=subnet[14] or 2;//7 if prefix>119 then subnet[14]:=subnet[14] or 1;//8 if prefix>120 then subnet[15]:=subnet[15] or 128;//1 if prefix>121 then subnet[15]:=subnet[15] or 64;//2 if prefix>122 then subnet[15]:=subnet[15] or 32;//3 if prefix>123 then subnet[15]:=subnet[15] or 16;//4 if prefix>124 then subnet[15]:=subnet[15] or 8;//5 if prefix>125 then subnet[15]:=subnet[15] or 4;//6 if prefix>126 then subnet[15]:=subnet[15] or 2;//7 if prefix>127 then subnet[15]:=subnet[15] or 1;//8 rtlipv6stringtoaddressexa(pchar(ip),aip,@scope,@port); //Convert a IP adresss in the string to a binary for i:=0to 15 do begin//generates the wildcard mask and start and end addresses wildcard[i]:=not subnet[i]; sip[i]:=aip[i] and subnet[i]; eip[i]:=addwithcarry(sip[i],wildcard[i],ce); end; cb:=256; rtlipv6addresstostringexa(subnet,0,0,sSubnet,@cb);//convert subnet to string cb:=256; rtlipv6addresstostringexa(aip,0,0,bip,@cb);//convert ending address to string writeln('IPv6 Address(short): ',bip); writeln('IPv6 Address(long): ',inttohex(aip[0],2),inttohex(aip[1],2),':', inttohex(aip[2],2),inttohex(aip[3],2),':',inttohex(aip[4],2),inttohex(aip[5],2) ,':',inttohex(aip[6],2),inttohex(aip[7],2),':',inttohex(aip[8],2), inttohex(aip[9],2),':',inttohex(aip[10],2),inttohex(aip[11],2),':', inttohex(aip[12],2),inttohex(aip[13],2),':', inttohex(aip[14],2),inttohex(aip[15],2)); writeln('ScopeID:',scope); writeln('Port:',port); writeln('Microsoft Address: ',stringreplace(bip,':','-',[rfReplaceAll])+ '.ipv6-literal.net'); sum:=0; for i:=0to 15 do sum:=sum+aip[i]; if sum*aip[15]=1 then Writeln('This is a loopback address'); write('Is part of a Local Unicast Network:'); if (aip[0]>$fb)and(aip[0]<$fe)then write('Yes')else write('No'); writeln(''); write('Is link-local address:'); if (aip[0]=$fe)and(aip[1]=$80)then write('Yes')else write('No'); writeln(''); write('Prefix L bit:'); if aip[0] and 128>0 then Write('Yes')else write('No'); writeln(''); write('GlobalID:$'); for i:=1to 5 do write(inttohex(aip[i],2)); writeln(''); write('Subnet ID:$'); for i:=6to 7 do write(Inttohex(aip[i],2)); writeln(''); write('Interface ID:$'); for i:=8 to 15 do write(inttohex(aip[i],2)); writeln(''); cb:=256; rtlipv6addresstostringexa(wildcard,0,0,sWildcard,@cb); writeln('Subnet Mask: ',sSubnet); if strscan(sWildCard,'.')=nil then swcint:=strpas(sWildCard)else begin swcint:=inttohex(wildcard[0],2)+inttohex(wildcard[1],2)+':'+ inttohex(wildcard[2],2)+inttohex(wildcard[3],2)+':'+ inttohex(wildcard[4],2)+inttohex(wildcard[5],2)+':'+ inttohex(wildcard[6],2)+inttohex(wildcard[7],2)+':'+ inttohex(wildcard[8],2)+inttohex(wildcard[9],2)+':'+ inttohex(wildcard[10],2)+inttohex(wildcard[11],2)+':'+ inttohex(wildcard[12],2)+inttohex(wildcard[13],2)+':'+ inttohex(wildcard[14],2)+inttohex(wildcard[15],2); end; writeln('Wildcard Mask: ',swcint); swcint:=stringreplace(swildcard,':','',[rfReplaceAll]); cb:=256; rtlipv6addresstostringexa(sip,0,0,ssip,@cb); writeln('Starting Address: ',ssip); cb:=256; rtlipv6addresstostringexa(eip,0,0,seip,@cb); writeln('Ending Address: ',seip); wcint:=StrToInt64Def('$'+swcint,-1); if wcint>-1 then writeln('Max. Hosts: ',wcint)else writeln('Max. Hosts: Overflow'); writeln('Press enter to exit...'); readln(ip); end.