- Fix derefercing of null pointer
[reactos.git] / reactos / base / services / dhcp / dhclient.c
index c5a361f..eee8e26 100644 (file)
@@ -72,8 +72,6 @@
 #define        domainchar(c) ((c) > 0x20 && (c) < 0x7f)
 
 unsigned long debug_trace_level = 0; /* DEBUG_ULTRA */
-time_t cur_time;
-time_t default_lease_time = 43200; /* 12 hours... */
 
 char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
 char *path_dhclient_db = NULL;
@@ -85,7 +83,6 @@ int privfd;
 struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
 struct in_addr inaddr_any;
 struct sockaddr_in sockaddr_broadcast;
-unsigned long old_default_route = 0;
 
 /*
  * ASSERT_STATE() does nothing now; it used to be
@@ -100,8 +97,6 @@ int          no_daemon;
 int            unknown_ok = 1;
 int            routefd;
 
-struct interface_info  *ifi = NULL;
-
 void            usage(void);
 int             check_option(struct client_lease *l, int option);
 int             ipv4addrs(char * buf);
@@ -134,13 +129,11 @@ static SERVICE_TABLE_ENTRY ServiceTable[2] =
 int
 main(int argc, char *argv[])
 {
-    int i = 0;
         ApiInit();
         AdapterInit();
         PipeInit();
 
        tzset();
-       time(&cur_time);
 
        memset(&sockaddr_broadcast, 0, sizeof(sockaddr_broadcast));
        sockaddr_broadcast.sin_family = AF_INET;
@@ -150,34 +143,6 @@ main(int argc, char *argv[])
 
         DH_DbgPrint(MID_TRACE,("DHCP Service Started\n"));
 
-       read_client_conf();
-
-       if (!interface_link_status(ifi->name)) {
-            DH_DbgPrint(MID_TRACE,("%s: no link ", ifi->name));
-            Sleep(1000);
-            while (!interface_link_status(ifi->name)) {
-                DH_DbgPrint(MID_TRACE,("."));
-                if (++i > 10) {
-                    DH_DbgPrint(MID_TRACE,("Giving up for now on adapter [%s]\n", ifi->name));
-                }
-                Sleep(1000);
-            }
-            DH_DbgPrint(MID_TRACE,("Got link on [%s]\n", ifi->name));
-       }
-
-        DH_DbgPrint(MID_TRACE,("Discover Interfaces\n"));
-
-        /* If no adapters were found, just idle for now ... If any show up,
-         * then we'll start it later */
-        if( ifi ) {
-            /* set up the interface */
-            discover_interfaces(ifi);
-
-            DH_DbgPrint
-                (MID_TRACE,
-                 ("Setting init state and restarting interface %p\n",ifi));
-        }
-
        bootp_packet_handler = do_packet;
 
         DH_DbgPrint(MID_TRACE,("Going into dispatch()\n"));
@@ -253,7 +218,7 @@ state_reboot(void *ipp)
           flags. */
        make_request(ip, ip->client->active);
        ip->client->destination = iaddr_broadcast;
-       ip->client->first_sending = cur_time;
+       time(&ip->client->first_sending);
        ip->client->interval = ip->client->config->initial_interval;
 
        /* Zap the medium list... */
@@ -280,7 +245,7 @@ state_init(void *ipp)
        ip->client->xid = ip->client->packet.xid;
        ip->client->destination = iaddr_broadcast;
        ip->client->state = S_SELECTING;
-       ip->client->first_sending = cur_time;
+       time(&ip->client->first_sending);
        ip->client->interval = ip->client->config->initial_interval;
 
        /* Add an immediate timeout to cause the first DHCPDISCOVER packet
@@ -297,9 +262,12 @@ state_selecting(void *ipp)
 {
        struct interface_info *ip = ipp;
        struct client_lease *lp, *next, *picked;
+        time_t cur_time;
 
        ASSERT_STATE(state, S_SELECTING);
 
+        time(&cur_time);
+
        /* Cancel state_selecting and send_discover timeouts, since either
           one could have got us here. */
        cancel_timeout(state_selecting, ip);
@@ -375,6 +343,9 @@ dhcpack(struct packet *packet)
 {
        struct interface_info *ip = packet->interface;
        struct client_lease *lease;
+        time_t cur_time;
+
+        time(&cur_time);
 
        /* If we're not receptive to an offer right now, or if the offer
           has an unrecognizable transaction id, then just drop it. */
@@ -408,7 +379,7 @@ dhcpack(struct packet *packet)
                ip->client->new->expiry = getULong(
                    ip->client->new->options[DHO_DHCP_LEASE_TIME].data);
        else
-               ip->client->new->expiry = default_lease_time;
+               ip->client->new->expiry = DHCP_DEFAULT_LEASE_TIME;
        /* A number that looks negative here is really just very large,
           because the lease expiry offset is unsigned. */
        if (ip->client->new->expiry < 0)
@@ -450,23 +421,26 @@ dhcpack(struct packet *packet)
        bind_lease(ip);
 }
 
-void set_name_servers( struct client_lease *new_lease ) {
+void set_name_servers( PDHCP_ADAPTER Adapter, struct client_lease *new_lease ) {
+    CHAR Buffer[200] = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
+    HKEY RegKey;
+
+    strcat(Buffer, Adapter->DhclientInfo.name);
+    if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Buffer, 0, KEY_WRITE, &RegKey ) != ERROR_SUCCESS)
+        return;
+
+
     if( new_lease->options[DHO_DOMAIN_NAME_SERVERS].len ) {
-        HKEY RegKey;
+
         struct iaddr nameserver;
         char *nsbuf;
         int i, addrs =
             new_lease->options[DHO_DOMAIN_NAME_SERVERS].len / sizeof(ULONG);
 
-               /* XXX I'm setting addrs to 1 until we are ready up the chain */
-               addrs = 1;
         nsbuf = malloc( addrs * sizeof(IP_ADDRESS_STRING) );
-        nsbuf[0] = 0;
 
-        if( nsbuf && !RegOpenKeyEx
-            ( HKEY_LOCAL_MACHINE,
-              "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
-              0, KEY_WRITE, &RegKey ) ) {
+        if( nsbuf) {
+            nsbuf[0] = 0;
             for( i = 0; i < addrs; i++ ) {
                 nameserver.len = sizeof(ULONG);
                 memcpy( nameserver.iabuf,
@@ -478,16 +452,30 @@ void set_name_servers( struct client_lease *new_lease ) {
 
             DH_DbgPrint(MID_TRACE,("Setting DhcpNameserver: %s\n", nsbuf));
 
-            RegSetValueEx( RegKey, "DhcpNameServer", 0, REG_SZ,
-                           (LPBYTE)nsbuf, strlen(nsbuf) + 1);
-
+            RegSetValueExA( RegKey, "DhcpNameServer", 0, REG_SZ,
+                           (LPBYTE)nsbuf, strlen(nsbuf) + 1 );
             free( nsbuf );
         }
+
+    } else {
+            RegDeleteValueW( RegKey, L"DhcpNameServer" );
     }
+
+    RegCloseKey( RegKey );
+
 }
 
 void setup_adapter( PDHCP_ADAPTER Adapter, struct client_lease *new_lease ) {
+    CHAR Buffer[200] = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
     struct iaddr netmask;
+    HKEY hkey;
+    int i;
+    DWORD dwEnableDHCP;
+
+    strcat(Buffer, Adapter->DhclientInfo.name);
+    if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Buffer, 0, KEY_WRITE, &hkey) != ERROR_SUCCESS)
+        hkey = NULL;
+
 
     if( Adapter->NteContext )
         DeleteIPAddress( Adapter->NteContext );
@@ -499,42 +487,67 @@ void setup_adapter( PDHCP_ADAPTER Adapter, struct client_lease *new_lease ) {
         memcpy( netmask.iabuf,
                 new_lease->options[DHO_SUBNET_MASK].data,
                 new_lease->options[DHO_SUBNET_MASK].len );
-
         Status = AddIPAddress
             ( *((ULONG*)new_lease->address.iabuf),
               *((ULONG*)netmask.iabuf),
               Adapter->IfMib.dwIndex,
               &Adapter->NteContext,
               &Adapter->NteInstance );
+        if (hkey) {
+            RegSetValueExA(hkey, "DhcpIPAddress", 0, REG_SZ, (LPBYTE)piaddr(new_lease->address), strlen(piaddr(new_lease->address))+1);
+            Buffer[0] = '\0';
+            for(i = 0; i < new_lease->options[DHO_SUBNET_MASK].len; i++)
+            {
+                sprintf(&Buffer[strlen(Buffer)], "%u", new_lease->options[DHO_SUBNET_MASK].data[i]);
+                if (i + 1 < new_lease->options[DHO_SUBNET_MASK].len)
+                    strcat(Buffer, ".");
+            }
+            RegSetValueExA(hkey, "DhcpSubnetMask", 0, REG_SZ, (LPBYTE)Buffer, strlen(Buffer)+1);
+            RegSetValueExA(hkey, "IPAddress", 0, REG_SZ, (LPBYTE)"0.0.0.0", 8);
+            RegSetValueExA(hkey, "SubnetMask", 0, REG_SZ, (LPBYTE)"0.0.0.0", 8);
+            dwEnableDHCP = 1;
+            RegSetValueExA(hkey, "EnableDHCP", 0, REG_DWORD, (LPBYTE)&dwEnableDHCP, sizeof(DWORD));
+        }
 
         if( !NT_SUCCESS(Status) )
             warning("AddIPAddress: %lx\n", Status);
     }
 
     if( new_lease->options[DHO_ROUTERS].len ) {
-        MIB_IPFORWARDROW RouterMib;
         NTSTATUS Status;
 
-        RouterMib.dwForwardDest = 0; /* Default route */
-        RouterMib.dwForwardMask = 0;
-        RouterMib.dwForwardMetric1 = 1;
+        Adapter->RouterMib.dwForwardDest = 0; /* Default route */
+        Adapter->RouterMib.dwForwardMask = 0;
+        Adapter->RouterMib.dwForwardMetric1 = 1;
 
-        if( old_default_route ) {
+        if( Adapter->RouterMib.dwForwardNextHop ) {
             /* If we set a default route before, delete it before continuing */
-            RouterMib.dwForwardDest = old_default_route;
-            DeleteIpForwardEntry( &RouterMib );
+            DeleteIpForwardEntry( &Adapter->RouterMib );
         }
 
-        RouterMib.dwForwardNextHop =
+        Adapter->RouterMib.dwForwardNextHop =
             *((ULONG*)new_lease->options[DHO_ROUTERS].data);
 
-        Status = CreateIpForwardEntry( &RouterMib );
+        Status = CreateIpForwardEntry( &Adapter->RouterMib );
 
         if( !NT_SUCCESS(Status) )
             warning("CreateIpForwardEntry: %lx\n", Status);
-        else
-            old_default_route = RouterMib.dwForwardNextHop;
+
+        if (hkey) {
+            Buffer[0] = '\0';
+            for(i = 0; i < new_lease->options[DHO_ROUTERS].len; i++)
+            {
+                sprintf(&Buffer[strlen(Buffer)], "%u", new_lease->options[DHO_ROUTERS].data[i]);
+                if (i + 1 < new_lease->options[DHO_ROUTERS].len)
+                    strcat(Buffer, ".");
+            }
+            RegSetValueExA(hkey, "DhcpDefaultGateway", 0, REG_SZ, (LPBYTE)Buffer, strlen(Buffer)+1);
+            RegSetValueExA(hkey, "DefaultGateway", 0, REG_SZ, (LPBYTE)"0.0.0.0", 8);
+        }
     }
+
+    if (hkey)
+        RegCloseKey(hkey);
 }
 
 
@@ -543,6 +556,9 @@ bind_lease(struct interface_info *ip)
 {
     PDHCP_ADAPTER Adapter;
     struct client_lease *new_lease = ip->client->new;
+    time_t cur_time;
+
+    time(&cur_time);
 
     /* Remember the medium. */
     ip->client->new->medium = ip->client->medium;
@@ -558,18 +574,18 @@ bind_lease(struct interface_info *ip)
 
     note("bound to %s -- renewal in %ld seconds.",
          piaddr(ip->client->active->address),
-         ip->client->active->renewal - cur_time);
+         (long int)(ip->client->active->renewal - cur_time));
 
     ip->client->state = S_BOUND;
 
     Adapter = AdapterFindInfo( ip );
 
     if( Adapter )  setup_adapter( Adapter, new_lease );
-    else warning("Could not find adapter for info %p\n", ip);
-
-    set_name_servers( new_lease );
-
-    reinitialize_interfaces();
+    else {
+        warning("Could not find adapter for info %p\n", ip);
+        return;
+    }
+    set_name_servers( Adapter, new_lease );
 }
 
 /*
@@ -596,7 +612,7 @@ state_bound(void *ipp)
        } else
                ip->client->destination = iaddr_broadcast;
 
-       ip->client->first_sending = cur_time;
+       time(&ip->client->first_sending);
        ip->client->interval = ip->client->config->initial_interval;
        ip->client->state = S_RENEWING;
 
@@ -669,6 +685,9 @@ dhcpoffer(struct packet *packet)
        int arp_timeout_needed = 0, stop_selecting;
        char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
            "DHCPOFFER" : "BOOTREPLY";
+        time_t cur_time;
+
+        time(&cur_time);
 
        /* If we're not receptive to an offer right now, or if the offer
           has an unrecognizable transaction id, then just drop it. */
@@ -907,9 +926,12 @@ send_discover(void *ipp)
 {
        struct interface_info *ip = ipp;
        int interval, increase = 1;
+        time_t cur_time;
 
         DH_DbgPrint(MID_TRACE,("Doing discover on interface %p\n",ip));
 
+        time(&cur_time);
+
        /* Figure out how long it's been since we started transmitting. */
        interval = cur_time - ip->client->first_sending;
 
@@ -987,7 +1009,7 @@ send_discover(void *ipp)
 
        note("DHCPDISCOVER on %s to %s port %d interval %ld",
            ip->name, inet_ntoa(sockaddr_broadcast.sin_addr),
-           ntohs(sockaddr_broadcast.sin_port), ip->client->interval);
+           ntohs(sockaddr_broadcast.sin_port), (long int)ip->client->interval);
 
        /* Send out a packet. */
        (void)send_packet(ip, &ip->client->packet, ip->client->packet_length,
@@ -1011,9 +1033,12 @@ state_panic(void *ipp)
        struct interface_info *ip = ipp;
        struct client_lease *loop = ip->client->active;
        struct client_lease *lp;
+        time_t cur_time;
 
        note("No DHCPOFFERS received.");
 
+        time(&cur_time);
+
        /* We may not have an active lease, but we may have some
           predefined leases that we can try. */
        if (!ip->client->active && ip->client->leases)
@@ -1040,8 +1065,8 @@ state_panic(void *ipp)
                             ip->client->active->renewal) {
                             ip->client->state = S_BOUND;
                             note("bound: renewal in %ld seconds.",
-                                 ip->client->active->renewal -
-                                 cur_time);
+                                 (long int)(ip->client->active->renewal -
+                                 cur_time));
                             add_timeout(
                                 ip->client->active->renewal,
                                 state_bound, ip);
@@ -1050,7 +1075,6 @@ state_panic(void *ipp)
                             note("bound: immediate renewal.");
                             state_bound(ip);
                         }
-                        reinitialize_interfaces();
                         return;
                }
 
@@ -1098,6 +1122,9 @@ send_request(void *ipp)
        struct sockaddr_in destination;
        struct in_addr from;
        int interval;
+        time_t cur_time;
+
+        time(&cur_time); 
 
        /* Figure out how long it's been since we started transmitting. */
        interval = cur_time - ip->client->first_sending;
@@ -1508,14 +1535,14 @@ free_client_lease(struct client_lease *lease)
 FILE *leaseFile;
 
 void
-rewrite_client_leases(void)
+rewrite_client_leases(struct interface_info *ifi)
 {
        struct client_lease *lp;
 
        if (!leaseFile) {
                leaseFile = fopen(path_dhclient_db, "w");
                if (!leaseFile)
-                       error("can't create %s: %m", path_dhclient_db);
+                       error("can't create %s", path_dhclient_db);
        } else {
                fflush(leaseFile);
                rewind(leaseFile);
@@ -1539,7 +1566,7 @@ write_client_lease(struct interface_info *ip, struct client_lease *lease,
 
        if (!rewrite) {
                if (leases_written++ > 20) {
-                       rewrite_client_leases();
+                       rewrite_client_leases(ip);
                        leases_written = 0;
                }
        }
@@ -1551,8 +1578,10 @@ write_client_lease(struct interface_info *ip, struct client_lease *lease,
 
        if (!leaseFile) {       /* XXX */
                leaseFile = fopen(path_dhclient_db, "w");
-               if (!leaseFile)
-                       error("can't create %s: %m", path_dhclient_db);
+               if (!leaseFile) {
+                       error("can't create %s", path_dhclient_db);
+                        return;
+                }
        }
 
        fprintf(leaseFile, "lease {\n");
@@ -1575,17 +1604,20 @@ write_client_lease(struct interface_info *ip, struct client_lease *lease,
                            lease->options[i].len, 1, 1));
 
        t = gmtime(&lease->renewal);
-       fprintf(leaseFile, "  renew %d %d/%d/%d %02d:%02d:%02d;\n",
-           t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
-           t->tm_hour, t->tm_min, t->tm_sec);
+        if (t)
+           fprintf(leaseFile, "  renew %d %d/%d/%d %02d:%02d:%02d;\n",
+               t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
+               t->tm_hour, t->tm_min, t->tm_sec);
        t = gmtime(&lease->rebind);
-       fprintf(leaseFile, "  rebind %d %d/%d/%d %02d:%02d:%02d;\n",
-           t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
-           t->tm_hour, t->tm_min, t->tm_sec);
+        if (t)
+           fprintf(leaseFile, "  rebind %d %d/%d/%d %02d:%02d:%02d;\n",
+                t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
+                t->tm_hour, t->tm_min, t->tm_sec);
        t = gmtime(&lease->expiry);
-       fprintf(leaseFile, "  expire %d %d/%d/%d %02d:%02d:%02d;\n",
-           t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
-           t->tm_hour, t->tm_min, t->tm_sec);
+        if (t)
+           fprintf(leaseFile, "  expire %d %d/%d/%d %02d:%02d:%02d;\n",
+               t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
+               t->tm_hour, t->tm_min, t->tm_sec);
        fprintf(leaseFile, "}\n");
        fflush(leaseFile);
 }
@@ -1607,7 +1639,7 @@ script_init(char *reason, struct string_list *medium)
            sizeof(size_t) + strlen(reason);
 
        if ((buf = buf_open(hdr.len)) == NULL)
-               error("buf_open: %m");
+               return;
 
        errs = 0;
        errs += buf_add(buf, &hdr, sizeof(hdr));
@@ -1619,26 +1651,23 @@ script_init(char *reason, struct string_list *medium)
        errs += buf_add(buf, reason, len);
 
        if (errs)
-               error("buf_add: %m");
+               error("buf_add: %d", WSAGetLastError());
 
        if (buf_close(privfd, buf) == -1)
-               error("buf_close: %m");
+               error("buf_close: %d", WSAGetLastError());
 }
 
 void
-priv_script_init(char *reason, char *medium)
+priv_script_init(struct interface_info *ip, char *reason, char *medium)
 {
-       struct interface_info *ip = ifi;
-
        if (ip) {
             // XXX Do we need to do anything?
         }
 }
 
 void
-priv_script_write_params(char *prefix, struct client_lease *lease)
+priv_script_write_params(struct interface_info *ip, char *prefix, struct client_lease *lease)
 {
-       struct interface_info *ip = ifi;
        u_int8_t dbuf[1500];
        int i, len = 0;
 
@@ -1706,7 +1735,7 @@ supersede:
                                        len = ip->client->
                                            config->defaults[i].len +
                                            lease->options[i].len;
-                                       if (len > sizeof(dbuf)) {
+                                       if (len >= sizeof(dbuf)) {
                                                warning("no space to %s %s",
                                                    "prepend option",
                                                    dhcp_options[i].name);
@@ -1727,7 +1756,7 @@ supersede:
                                case ACTION_APPEND:
                                        len = ip->client->
                                            config->defaults[i].len +
-                                           lease->options[i].len;
+                                           lease->options[i].len + 1;
                                        if (len > sizeof(dbuf)) {
                                                warning("no space to %s %s",
                                                    "append option",
@@ -1743,7 +1772,7 @@ supersede:
                                                config->defaults[i].data,
                                                ip->client->
                                                config->defaults[i].len);
-                                       dp[len] = '\0';
+                                       dp[len-1] = '\0';
                                }
                        } else {
                                dp = ip->client->
@@ -1800,7 +1829,7 @@ script_write_params(char *prefix, struct client_lease *lease)
        scripttime = time(NULL);
 
        if ((buf = buf_open(hdr.len)) == NULL)
-               error("buf_open: %m");
+               return;
 
        errs = 0;
        errs += buf_add(buf, &hdr, sizeof(hdr));
@@ -1820,10 +1849,10 @@ script_write_params(char *prefix, struct client_lease *lease)
        }
 
        if (errs)
-               error("buf_add: %m");
+               error("buf_add: %d", WSAGetLastError());
 
        if (buf_close(privfd, buf) == -1)
-               error("buf_close: %m");
+               error("buf_close: %d", WSAGetLastError());
 }
 
 int
@@ -1913,11 +1942,9 @@ check_option(struct client_lease *l, int option)
        case DHO_HOST_NAME:
        case DHO_DOMAIN_NAME:
        case DHO_NIS_DOMAIN:
-               if (!res_hnok(sbuf)) {
+               if (!res_hnok(sbuf))
                        warning("Bogus Host Name option %d: %s (%s)", option,
                            sbuf, opbuf);
-                       return (0);
-               }
                return (1);
        case DHO_PAD:
        case DHO_TIME_OFFSET:
@@ -2055,41 +2082,3 @@ toobig:
        return "<error>";
 }
 
-#if 0
-int
-fork_privchld(int fd, int fd2)
-{
-       struct pollfd pfd[1];
-       int nfds;
-
-       switch (fork()) {
-       case -1:
-               error("cannot fork");
-       case 0:
-               break;
-       default:
-               return (0);
-       }
-
-       setproctitle("%s [priv]", ifi->name);
-
-       dup2(nullfd, STDIN_FILENO);
-       dup2(nullfd, STDOUT_FILENO);
-       dup2(nullfd, STDERR_FILENO);
-       close(nullfd);
-       close(fd2);
-
-       for (;;) {
-               pfd[0].fd = fd;
-               pfd[0].events = POLLIN;
-               if ((nfds = poll(pfd, 1, INFTIM)) == -1)
-                       if (errno != EINTR)
-                               error("poll error");
-
-               if (nfds == 0 || !(pfd[0].revents & POLLIN))
-                       continue;
-
-               dispatch_imsg(fd);
-       }
-}
-#endif
\ No newline at end of file