[haiku-commits] r34642 - haiku/trunk/src/servers/net

  • From: korli@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 12 Dec 2009 16:30:26 +0100 (CET)

Author: korli
Date: 2009-12-12 16:30:26 +0100 (Sat, 12 Dec 2009)
New Revision: 34642
Changeset: http://dev.haiku-os.org/changeset/34642/haiku

Modified:
   haiku/trunk/src/servers/net/NetServer.cpp
Log:
* free buffer on ioctl failures
* monitors /dev/net for added or removed devices and handles events 
        by configuring or unconfiguring interfaces. When plugged a usb 
        network device, it now appears correcly.


Modified: haiku/trunk/src/servers/net/NetServer.cpp
===================================================================
--- haiku/trunk/src/servers/net/NetServer.cpp   2009-12-12 15:02:30 UTC (rev 
34641)
+++ haiku/trunk/src/servers/net/NetServer.cpp   2009-12-12 15:30:26 UTC (rev 
34642)
@@ -45,6 +45,7 @@
 class NetServer : public BServer {
        public:
                NetServer(status_t& status);
+               virtual ~NetServer();
 
                virtual void AboutRequested();
                virtual void ReadyToRun();
@@ -64,6 +65,7 @@
                void _ConfigureInterfaces(int socket, BMessage* _missingDevice 
= NULL);
                void _BringUpInterfaces();
                void _StartServices();
+               void _HandleDeviceMonitor(int socket, BMessage* message);
 
                Settings        fSettings;
                LooperMap       fDeviceMap;
@@ -245,6 +247,12 @@
 }
 
 
+NetServer::~NetServer()
+{
+       BPrivate::BPathMonitor::StopWatching("/dev/net", this); 
+}
+
+
 void
 NetServer::AboutRequested()
 {
@@ -270,6 +278,10 @@
        fSettings.StartMonitoring(this);
        _BringUpInterfaces();
        _StartServices();
+       
+       BPrivate::BPathMonitor::StartWatching("/dev/net", B_ENTRY_CREATED
+                       | B_ENTRY_REMOVED | B_ENTRY_MOVED | B_WATCH_FILES_ONLY
+                       | B_WATCH_RECURSIVELY, this);
 }
 
 
@@ -278,9 +290,17 @@
 {
        switch (message->what) {
                case B_PATH_MONITOR:
+               {
                        fSettings.Update(message);
+                       
+                       // we need a socket to talk to the networking stack
+                       int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
+                       if (socket < 0)
+                               break;
+                       _HandleDeviceMonitor(socket, message);
+                       close(socket);
                        break;
-
+               }
                case kMsgInterfaceSettingsUpdated:
                {
                        // we need a socket to talk to the networking stack
@@ -413,8 +433,10 @@
 
        config.ifc_len = count * sizeof(struct ifreq);
        config.ifc_buf = buffer;
-       if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0)
+       if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) {
+               free(buffer);
                return;
+       }
 
        ifreq *interface = (ifreq *)buffer;
 
@@ -423,7 +445,7 @@
                        // remove invalid interface
                        ifreq request;
                        if (!prepare_request(request, interface->ifr_name))
-                               return;
+                               break;
 
                        if (ioctl(socket, SIOCDIFADDR, &request, 
sizeof(request)) < 0) {
                                fprintf(stderr, "%s: Could not delete interface 
%s: %s\n",
@@ -431,7 +453,8 @@
                        }
                }
 
-               interface = (ifreq *)((addr_t)interface + IF_NAMESIZE + 
interface->ifr_addr.sa_len);
+               interface = (ifreq *)((addr_t)interface + IF_NAMESIZE
+                       + interface->ifr_addr.sa_len);
        }
 
        free(buffer);
@@ -462,8 +485,10 @@
 
        config.ifc_len = count * sizeof(struct ifreq);
        config.ifc_buf = buffer;
-       if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0)
+       if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) {
+               free(buffer);
                return false;
+       }
 
        ifreq *interface = (ifreq *)buffer;
        int32 nameLength = strlen(name);
@@ -850,6 +875,78 @@
 }
 
 
+void
+NetServer::_HandleDeviceMonitor(int socket, BMessage* message)
+{
+       int32 opcode;
+       if (message->FindInt32("opcode", &opcode) != B_OK)
+               return;
+
+       if (opcode != B_ENTRY_CREATED && opcode != B_ENTRY_REMOVED)
+               return;
+               
+       const char* path;
+       const char* watchedPath;
+       if (message->FindString("watched_path", &watchedPath) != B_OK
+               || message->FindString("path", &path) != B_OK)
+               return;
+               
+       if (opcode == B_ENTRY_CREATED) {
+               _ConfigureDevice(socket, path);
+               return; 
+       }
+               
+       ifconf config;
+       config.ifc_len = sizeof(config.ifc_value);
+       if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0)
+               return;
+
+       uint32 count = (uint32)config.ifc_value;
+       if (count == 0) {
+               // there are no interfaces yet
+               return;
+       }
+
+       void *buffer = malloc(count * sizeof(struct ifreq));
+       if (buffer == NULL) {
+               fprintf(stderr, "%s: Out of memory.\n", Name());
+               return;
+       }
+
+       config.ifc_len = count * sizeof(struct ifreq);
+       config.ifc_buf = buffer;
+       if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) {
+               free(buffer);
+               return;
+       }
+
+       ifreq *interface = (ifreq *)buffer;
+       int32 pathLength = strlen(path);
+       
+       for (uint32 i = 0; i < count; i++) {
+               if (strncmp(interface->ifr_name, path, pathLength)) {
+                       interface = (ifreq *)((addr_t)interface + IF_NAMESIZE
+                       + interface->ifr_addr.sa_len);
+                       continue;
+               }
+               
+               ifreq request;
+               if (!prepare_request(request, interface->ifr_name))
+                       break;
+
+               if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) < 0) {
+                       fprintf(stderr, "%s: Could not delete interface %s: 
%s\n",
+                               Name(), interface->ifr_name, strerror(errno));
+               }
+               break;
+       }
+
+       free(buffer);
+       
+       
+}
+
+
 //     #pragma mark -
 
 


Other related posts: