X-Git-Url: http://www.lcore.org/git/lcore.git/blobdiff_plain/095083d60a366c89e8bf240e35bd8315c5772c41..803cf6668d9e89c244e5fbc7f996a460470338dd:/lcorelocalips.pas diff --git a/lcorelocalips.pas b/lcorelocalips.pas index 453ce81..f1e87c1 100644 --- a/lcorelocalips.pas +++ b/lcorelocalips.pas @@ -71,24 +71,27 @@ implementation uses baseunix,unix,sockets,sysutils; +{$ifdef linux} function getlocalips_internal(wantfamily:integer):tbiniplist; const IF_NAMESIZE=16; + SIOCGIFCONF=$8912; - {$ifdef linux}SIOCGIFCONF=$8912;{$endif} - {$ifdef bsd}{$ifdef cpu386}SIOCGIFCONF=$C0086924;{$endif}{$endif} - - {amd64: mac OS X: $C00C6924; freeBSD: $c0106924} type tifconf=packed record - ifc_len:longint; + ifc_len:taddrint; ifcu_rec:pointer; end; tifrec=packed record ifr_ifrn:array [0..IF_NAMESIZE-1] of char; - ifru_addr:TSockAddr; + case integer of + 0: (ifru_addr: Tsockaddr); + {$ifdef cpu64} + //tifrec is 40 bytes on 64 bits due to a union with one of the other data types + 1: (sizefor64: array[0..23] of byte); + {$endif} end; var @@ -120,11 +123,11 @@ begin if (fpioctl(s,SIOCGIFCONF,@ifc) < 0) then begin raise exception.create('getv4localips ioctl failed'); end; - if (lastlen = ifc.ifc_len) then break; + if (lastlen = ifc.ifc_len) then break; lastlen := ifc.ifc_len; len := len * 2; until false; - + ifr2 := ifr; ifrmax := pointer(taddrint(ifr) + ifc.ifc_len); while (ifr2 < ifrmax) do begin @@ -133,10 +136,6 @@ begin {calculate len} ad := @ifr2.ifru_addr; - {$ifdef bsd} - len := ad.inaddr.len + IF_NAMESIZE; - if (len < sizeof(tifrec)) then - {$endif} len := sizeof(tifrec); if (len < sizeof(tifrec)) then break; {not enough left} @@ -150,14 +149,72 @@ begin FileClose(s); end; +{$endif} //linux + +{$ifdef bsd} + +type + pifaddrs = ^Tifaddrs; + Tifaddrs = record + ifa_next: pifaddrs; + ifa_name: pansichar; + ifa_flags: cuint; // Interface flags (IFF_UP, IFF_BROADCAST, etc.) + ifa_addr: Pinetsockaddrv; + ifa_netmask: psockaddr; + ifa_dstaddr: psockaddr; // union: Destination address (P-t-P) or broadcast address + ifa_data: Pointer; + end; + +const + IFF_UP=1; //interface is administratively enabled + +function getifaddrs(var ifap: pifaddrs): cint; cdecl; external 'c' name 'getifaddrs'; +function freeifaddrs(ifap: pifaddrs): cint; cdecl; external 'c' name 'freeifaddrs'; + + +function getlocalips_internal(wantfamily:integer):tbiniplist; +var + IfList: pifaddrs; + IfPtr: pifaddrs; + sa: PinetSockAddrV; +begin + result := biniplist_new; + + if getifaddrs(IfList) <> 0 then raise exception.create('getlocalips getifaddrs failed'); + + IfPtr := IfList; + while IfPtr <> nil do begin + if ((IfPtr^.ifa_flags and IFF_UP) <> 0) then begin + sa := IfPtr^.ifa_addr; + //if (sa <> nil) then writeln(sa^.inaddr.len,' ',sa^.inaddr.family); + + if (sa <> nil) and (sa^.inaddr.family = wantfamily) then begin + biniplist_add(result, inaddrvtobinip(sa^)); + end; + end; + IfPtr := IfPtr^.ifa_next; + end; + + freeifaddrs(IfList); +end; + +{$endif} //bsd + + {$ifdef ipv6} function getv6localips:tbiniplist; +{$ifndef bsd} var t:textfile; s,s2:ansistring; ip:tbinip; a:integer; +{$endif} begin + {$ifdef bsd} + result := getlocalips_internal(AF_INET6); + {$else} + //linux result := biniplist_new; assignfile(t,'/proc/net/if_inet6'); @@ -178,6 +235,7 @@ begin if ip.family <> 0 then biniplist_add(result,ip); end; closefile(t); + {$endif} end; {$endif} //ipv6