[haiku-commits] haiku: hrev48684 - src/kits/network headers/compatibility/bsd

  • From: pulkomandy@xxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 16 Jan 2015 13:10:16 +0100 (CET)

hrev48684 adds 1 changeset to branch 'master'
old head: 23f1ce0756ffcde7835b8d5d9a42cb3eff54318f
new head: e2fc7cd3c7be1918e8de18e984d10acb5ea2626d
overview: 
http://cgit.haiku-os.org/haiku/log/?qt=range&q=e2fc7cd3c7be+%5E23f1ce0756ff

----------------------------------------------------------------------------

e2fc7cd3c7be: Implement getifaddrs.
  
  This is a BSD extension also available in glibc, but is not POSIX.
  Fixes #6279.

                                 [ Adrien Destugues <pulkomandy@xxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev48684
Commit:      e2fc7cd3c7be1918e8de18e984d10acb5ea2626d
URL:         http://cgit.haiku-os.org/haiku/commit/?id=e2fc7cd3c7be
Author:      Adrien Destugues <pulkomandy@xxxxxxxxx>
Date:        Fri Jan 16 12:06:48 2015 UTC

Ticket:      https://dev.haiku-os.org/ticket/6279

----------------------------------------------------------------------------

2 files changed, 98 insertions(+), 1 deletion(-)
headers/compatibility/bsd/ifaddrs.h | 25 +++++++++++
src/kits/network/interfaces.cpp     | 74 ++++++++++++++++++++++++++++++++-

----------------------------------------------------------------------------

diff --git a/headers/compatibility/bsd/ifaddrs.h 
b/headers/compatibility/bsd/ifaddrs.h
new file mode 100644
index 0000000..7169d0c
--- /dev/null
+++ b/headers/compatibility/bsd/ifaddrs.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2015, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef _IFADDRS_H
+#define _IFADDRS_H
+
+
+struct ifaddrs {
+       struct ifaddrs  *ifa_next;    /* Next item in list */
+       const char      *ifa_name;    /* Name of interface */
+       unsigned int     ifa_flags;   /* Flags from SIOCGIFFLAGS */
+       struct sockaddr *ifa_addr;    /* Address of interface */
+       struct sockaddr *ifa_netmask; /* Netmask of interface */
+       struct sockaddr *ifa_dstaddr;
+       #define         ifa_broadaddr ifa_dstaddr
+       void            *ifa_data;    /* Address-specific data */
+};
+
+
+int getifaddrs(struct ifaddrs **ifap);
+void freeifaddrs(struct ifaddrs *ifa);
+
+
+#endif
diff --git a/src/kits/network/interfaces.cpp b/src/kits/network/interfaces.cpp
index f0a7faf..42a043d 100644
--- a/src/kits/network/interfaces.cpp
+++ b/src/kits/network/interfaces.cpp
@@ -1,12 +1,14 @@
 /*
- * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
+ * Copyright 2006-2015, Haiku, Inc. All Rights Reserved.
  * Distributed under the terms of the MIT License.
  *
  * Authors:
  *             Axel Dörfler, axeld@xxxxxxxxxxxxxxxx
+ *             Adrien Destugues, pulkomandy@xxxxxxxxxxxxx
  */
 
 
+#include <errno.h>
 #include <net/if.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
@@ -15,6 +17,11 @@
 #include <unistd.h>
 
 #include <AutoDeleter.h>
+#include <NetworkAddress.h>
+#include <NetworkInterface.h>
+#include <NetworkRoster.h>
+
+#include "compatibility/bsd/ifaddrs.h"
 
 
 namespace BPrivate {
@@ -141,3 +148,68 @@ if_freenameindex(struct if_nameindex *interfaceArray)
        free(interfaceArray);
 }
 
+
+int getifaddrs(struct ifaddrs **ifap)
+{
+       if (ifap == NULL) {
+               errno = B_BAD_VALUE;
+               return -1;
+       }
+
+       BNetworkRoster& roster = BNetworkRoster::Default();
+
+       uint32 cookie;
+
+       struct ifaddrs* previous = NULL;
+       struct ifaddrs* current = NULL;
+       BNetworkInterface* interface = new BNetworkInterface();
+
+       while (roster.GetNextInterface(&cookie, *interface) == B_OK) {
+               BNetworkInterfaceAddress address;
+               int32 i = 0;
+               while (interface->GetAddressAt(i++, address) == B_OK) {
+                       current = new ifaddrs();
+
+                       // Chain this interface with the next one
+                       current->ifa_next = previous;
+                       previous = current;
+
+                       current->ifa_data = interface;
+                       current->ifa_name = interface->Name();
+                               // Points to the name in the BNetworkInterface 
instance, which
+                               // is added as ifa_data so freeifaddrs can 
release it.
+                       current->ifa_flags = address.Flags();
+                       current->ifa_addr = new 
sockaddr(address.Address().SockAddr());
+                       current->ifa_netmask = new 
sockaddr(address.Mask().SockAddr());
+                       current->ifa_dstaddr = new 
sockaddr(address.Destination().SockAddr());
+               }
+
+               interface = new BNetworkInterface();
+       }
+
+       delete interface;
+       *ifap = current;
+
+       return 0;
+}
+
+
+void freeifaddrs(struct ifaddrs *ifa)
+{
+       struct ifaddrs* next;
+       BNetworkInterface* interface = NULL;
+       while (ifa != NULL) {
+               if (ifa->ifa_data != interface) {
+                       interface = (BNetworkInterface*)ifa->ifa_data;
+                       delete interface;
+               }
+
+               delete ifa->ifa_addr;
+               delete ifa->ifa_netmask;
+               delete ifa->ifa_dstaddr;
+
+               next = ifa->ifa_next;
+               delete ifa;
+               ifa = next;
+       }
+}


Other related posts: