mirror of
https://github.com/rejetto/hfs2.git
synced 2025-12-19 18:13:46 +01:00
better ipv6 support
This commit is contained in:
parent
72b28af2e1
commit
45f389691d
@ -370,6 +370,8 @@ function isLocalIP(ip:string):boolean;
|
|||||||
var
|
var
|
||||||
r: record d,c,b,a:byte end;
|
r: record d,c,b,a:byte end;
|
||||||
begin
|
begin
|
||||||
|
if ip = '::1' then
|
||||||
|
exit(TRUE);
|
||||||
dword(r):=WSocket_ntohl(WSocket_inet_addr(ansiString(ip)));
|
dword(r):=WSocket_ntohl(WSocket_inet_addr(ansiString(ip)));
|
||||||
result:=(r.a in [0,10,23,127])
|
result:=(r.a in [0,10,23,127])
|
||||||
or (r.a = 192) and ((r.b = 168) or (r.b = 0) and (r.c = 2))
|
or (r.a = 192) and ((r.b = 168) or (r.b = 0) and (r.c = 2))
|
||||||
@ -670,6 +672,7 @@ try
|
|||||||
P_port:=sock.getxport();
|
P_port:=sock.getxport();
|
||||||
result:=TRUE;
|
result:=TRUE;
|
||||||
|
|
||||||
|
if onAddress = '*' then
|
||||||
try
|
try
|
||||||
sock.MultiListenSockets.Clear();
|
sock.MultiListenSockets.Clear();
|
||||||
with sock.MultiListenSockets.Add do
|
with sock.MultiListenSockets.Add do
|
||||||
|
|||||||
55
main.pas
55
main.pas
@ -4256,6 +4256,13 @@ while i < srv.conns.count do
|
|||||||
end;
|
end;
|
||||||
end; // kickBannedOnes
|
end; // kickBannedOnes
|
||||||
|
|
||||||
|
function getAcceptOptions():TstringDynArray;
|
||||||
|
begin
|
||||||
|
result:=listToArray(localIPlist(sfAny));
|
||||||
|
addUniqueString('127.0.0.1', result);
|
||||||
|
addUniqueString('::1', result);
|
||||||
|
end; // getAcceptOptions
|
||||||
|
|
||||||
function startServer():boolean;
|
function startServer():boolean;
|
||||||
|
|
||||||
procedure tryPorts(list:array of string);
|
procedure tryPorts(list:array of string);
|
||||||
@ -4273,7 +4280,7 @@ begin
|
|||||||
result:=FALSE;
|
result:=FALSE;
|
||||||
if srv.active then exit; // fail if already active
|
if srv.active then exit; // fail if already active
|
||||||
|
|
||||||
if (localIPlist.IndexOf(listenOn) < 0) and (listenOn <> '127.0.0.1') then
|
if not stringExists(listenOn, getAcceptOptions()) then
|
||||||
listenOn:='';
|
listenOn:='';
|
||||||
|
|
||||||
if port > '' then
|
if port > '' then
|
||||||
@ -5911,19 +5918,16 @@ end; // httpEvent
|
|||||||
|
|
||||||
procedure findSimilarIP(fromIP:string);
|
procedure findSimilarIP(fromIP:string);
|
||||||
|
|
||||||
function howManySameNumbers(ip1,ip2:string):integer;
|
function howManySameChars(ip1,ip2:string):integer;
|
||||||
var
|
var
|
||||||
n1, n2: string;
|
i,n: integer;
|
||||||
begin
|
begin
|
||||||
result:=0;
|
i:=1;
|
||||||
while ip1 > '' do
|
n:=min(length(ip1),length(ip2));
|
||||||
begin
|
while (i<=n) and (ip1[i] = ip2[i]) do
|
||||||
n1:=chop('.',ip1);
|
inc(i);
|
||||||
n2:=chop('.',ip2);
|
result:=i-1;
|
||||||
if n1 <> n2 then exit;
|
end; // howManySameChars
|
||||||
inc(result);
|
|
||||||
end;
|
|
||||||
end; // howManySameNumbers
|
|
||||||
|
|
||||||
var
|
var
|
||||||
chosen: string;
|
chosen: string;
|
||||||
@ -5937,9 +5941,9 @@ if stringExists(fromIP, customIPs) then
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
chosen:=getIP();
|
chosen:=getIP();
|
||||||
a:=getIPs();
|
a:=getAcceptOptions();
|
||||||
for i:=0 to length(a)-1 do
|
for i:=0 to length(a)-1 do
|
||||||
if howManySameNumbers(chosen, fromIP) < howManySameNumbers(a[i], fromIP) then
|
if howManySameChars(chosen, fromIP) < howManySameChars(a[i], fromIP) then
|
||||||
chosen:=a[i];
|
chosen:=a[i];
|
||||||
setDefaultIP(chosen);
|
setDefaultIP(chosen);
|
||||||
end; // findSimilarIP
|
end; // findSimilarIP
|
||||||
@ -7878,7 +7882,7 @@ var
|
|||||||
procedure every10sec();
|
procedure every10sec();
|
||||||
var
|
var
|
||||||
s: string;
|
s: string;
|
||||||
ss: Tstrings;
|
ss: TstringDynArray;
|
||||||
begin
|
begin
|
||||||
if not stringExists(defaultIP, getPossibleAddresses()) then
|
if not stringExists(defaultIP, getPossibleAddresses()) then
|
||||||
// previous address not available anymore (it happens using dial-up)
|
// previous address not available anymore (it happens using dial-up)
|
||||||
@ -7891,10 +7895,10 @@ var
|
|||||||
s:=getIP();
|
s:=getIP();
|
||||||
if not isLocalIP(s) then // clearly better
|
if not isLocalIP(s) then // clearly better
|
||||||
setDefaultIP(s)
|
setDefaultIP(s)
|
||||||
else if ansiStartsStr('169', defaultIP) then // we consider the 169 worst of other locals
|
else if ansiStartsStr('169.', defaultIP) then // we consider the 169 worst of other locals
|
||||||
begin
|
begin
|
||||||
ss:=LocalIPList();
|
ss:=getAcceptOptions();
|
||||||
if ss.count > 1 then
|
if length(ss) > 1 then
|
||||||
setDefaultIP(ss[ if_(ss[0]=defaultIP, 1, 0) ]);
|
setDefaultIP(ss[ if_(ss[0]=defaultIP, 1, 0) ]);
|
||||||
end;;
|
end;;
|
||||||
end;
|
end;
|
||||||
@ -8209,25 +8213,24 @@ CONST
|
|||||||
INDEX_FOR_NIC = 1;
|
INDEX_FOR_NIC = 1;
|
||||||
var
|
var
|
||||||
a: TStringDynArray;
|
a: TStringDynArray;
|
||||||
i: integer;
|
s: string;
|
||||||
begin
|
begin
|
||||||
while IPaddress1.Items[INDEX_FOR_URL].Caption <> '-' do
|
while IPaddress1.Items[INDEX_FOR_URL].Caption <> '-' do
|
||||||
IPaddress1.delete(INDEX_FOR_URL);
|
IPaddress1.delete(INDEX_FOR_URL);
|
||||||
// fill 'IP address' menu
|
// fill 'IP address' menu
|
||||||
a:=getPossibleAddresses();
|
a:=getPossibleAddresses();
|
||||||
for i:=0 to length(a)-1 do
|
for s in a do
|
||||||
mainfrm.IPaddress1.Insert(INDEX_FOR_URL,
|
mainfrm.IPaddress1.Insert(INDEX_FOR_URL,
|
||||||
newItem(a[i], 0, a[i]=defaultIP, TRUE, ipmenuclick, 0, '') );
|
newItem(s, 0, s=defaultIP, TRUE, ipmenuclick, 0, '') );
|
||||||
|
|
||||||
// fill 'Accept connections on' menu
|
// fill 'Accept connections on' menu
|
||||||
while Acceptconnectionson1.count > INDEX_FOR_NIC do
|
while Acceptconnectionson1.count > INDEX_FOR_NIC do
|
||||||
Acceptconnectionson1.delete(INDEX_FOR_NIC);
|
Acceptconnectionson1.delete(INDEX_FOR_NIC);
|
||||||
Anyaddress1.checked:= listenOn = '';
|
Anyaddress1.checked:= listenOn = '';
|
||||||
a:=listToArray(localIPlist);
|
a:=getAcceptOptions();
|
||||||
addUniqueString('127.0.0.1', a);
|
for s in a do
|
||||||
for i:=0 to length(a)-1 do
|
|
||||||
Acceptconnectionson1.Insert(INDEX_FOR_NIC,
|
Acceptconnectionson1.Insert(INDEX_FOR_NIC,
|
||||||
newItem( a[i], 0, a[i]=listenOn, TRUE, acceptOnMenuclick, 0, '') );
|
newItem( s, 0, s=listenOn, TRUE, acceptOnMenuclick, 0, '') );
|
||||||
end; // refreshIPlist
|
end; // refreshIPlist
|
||||||
|
|
||||||
procedure TmainFrm.filesBoxDblClick(Sender: TObject);
|
procedure TmainFrm.filesBoxDblClick(Sender: TObject);
|
||||||
@ -11361,7 +11364,7 @@ resourcestring
|
|||||||
// we many need to try this specific test more than once
|
// we many need to try this specific test more than once
|
||||||
repeat
|
repeat
|
||||||
t:=now();
|
t:=now();
|
||||||
try result:=httpGet(SELF_TEST_URL+'?port='+port+'&host='+host+'&natted='+YESNO[localIPlist.IndexOf(externalIP)<0] )
|
try result:=httpGet(SELF_TEST_URL+'?port='+port+'&host='+host+'&natted='+YESNO[not stringExists(externalIP, getAcceptOptions())] )
|
||||||
except break end;
|
except break end;
|
||||||
t:=now()-t;
|
t:=now()-t;
|
||||||
if (result ='') or (result[1] <> '4') or progFrm.cancelRequested then break;
|
if (result ='') or (result[1] <> '4') or progFrm.cancelRequested then break;
|
||||||
|
|||||||
149
utillib.pas
149
utillib.pas
@ -82,11 +82,10 @@ function smartsize(size:int64):string;
|
|||||||
function httpGet(url:string; from:int64=0; size:int64=-1):string;
|
function httpGet(url:string; from:int64=0; size:int64=-1):string;
|
||||||
function httpGetFile(url, filename:string; tryTimes:integer=1; notify:TdocDataEvent=NIL):boolean;
|
function httpGetFile(url, filename:string; tryTimes:integer=1; notify:TdocDataEvent=NIL):boolean;
|
||||||
function httpFileSize(url:string):int64;
|
function httpFileSize(url:string):int64;
|
||||||
function getIPs():TStringDynArray;
|
|
||||||
function getPossibleAddresses():TstringDynArray;
|
function getPossibleAddresses():TstringDynArray;
|
||||||
function whatStatusPanel(statusbar:Tstatusbar; x:integer):integer;
|
function whatStatusPanel(statusbar:Tstatusbar; x:integer):integer;
|
||||||
function getExternalAddress(var res:string; provider:Pstring=NIL):boolean;
|
function getExternalAddress(var res:string; provider:Pstring=NIL):boolean;
|
||||||
function checkAddressSyntax(address:string; wildcards:boolean=TRUE):boolean;
|
function checkAddressSyntax(address:string; mask:boolean=TRUE):boolean;
|
||||||
function inputQueryLong(const caption, msg:string; var value:string; ofs:integer=0):boolean;
|
function inputQueryLong(const caption, msg:string; var value:string; ofs:integer=0):boolean;
|
||||||
procedure purgeVFSaccounts();
|
procedure purgeVFSaccounts();
|
||||||
function exec(cmd:string; pars:string=''; showCmd:integer=SW_SHOW):boolean;
|
function exec(cmd:string; pars:string=''; showCmd:integer=SW_SHOW):boolean;
|
||||||
@ -1378,56 +1377,72 @@ while mask > '' do
|
|||||||
result:=result xor odd(invert);
|
result:=result xor odd(invert);
|
||||||
end; // filematch
|
end; // filematch
|
||||||
|
|
||||||
function checkAddressSyntax(address:string; wildcards:boolean=TRUE):boolean;
|
function checkAddressSyntax(address:string; mask:boolean=TRUE):boolean;
|
||||||
var
|
var
|
||||||
a1, a2: string;
|
a1, a2: string;
|
||||||
i, dots, lastDot: integer;
|
sf: TSocketFamily;
|
||||||
wildcardsMet: boolean;
|
|
||||||
|
|
||||||
function validNumber():boolean;
|
|
||||||
begin result:=strToIntDef(substr(a1,lastDot+1,i-1), 0) <= 255 end;
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
if not mask then
|
||||||
|
exit(WSocketIsIPEx(address, sf));
|
||||||
result:=FALSE;
|
result:=FALSE;
|
||||||
if address = '' then exit;
|
while (address > '') and (address[1] = '\') do
|
||||||
while (address > '') and (address[1] = '\') do delete(address,1,1);
|
delete(address,1,1);
|
||||||
while address > '' do
|
while address > '' do
|
||||||
begin
|
begin
|
||||||
a2:=chop(';', address);
|
a2:=chop(';', address);
|
||||||
if sameText(a2, 'lan') then continue;
|
if sameText(a2, 'lan') then
|
||||||
|
continue;
|
||||||
a1:=chop('-', a2);
|
a1:=chop('-', a2);
|
||||||
if a2 > '' then
|
if a2 > '' then
|
||||||
if not checkAddressSyntax(a1, FALSE)
|
if not checkAddressSyntax(a1, FALSE)
|
||||||
or not checkAddressSyntax(a2, FALSE) then
|
or not checkAddressSyntax(a2, FALSE) then
|
||||||
exit;
|
exit;
|
||||||
wildcardsMet:=FALSE;
|
if reMatch(a1, '^[?*a-f0-9\.:]+$', '!') = 0 then
|
||||||
dots:=0;
|
exit;
|
||||||
lastDot:=0;
|
|
||||||
for i:=1 to length(a1) do
|
|
||||||
case a1[i] of
|
|
||||||
'.':
|
|
||||||
begin
|
|
||||||
if not validNumber() then exit;
|
|
||||||
lastDot:=i;
|
|
||||||
inc(dots);
|
|
||||||
end;
|
end;
|
||||||
'0'..'9': ;
|
result:=TRUE;
|
||||||
'?','*' : if wildcards then wildcardsMet:=TRUE else exit;
|
|
||||||
else exit;
|
|
||||||
end;
|
|
||||||
if (dots > 3) or not wildcardsMet and (dots <> 3) then exit;
|
|
||||||
end;
|
|
||||||
result:=validNumber();
|
|
||||||
end; // checkAddressSyntax
|
end; // checkAddressSyntax
|
||||||
|
|
||||||
|
function ipv6hex(ip:TIcsIPv6Address):string;
|
||||||
|
begin
|
||||||
|
setLength(result, 4*8);
|
||||||
|
binToHex(@ip.words[0], pchar(result), sizeOf(ip))
|
||||||
|
end;
|
||||||
|
|
||||||
function addressMatch(mask, address:string):boolean;
|
function addressMatch(mask, address:string):boolean;
|
||||||
var
|
var
|
||||||
invert: boolean;
|
invert: boolean;
|
||||||
part1, part2: string;
|
addr4: dword;
|
||||||
addrInt: dword;
|
addr6: string;
|
||||||
ofs, i, bits: integer;
|
bits: integer;
|
||||||
masks: TStringDynArray;
|
a: TStringDynArray;
|
||||||
mode: (SINGLE, BITMASK, RANGE);
|
|
||||||
|
function ipv6fix(s:string):string;
|
||||||
|
var
|
||||||
|
ok: boolean;
|
||||||
|
r: TIcsIPv6Address;
|
||||||
|
begin
|
||||||
|
if length(s) = 39 then
|
||||||
|
exit(replaceStr(s,':',''));
|
||||||
|
r:=wsocketStrToipv6(s, ok);
|
||||||
|
if ok then
|
||||||
|
exit(ipv6hex(r));
|
||||||
|
exit('');
|
||||||
|
end;
|
||||||
|
|
||||||
|
function ipv6range():boolean;
|
||||||
|
var
|
||||||
|
min, max: string;
|
||||||
|
begin
|
||||||
|
min:=ipv6fix(a[0]);
|
||||||
|
if min = ''then
|
||||||
|
exit(FALSE);
|
||||||
|
max:=ipv6fix(a[1]);
|
||||||
|
if max = '' then
|
||||||
|
exit(FALSE);
|
||||||
|
result:=(min <= addr6) and (max >= addr6)
|
||||||
|
end; // ipv6range
|
||||||
|
|
||||||
begin
|
begin
|
||||||
result:=FALSE;
|
result:=FALSE;
|
||||||
invert:=FALSE;
|
invert:=FALSE;
|
||||||
@ -1436,39 +1451,45 @@ while (mask > '') and (mask[1] = '\') do
|
|||||||
delete(mask,1,1);
|
delete(mask,1,1);
|
||||||
invert:=not invert;
|
invert:=not invert;
|
||||||
end;
|
end;
|
||||||
addrInt:=ipToInt(address);
|
addr6:=ipv6fix(address);
|
||||||
masks:=split(';',mask);
|
addr4:=0;
|
||||||
ofs:=1;
|
if addr6 = '' then
|
||||||
while not result and (ofs <= length(mask)) do
|
addr4:=ipToInt(address);
|
||||||
|
for mask in split(';',mask) do
|
||||||
begin
|
begin
|
||||||
mode:=SINGLE;
|
if result then
|
||||||
part1:=trim(substr(mask, ofs, max(0,posEx(';', mask, ofs)-1) ));
|
break;
|
||||||
inc(ofs, length(part1)+1);
|
if sameText(mask, 'lan') then
|
||||||
|
|
||||||
if sameText(part1, 'lan') then
|
|
||||||
begin
|
begin
|
||||||
result:=isLocalIP(address);
|
result:=isLocalIP(address);
|
||||||
continue;
|
continue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
i:=lastDelimiter('-/', part1);
|
// range?
|
||||||
if i > 0 then
|
a:=split('-', mask);
|
||||||
|
if length(a) = 2 then
|
||||||
begin
|
begin
|
||||||
if part1[i] = '-' then mode:=RANGE
|
if addr6 > '' then
|
||||||
else mode:=BITMASK;
|
result:=ipv6range()
|
||||||
part2:=part1;
|
else
|
||||||
part1:=chop(i, 1, part2);
|
result:=(addr4 >= ipToInt(a[0])) and (addr4 <= ipToInt(a[1]));
|
||||||
|
continue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
case mode of
|
// bitmask? ipv4 only
|
||||||
SINGLE: result:=match( pchar(part1), pchar(address) ) > 0;
|
a:=split('/', mask);
|
||||||
RANGE: result:=(addrInt >= ipToInt(part1)) and (addrInt <= ipToInt(part2));
|
if (addr6='') and (length(a) = 2) then
|
||||||
BITMASK:
|
begin
|
||||||
try
|
try
|
||||||
bits:=32-strToInt(part2);
|
bits:=32-strToInt(a[1]);
|
||||||
result:=addrInt shr bits = ipToInt(part1) shr bits;
|
result:=addr4 shr bits = ipToInt(a[0]) shr bits;
|
||||||
except end;
|
except
|
||||||
end;
|
end;
|
||||||
|
continue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// single
|
||||||
|
result:=match( pchar(mask), pchar(address) ) > 0;
|
||||||
end;
|
end;
|
||||||
result:=result xor invert;
|
result:=result xor invert;
|
||||||
end; // addressMatch
|
end; // addressMatch
|
||||||
@ -1757,10 +1778,12 @@ s:=trim(s);
|
|||||||
if s = '' then exit;
|
if s = '' then exit;
|
||||||
// try to determine length
|
// try to determine length
|
||||||
i:=1;
|
i:=1;
|
||||||
while (i < length(s)) and (i < 15) and charInSet(s[i+1], ['0'..'9','.']) do inc(i);
|
while (i < length(s)) and (i < 15) and charInSet(s[i+1], ['0'..'9','.']) do
|
||||||
while (i > 0) and (s[i] = '.') do dec(i);
|
inc(i);
|
||||||
|
while (i > 0) and (s[i] = '.') do
|
||||||
|
dec(i);
|
||||||
setLength(s,i);
|
setLength(s,i);
|
||||||
result:= checkAddressSyntax(s) and not HSlib.isLocalIP(s);
|
result:= checkAddressSyntax(s, FALSE) and not HSlib.isLocalIP(s);
|
||||||
if not result then exit;
|
if not result then exit;
|
||||||
if (res <> s) and mainFrm.logOtherEventsChk.checked then
|
if (res <> s) and mainFrm.logOtherEventsChk.checked then
|
||||||
mainFrm.add2log('New external address: '+s+' via '+hostFromURL(addr));
|
mainFrm.add2log('New external address: '+s+' via '+hostFromURL(addr));
|
||||||
@ -1780,17 +1803,13 @@ while (x > x1) and (result < statusbar.Panels.Count-1) do
|
|||||||
end;
|
end;
|
||||||
end; // whatStatusPanel
|
end; // whatStatusPanel
|
||||||
|
|
||||||
function getIPs():TStringDynArray;
|
|
||||||
begin
|
|
||||||
try result:=listToArray(localIPlist) except result:=NIL end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function getPossibleAddresses():TstringDynArray;
|
function getPossibleAddresses():TstringDynArray;
|
||||||
begin // next best
|
begin // next best
|
||||||
result:=toSA([defaultIP, dyndns.host]);
|
result:=toSA([defaultIP, dyndns.host]);
|
||||||
addArray(result, customIPs);
|
addArray(result, customIPs);
|
||||||
addString(externalIP, result);
|
addString(externalIP, result);
|
||||||
addArray(result, getIPs());
|
try addArray(result, listToArray(localIPlist(sfAny)))
|
||||||
|
except end;
|
||||||
removeStrings('', result);
|
removeStrings('', result);
|
||||||
uniqueStrings(result);
|
uniqueStrings(result);
|
||||||
end; // getPossibleAddresses
|
end; // getPossibleAddresses
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user