FreeBSD support
[lcore.git] / lcorelocalips.pas
index 07752ca5b55184cf630a8aac69b0e6fb0eeb8068..f1e87c12f85d1f6a00278bccf0443991de6f9797 100644 (file)
@@ -71,15 +71,13 @@ implementation
 uses\r
   baseunix,unix,sockets,sysutils;\r
 \r
+{$ifdef linux}\r
 \r
 function getlocalips_internal(wantfamily:integer):tbiniplist;\r
 const\r
   IF_NAMESIZE=16;\r
+  SIOCGIFCONF=$8912;\r
 \r
-  {$ifdef linux}SIOCGIFCONF=$8912;{$endif}\r
-  {$ifdef bsd}{$ifdef cpu386}SIOCGIFCONF=$C0086924;{$endif}{$endif}\r
-\r
-  {amd64: mac OS X: $C00C6924; freeBSD: $c0106924}\r
 type\r
   tifconf=packed record\r
     ifc_len:taddrint;\r
@@ -125,11 +123,11 @@ begin
     if (fpioctl(s,SIOCGIFCONF,@ifc) < 0) then begin\r
       raise exception.create('getv4localips ioctl failed');\r
     end;\r
-    if (lastlen = ifc.ifc_len) then break; \r
+    if (lastlen = ifc.ifc_len) then break;\r
     lastlen := ifc.ifc_len;\r
     len := len * 2;\r
   until false;\r
-  \r
+\r
   ifr2 := ifr;\r
   ifrmax := pointer(taddrint(ifr) + ifc.ifc_len);\r
   while (ifr2 < ifrmax) do begin\r
@@ -138,10 +136,6 @@ begin
     {calculate len}\r
     ad := @ifr2.ifru_addr;\r
 \r
-    {$ifdef bsd}\r
-    len := ad.inaddr.len + IF_NAMESIZE;\r
-    if (len < sizeof(tifrec)) then \r
-    {$endif}\r
     len := sizeof(tifrec);\r
 \r
     if (len < sizeof(tifrec)) then break; {not enough left}\r
@@ -155,14 +149,72 @@ begin
   FileClose(s);\r
 end;\r
 \r
+{$endif}   //linux\r
+\r
+{$ifdef bsd}\r
+\r
+type\r
+  pifaddrs = ^Tifaddrs;\r
+  Tifaddrs = record\r
+    ifa_next: pifaddrs;\r
+    ifa_name: pansichar;\r
+    ifa_flags: cuint;   // Interface flags (IFF_UP, IFF_BROADCAST, etc.)\r
+    ifa_addr: Pinetsockaddrv;\r
+    ifa_netmask: psockaddr;\r
+    ifa_dstaddr: psockaddr; // union: Destination address (P-t-P) or broadcast address\r
+    ifa_data: Pointer;\r
+  end;\r
+\r
+const\r
+  IFF_UP=1; //interface is administratively enabled\r
+\r
+function getifaddrs(var ifap: pifaddrs): cint; cdecl; external 'c' name 'getifaddrs';\r
+function freeifaddrs(ifap: pifaddrs): cint; cdecl; external 'c' name 'freeifaddrs';\r
+\r
+\r
+function getlocalips_internal(wantfamily:integer):tbiniplist;\r
+var\r
+  IfList: pifaddrs;\r
+  IfPtr: pifaddrs;\r
+  sa: PinetSockAddrV;\r
+begin\r
+  result := biniplist_new;\r
+\r
+  if getifaddrs(IfList) <> 0 then raise exception.create('getlocalips getifaddrs failed');\r
+\r
+  IfPtr := IfList;\r
+  while IfPtr <> nil do begin\r
+    if ((IfPtr^.ifa_flags and IFF_UP) <> 0) then begin\r
+      sa := IfPtr^.ifa_addr;\r
+      //if (sa <> nil) then writeln(sa^.inaddr.len,' ',sa^.inaddr.family);\r
+\r
+      if (sa <> nil) and (sa^.inaddr.family = wantfamily) then begin\r
+        biniplist_add(result, inaddrvtobinip(sa^));\r
+      end;\r
+    end;\r
+    IfPtr := IfPtr^.ifa_next;\r
+  end;\r
+\r
+  freeifaddrs(IfList);\r
+end;\r
+\r
+{$endif}    //bsd\r
+\r
+\r
 {$ifdef ipv6}\r
 function getv6localips:tbiniplist;\r
+{$ifndef bsd}\r
 var\r
   t:textfile;\r
   s,s2:ansistring;\r
   ip:tbinip;\r
   a:integer;\r
+{$endif}\r
 begin\r
+ {$ifdef bsd}\r
+  result := getlocalips_internal(AF_INET6);\r
+ {$else}\r
+  //linux\r
   result := biniplist_new;\r
 \r
   assignfile(t,'/proc/net/if_inet6');\r
@@ -183,6 +235,7 @@ begin
     if ip.family <> 0 then biniplist_add(result,ip);\r
   end;\r
   closefile(t);\r
+ {$endif}\r
 end;\r
 {$endif}    //ipv6\r
 \r