----------------------------------------------------------------------------- }\r
unit binipstuff;\r
\r
+{$ifdef fpc}\r
+{$mode delphi}\r
+{$endif}\r
+\r
interface\r
\r
{$include lcoreconfig.inc}\r
\r
uses\r
-{$ifndef win32}\r
+{$ifndef mswindows}\r
sockets,\r
{$endif}\r
pgtypes;\r
\r
-{$ifdef fpc}\r
- {$mode delphi}\r
-{$endif}\r
-{$ifdef cpu386}{$define i386}{$endif}\r
-{$ifdef i386}{$define ENDIAN_LITTLE}{$endif}\r
+\r
+{$include pgtypes.inc}\r
\r
{$include uint32.inc}\r
\r
const\r
hexchars:array[0..15] of ansichar='0123456789abcdef';\r
- {$ifdef win32}\r
+ {$ifdef mswindows}\r
AF_INET=2;\r
AF_INET6=23;\r
{$else}\r
type\r
{$ifdef ipv6}\r
\r
- {$ifdef win32}\r
+ {$ifdef mswindows}\r
{$define want_Tin6_addr}\r
{$endif}\r
{$ifdef ver1_0}\r
{$endif}\r
end;\r
\r
- {$ifdef win32}\r
- TInetSockAddr = packed Record\r
- family:Word;\r
- port :Word;\r
- addr :uint32;\r
- pad :array [1..8] of byte;\r
- end;\r
- {$ifdef ipv6}\r
+ {zipplet 20170204: FPC 3.0.0 changed the definition of TInetSockAddr:\r
+ - http://www.freepascal.org/docs-html/rtl/sockets/tinetsockaddr.html\r
+ - http://www.freepascal.org/docs-html/rtl/sockets/sockaddr_in.html\r
+ Due to this, TInetSockAddr -> TLInetSockAddr4 / TLInetSockAddr6\r
+ Using our own types no matter what OS or compiler version will prevent future problems.\r
+ Adding "4" to non IPv6 record names improves code clarity }\r
\r
- TInetSockAddr6 = packed record\r
- sin6_family: word;\r
- sin6_port: word;\r
- sin6_flowinfo: uint32;\r
- sin6_addr: tin6_addr;\r
- sin6_scope_id: uint32;\r
- end;\r
+ {$ifndef mswindows}\r
+ //zipplet 20170204: Do we still need to support ver1_0? Perhaps a cleanup is in order.\r
+ //For now keep supporting it for compatibility.\r
+ {$ifdef ver1_0}\r
+ cuint16 = word;\r
+ cuint32 = dword;\r
+ sa_family_t = word;\r
{$endif}\r
{$endif}\r
\r
-\r
-\r
+ TLInetSockAddr4 = packed Record\r
+ family:Word;\r
+ port :Word;\r
+ addr :uint32;\r
+ pad :array [0..7] of byte; //zipplet 20170204 - originally this was 1..8 for some reason\r
+ end;\r
+ \r
{$ifdef ipv6}\r
- {$ifdef ver1_0}\r
- cuint16=word;\r
- cuint32=dword;\r
- sa_family_t=word;\r
-\r
- TInetSockAddr6 = packed record\r
- sin6_family: word;\r
- sin6_port: word;\r
- sin6_flowinfo: uint32;\r
- sin6_addr: tin6_addr;\r
- sin6_scope_id: uint32;\r
- end;\r
- {$endif}\r
+ TLInetSockAddr6 = packed record\r
+ sin6_family: word;\r
+ sin6_port: word;\r
+ sin6_flowinfo: uint32;\r
+ sin6_addr: tin6_addr;\r
+ sin6_scope_id: uint32;\r
+ end;\r
{$endif}\r
+\r
+ //zipplet 20170204: I did not rename the unioned record. We might want to rename this to TLinetSockAddrv\r
TinetSockAddrv = packed record\r
case integer of\r
- 0: (InAddr:TInetSockAddr);\r
+ 0: (InAddr:TLInetSockAddr4);\r
{$ifdef ipv6}\r
- 1: (InAddr6:TInetSockAddr6);\r
+ 1: (InAddr6:TLInetSockAddr6);\r
{$endif}\r
end;\r
Pinetsockaddrv = ^Tinetsockaddrv;\r
\r
type\r
- tsockaddrin=TInetSockAddr;\r
-\r
-\r
+ tsockaddrin=TLInetSockAddr4;\r
\r
{\r
bin IP list code, by beware\r
function makeinaddrv(addr:tbinip;port:ansistring;var inaddr:tinetsockaddrv):integer;\r
function inaddrsize(inaddr:tinetsockaddrv):integer;\r
\r
+function getbinipbitlength(const ip:tbinip):integer;\r
+function getipstrbitlength(const ip:thostname):integer;\r
+function getfamilybitlength(family:integer):integer;\r
+\r
implementation\r
\r
uses sysutils;\r
inAddr.InAddr.family:=AF_INET;\r
inAddr.InAddr.port:=htons(strtointdef(port,0));\r
inAddr.InAddr.addr:=addr.ip;\r
- result := sizeof(tinetsockaddr);\r
+ result := sizeof(tlinetsockaddr4);\r
end else\r
{$ifdef ipv6}\r
if addr.family = AF_INET6 then begin\r
inAddr.InAddr6.sin6_family:=AF_INET6;\r
inAddr.InAddr6.sin6_port:=htons(strtointdef(port,0));\r
inAddr.InAddr6.sin6_addr:=addr.ip6;\r
- result := sizeof(tinetsockaddr6);\r
+ result := sizeof(tlinetsockaddr6);\r
end;\r
{$endif}\r
end;\r
function inaddrsize(inaddr:tinetsockaddrv):integer;\r
begin\r
{$ifdef ipv6}\r
- if inaddr.inaddr.family = AF_INET6 then result := sizeof(tinetsockaddr6) else\r
+ if inaddr.inaddr.family = AF_INET6 then result := sizeof(tlinetsockaddr6) else\r
{$endif}\r
- result := sizeof(tinetsockaddr);\r
+ result := sizeof(tlinetsockaddr4);\r
end;\r
\r
{internal}\r
{$endif}\r
\r
{try v4}\r
- binip.ip := htonl(longip(s));\r
+ // zipplet: htonl() expects a uint32 but longip() spits out longint.\r
+ // Because longip() is deprecated, we do not fix it but typecast.\r
+ //binip.ip := htonl(longip(s));\r
+ binip.ip := htonl(uint32(longip(s)));\r
if (binip.ip <> 0) or (s = '0.0.0.0') then begin\r
result := true;\r
binip.family := AF_INET;\r
\r
- implementation does not depend on other ipv6 code such as the tin6_addr type,\r
the parameter can also be untyped.\r
-- it is host endian neutral - binary format is aways network order\r
+- it is host endian neutral - binary format is always network order\r
- it supports compression of zeroes\r
- it supports ::ffff:192.168.12.34 style addresses\r
- they are made to do the Right Thing, more efficient implementations are possible\r
end;\r
end;\r
\r
- {run length atleast 2 0 words}\r
+ {run length at least 2 0 words}\r
if (runlength = 1) then begin\r
runlength := 0;\r
runbegin := 0;\r
{$ifdef ipv6}\r
if ip.family = AF_INET then begin\r
ip.family := AF_INET6;\r
- ip.ip6.s6_addr32[3] := ip.ip; \r
- ip.ip6.u6_addr32[0] := 0; \r
+ ip.ip6.s6_addr32[3] := ip.ip;\r
+ ip.ip6.u6_addr32[0] := 0;\r
ip.ip6.u6_addr32[1] := 0;\r
ip.ip6.u6_addr16[4] := 0;\r
ip.ip6.u6_addr16[5] := $ffff;\r
end;\r
end;\r
\r
+function getfamilybitlength(family:integer):integer;\r
+begin\r
+ {$ifdef ipv6}\r
+ if family = AF_INET6 then result := 128 else\r
+ {$endif}\r
+ if family = AF_INET then result := 32\r
+ else result := 0;\r
+end;\r
+\r
+function getbinipbitlength(const ip:tbinip):integer;\r
+begin\r
+ result := getfamilybitlength(ip.family);\r
+end;\r
+\r
+function getipstrbitlength(const ip:thostname):integer;\r
+var\r
+ biniptemp:tbinip;\r
+begin\r
+ ipstrtobin(ip,biniptemp);\r
+ result := getbinipbitlength(biniptemp);\r
+end;\r
\r
end.\r