- Stop trying to find more adapters if it failed to avoid spamming the debug log
[reactos.git] / reactos / base / services / dhcp / dispatch.c
index 5bf9410..76ac90e 100644 (file)
 struct protocol *protocols = NULL;
 struct timeout *timeouts = NULL;
 static struct timeout *free_timeouts = NULL;
-static int interfaces_invalidated = FALSE;
 void (*bootp_packet_handler)(struct interface_info *,
                              struct dhcp_packet *, int, unsigned int,
                              struct iaddr, struct hardware *);
 
-static int interface_status(struct interface_info *ifinfo);
-
-/*
- * Use getifaddrs() to get a list of all the attached interfaces.  For
- * each interface that's of type INET and not the loopback interface,
- * register that interface with the network I/O software, figure out
- * what subnet it's on, and add it to the list of interfaces.
- */
-void
-discover_interfaces(struct interface_info *iface)
-{
-    PDHCP_ADAPTER Adapter = AdapterFindInfo( iface );
-
-    if_register_receive(iface);
-    if_register_send(iface);
-
-    if( Adapter->DhclientState.state != S_STATIC ) {
-        add_protocol(iface->name, iface->rfdesc, got_one, iface);
-       iface->client->state = S_INIT;
-       state_reboot(iface);
-    }
-}
-
-void
-reinitialize_interfaces(void)
-{
-    interfaces_invalidated = 1;
-}
-
 /*
  * Wait for packets to come in using poll().  When a packet comes in,
  * call receive_packet to receive the packet and possibly strip hardware
@@ -93,25 +63,32 @@ reinitialize_interfaces(void)
 void
 dispatch(void)
 {
-    int count, i, to_msec, nfds = 0;
+    int count, i, to_msec, nfds, err;
     struct protocol *l;
     fd_set fds;
-    time_t howlong;
+    time_t howlong, cur_time;
     struct timeval timeval;
 
     ApiLock();
 
-    for (l = protocols; l; l = l->next)
-        nfds++;
-
-    FD_ZERO(&fds);
-
     do {
         /*
          * Call any expired timeouts, and then if there's still
          * a timeout registered, time out the select call then.
          */
     another:
+        if (!AdapterDiscover()) {
+            AdapterStop();
+            break;
+        }
+
+        for (l = protocols, nfds = 0; l; l = l->next)
+            nfds++;
+
+        FD_ZERO(&fds);
+
+        time(&cur_time);
+
         if (timeouts) {
             struct timeout *t;
 
@@ -148,10 +125,9 @@ dispatch(void)
         }
 
         if (i == 0) {
-            /* No interfaces for now, set the select timeout reasonably so
-             * we can recover from that condition later. */
-            timeval.tv_sec = 5;
-            timeval.tv_usec = 0;
+            /* Wait for 5 seconds before looking for more interfaces */
+            Sleep(5000);
+            continue;
         } else {
             /* Wait for a packet or a timeout... XXX */
             timeval.tv_sec = to_msec / 1000;
@@ -182,18 +158,11 @@ dispatch(void)
 
         /* Not likely to be transitory... */
         if (count == SOCKET_ERROR) {
-            if (errno == EAGAIN || errno == EINTR) {
-                time(&cur_time);
-                continue;
-            } else {
-                error("poll: %m");
-                break;
-            }
+            err = WSAGetLastError();
+            error("poll: %d", err);
+            break;
         }
 
-        /* Get the current time... */
-        time(&cur_time);
-
         i = 0;
         for (l = protocols; l; l = l->next) {
             struct interface_info *ip;
@@ -203,12 +172,9 @@ dispatch(void)
                            !ip->dead)) {
                     DH_DbgPrint(MID_TRACE,("Handling %x\n", l));
                     (*(l->handler))(l);
-                    if (interfaces_invalidated)
-                        break;
                 }
                 i++;
             }
-            interfaces_invalidated = 0;
         }
     } while (1);
 
@@ -231,22 +197,25 @@ got_one(struct protocol *l)
         struct dhcp_packet packet;
     } u;
     struct interface_info *ip = l->local;
+    PDHCP_ADAPTER adapter;
 
     if ((result = receive_packet(ip, u.packbuf, sizeof(u), &from,
                                  &hfrom)) == -1) {
-        warning("receive_packet failed on %s: %s", ip->name,
-                strerror(errno));
+        warning("receive_packet failed on %s: %d", ip->name,
+                WSAGetLastError());
         ip->errors++;
-        if ((!interface_status(ip)) ||
-            (ip->noifmedia && ip->errors > 20)) {
+        if (ip->errors > 20) {
             /* our interface has gone away. */
             warning("Interface %s no longer appears valid.",
                     ip->name);
             ip->dead = 1;
-            interfaces_invalidated = 1;
             close(l->fd);
             remove_protocol(l);
-            free(ip);
+            adapter = AdapterFindInfo(ip);
+            if (adapter) {
+                RemoveEntryList(&adapter->ListEntry);
+                free(adapter);
+            }
         }
         return;
     }
@@ -257,79 +226,19 @@ got_one(struct protocol *l)
         ifrom.len = 4;
         memcpy(ifrom.iabuf, &from.sin_addr, ifrom.len);
 
-        (*bootp_packet_handler)(ip, &u.packet, result,
-                                from.sin_port, ifrom, &hfrom);
-    }
-}
-
-#if 0
-int
-interface_status(struct interface_info *ifinfo)
-{
-    char *ifname = ifinfo->name;
-    int ifsock = ifinfo->rfdesc;
-    struct ifreq ifr;
-    struct ifmediareq ifmr;
-
-    /* get interface flags */
-    memset(&ifr, 0, sizeof(ifr));
-    strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-    if (ioctl(ifsock, SIOCGIFFLAGS, &ifr) < 0) {
-        syslog(LOG_ERR, "ioctl(SIOCGIFFLAGS) on %s: %m", ifname);
-        goto inactive;
-    }
+        
+        adapter = AdapterFindByHardwareAddress(u.packet.chaddr,
+                                               u.packet.hlen);
 
-    /*
-     * if one of UP and RUNNING flags is dropped,
-     * the interface is not active.
-     */
-    if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
-        goto inactive;
-
-    /* Next, check carrier on the interface, if possible */
-    if (ifinfo->noifmedia)
-        goto active;
-    memset(&ifmr, 0, sizeof(ifmr));
-    strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
-    if (ioctl(ifsock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
-        if (errno != EINVAL) {
-            syslog(LOG_DEBUG, "ioctl(SIOCGIFMEDIA) on %s: %m",
-                   ifname);
-
-            ifinfo->noifmedia = 1;
-            goto active;
-        }
-        /*
-         * EINVAL (or ENOTTY) simply means that the interface
-         * does not support the SIOCGIFMEDIA ioctl. We regard it alive.
-         */
-        ifinfo->noifmedia = 1;
-        goto active;
-    }
-    if (ifmr.ifm_status & IFM_AVALID) {
-        switch (ifmr.ifm_active & IFM_NMASK) {
-        case IFM_ETHER:
-            if (ifmr.ifm_status & IFM_ACTIVE)
-                goto active;
-            else
-                goto inactive;
-            break;
-        default:
-            goto inactive;
+        if (!adapter) {
+            warning("Discarding packet with a non-matching target physical address\n");
+            return;
         }
+
+        (*bootp_packet_handler)(&adapter->DhclientInfo, &u.packet, result,
+                                from.sin_port, ifrom, &hfrom);
     }
-inactive:
-    return (0);
-active:
-    return (1);
 }
-#else
-int
-interface_status(struct interface_info *ifinfo)
-{
-    return (1);
-}
-#endif
 
 void
 add_timeout(time_t when, void (*where)(void *), void *what)
@@ -468,33 +377,5 @@ find_protocol_by_adapter(struct interface_info *info)
 int
 interface_link_status(char *ifname)
 {
-#if 0
-    struct ifmediareq ifmr;
-    int sock;
-
-    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
-        error("Can't create socket");
-
-    memset(&ifmr, 0, sizeof(ifmr));
-    strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
-    if (ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifmr) == -1) {
-        /* EINVAL -> link state unknown. treat as active */
-        if (errno != EINVAL)
-            syslog(LOG_DEBUG, "ioctl(SIOCGIFMEDIA) on %s: %m",
-                   ifname);
-        close(sock);
-        return (1);
-    }
-    close(sock);
-
-    if (ifmr.ifm_status & IFM_AVALID) {
-        if ((ifmr.ifm_active & IFM_NMASK) == IFM_ETHER) {
-            if (ifmr.ifm_status & IFM_ACTIVE)
-                return (1);
-            else
-                return (0);
-        }
-    }
-#endif
     return (1);
 }