source: src/router/services/services/udhcpd.c @ 10735

Last change on this file since 10735 was 10735, checked in by BrainSlayer, 5 years ago

still alot todo

File size: 10.9 KB
Line 
1/*
2 * udhcpd.c
3 *
4 * Copyright (C) 2007 Sebastian Gottschall <gottschall@dd-wrt.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 *
20 * $Id:
21 */
22#ifdef HAVE_UDHCPD
23#include <unistd.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <errno.h>
28#include <sys/time.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <syslog.h>
32#include <signal.h>
33#include <netinet/in.h>
34#include <arpa/inet.h>
35#include <utils.h>
36#include <bcmnvram.h>
37#include <shutils.h>
38
39extern int usejffs;
40
41void stop_udhcpd( void );
42extern void addHost( char *host, char *ip );
43
44static int adjust_dhcp_range( void )
45{
46    struct in_addr ipaddr, netaddr, netmask;
47
48    char *lan_ipaddr = nvram_safe_get( "lan_ipaddr" );
49    char *lan_netmask = nvram_safe_get( "lan_netmask" );
50    char *dhcp_num = nvram_safe_get( "dhcp_num" );
51    char *dhcp_start = nvram_safe_get( "dhcp_start" );
52
53    int legal_start_ip, legal_end_ip, legal_total_ip, dhcp_start_ip;
54    int set_dhcp_start_ip = 0, set_dhcp_num = 0;
55    int adjust_ip = 0, adjust_num = 0;
56
57    inet_aton( lan_ipaddr, &netaddr );
58    inet_aton( lan_netmask, &netmask );
59    inet_aton( dhcp_start, &ipaddr );
60
61    legal_total_ip = 254 - get_single_ip( lan_netmask, 3 );
62    legal_start_ip =
63        ( get_single_ip( lan_ipaddr, 3 ) & get_single_ip( lan_netmask, 3 ) ) +
64        1;
65    legal_end_ip = legal_start_ip + legal_total_ip - 1;
66    dhcp_start_ip = atoi( dhcp_start );
67
68    cprintf
69        ( "legal_total_ip=[%d] legal_start_ip=[%d] legal_end_ip=[%d] dhcp_start_ip=[%d]\n",
70          legal_total_ip, legal_start_ip, legal_end_ip, dhcp_start_ip );
71
72    if( ( dhcp_start_ip > legal_end_ip )
73        || ( dhcp_start_ip < legal_start_ip ) )
74    {
75        cprintf
76            ( "Illegal DHCP Start IP: We need to adjust DHCP Start ip.\n" );
77        set_dhcp_start_ip = legal_start_ip;
78        adjust_ip = 1;
79        if( atoi( dhcp_num ) > legal_total_ip )
80        {
81            cprintf( "DHCP num is exceed, we need to adjust." );
82            set_dhcp_num = legal_total_ip;
83            adjust_num = 1;
84        }
85    }
86    else
87    {
88        cprintf( "Legal DHCP Start IP: We need to check DHCP num.\n" );
89        if( ( atoi( dhcp_num ) + dhcp_start_ip ) > legal_end_ip )
90        {
91            cprintf( "DHCP num is exceed, we need to adjust.\n" );
92            set_dhcp_num = legal_end_ip - dhcp_start_ip + 1;
93            adjust_num = 1;
94        }
95    }
96
97    if( adjust_ip )
98    {
99        char ip[20];
100
101        cprintf( "set_dhcp_start_ip=[%d]\n", set_dhcp_start_ip );
102        snprintf( ip, sizeof( ip ), "%d", set_dhcp_start_ip );
103        nvram_set( "dhcp_start", ip );
104    }
105    if( adjust_num )
106    {
107        char num[5];
108
109        cprintf( "set_dhcp_num=[%d]\n", set_dhcp_num );
110        snprintf( num, sizeof( num ), "%d", set_dhcp_num );
111        nvram_set( "dhcp_num", num );
112    }
113
114    return 1;
115}
116
117void start_udhcpd( void )
118{
119    FILE *fp = NULL;
120    struct dns_lists *dns_list = NULL;
121    int i = 0;
122
123    if( nvram_match( "dhcpfwd_enable", "1" ) )
124    {
125        return;
126    }
127#ifndef HAVE_RB500
128#ifndef HAVE_XSCALE
129    if( nvram_match( "wl0_mode", "wet" ) || nvram_match( "wl0_mode", "apstawet" ) )     // dont
130        // start
131        // any
132        // dhcp
133        // services
134        // in
135        // bridge
136        // mode
137    {
138        nvram_set( "lan_proto", "static" );
139        return;
140    }
141#endif
142#endif
143
144    if( nvram_invmatch( "lan_proto", "dhcp" )
145        || nvram_match( "dhcp_dnsmasq", "1" ) )
146    {
147        stop_udhcpd(  );
148        return;
149    }
150
151    /*
152     * Automatically adjust DHCP Start IP and num when LAN IP or netmask is
153     * changed
154     */
155    adjust_dhcp_range(  );
156
157    cprintf( "%s %d.%d.%d.%s %s %s\n",
158             nvram_safe_get( "lan_ifname" ),
159             get_single_ip( nvram_safe_get( "lan_ipaddr" ), 0 ),
160             get_single_ip( nvram_safe_get( "lan_ipaddr" ), 1 ),
161             get_single_ip( nvram_safe_get( "lan_ipaddr" ), 2 ),
162             nvram_safe_get( "dhcp_start" ),
163             nvram_safe_get( "dhcp_end" ), nvram_safe_get( "lan_lease" ) );
164
165    /*
166     * Touch leases file
167     */
168
169    usejffs = 0;
170
171    if( nvram_match( "dhcpd_usejffs", "1" ) )
172    {
173        if( !( fp = fopen( "/jffs/udhcpd.leases", "a" ) ) )
174        {
175            usejffs = 0;
176        }
177        else
178        {
179            usejffs = 1;
180        }
181    }
182    if( !usejffs )
183    {
184        if( !( fp = fopen( "/tmp/udhcpd.leases", "a" ) ) )
185        {
186            perror( "/tmp/udhcpd.leases" );
187            return;
188        }
189    }
190    fclose( fp );
191
192    /*
193     * Write configuration file based on current information
194     */
195    if( !( fp = fopen( "/tmp/udhcpd.conf", "w" ) ) )
196    {
197        perror( "/tmp/udhcpd.conf" );
198        return;
199    }
200    fprintf( fp, "pidfile /var/run/udhcpd.pid\n" );
201    fprintf( fp, "start %d.%d.%d.%s\n",
202             get_single_ip( nvram_safe_get( "lan_ipaddr" ), 0 ),
203             get_single_ip( nvram_safe_get( "lan_ipaddr" ), 1 ),
204             get_single_ip( nvram_safe_get( "lan_ipaddr" ), 2 ),
205             nvram_safe_get( "dhcp_start" ) );
206    fprintf( fp, "end %d.%d.%d.%d\n",
207             get_single_ip( nvram_safe_get( "lan_ipaddr" ), 0 ),
208             get_single_ip( nvram_safe_get( "lan_ipaddr" ), 1 ),
209             get_single_ip( nvram_safe_get( "lan_ipaddr" ), 2 ),
210             atoi( nvram_safe_get( "dhcp_start" ) ) +
211             atoi( nvram_safe_get( "dhcp_num" ) ) - 1 );
212    int dhcp_max =
213        atoi( nvram_safe_get( "dhcp_num" ) ) +
214        atoi( nvram_safe_get( "static_leasenum" ) );
215    fprintf( fp, "max_leases %d\n", dhcp_max );
216    fprintf( fp, "interface %s\n", nvram_safe_get( "lan_ifname" ) );
217    fprintf( fp, "remaining yes\n" );
218    fprintf( fp, "auto_time 30\n" );    // N seconds to update lease table
219    if( usejffs )
220        fprintf( fp, "lease_file /jffs/udhcpd.leases\n" );
221    else
222        fprintf( fp, "lease_file /tmp/udhcpd.leases\n" );
223    fprintf( fp, "statics_file /tmp/udhcpd.statics\n" );
224
225    if( nvram_invmatch( "lan_netmask", "" )
226        && nvram_invmatch( "lan_netmask", "0.0.0.0" ) )
227        fprintf( fp, "option subnet %s\n", nvram_safe_get( "lan_netmask" ) );
228
229    if( nvram_invmatch( "dhcp_gateway", "" )
230        && nvram_invmatch( "dhcp_gateway", "0.0.0.0" ) )
231        fprintf( fp, "option router %s\n", nvram_safe_get( "dhcp_gateway" ) );
232    else if( nvram_invmatch( "lan_ipaddr", "" )
233             && nvram_invmatch( "lan_ipaddr", "0.0.0.0" ) )
234        fprintf( fp, "option router %s\n", nvram_safe_get( "lan_ipaddr" ) );
235
236    if( nvram_invmatch( "wan_wins", "" )
237        && nvram_invmatch( "wan_wins", "0.0.0.0" ) )
238        fprintf( fp, "option wins %s\n", nvram_get( "wan_wins" ) );
239
240    // Wolf add - keep lease within reasonable timeframe
241    if( atoi( nvram_safe_get( "dhcp_lease" ) ) < 10 )
242    {
243        nvram_set( "dhcp_lease", "10" );
244        nvram_commit(  );
245    }
246    if( atoi( nvram_safe_get( "dhcp_lease" ) ) > 5760 )
247    {
248        nvram_set( "dhcp_lease", "5760" );
249        nvram_commit(  );
250    }
251
252    fprintf( fp, "option lease %d\n",
253             atoi( nvram_safe_get( "dhcp_lease" ) ) ?
254             atoi( nvram_safe_get( "dhcp_lease" ) ) * 60 : 86400 );
255
256    dns_list = get_dns_list(  );
257
258    if( !dns_list || dns_list->num_servers == 0 )
259    {
260        if( nvram_invmatch( "lan_ipaddr", "" ) )
261            fprintf( fp, "option dns %s\n", nvram_safe_get( "lan_ipaddr" ) );
262    }
263    else if( nvram_match( "local_dns", "1" ) )
264    {
265        if( dns_list
266            && ( nvram_invmatch( "lan_ipaddr", "" )
267                 || strlen( dns_list->dns_server[0] ) > 0
268                 || strlen( dns_list->dns_server[1] ) > 0
269                 || strlen( dns_list->dns_server[2] ) > 0 ) )
270        {
271            fprintf( fp, "option dns" );
272
273            if( nvram_invmatch( "lan_ipaddr", "" ) )
274                fprintf( fp, " %s", nvram_safe_get( "lan_ipaddr" ) );
275            if( strlen( dns_list->dns_server[0] ) > 0 )
276                fprintf( fp, " %s", dns_list->dns_server[0] );
277            if( strlen( dns_list->dns_server[1] ) > 0 )
278                fprintf( fp, " %s", dns_list->dns_server[1] );
279            if( strlen( dns_list->dns_server[2] ) > 0 )
280                fprintf( fp, " %s", dns_list->dns_server[2] );
281
282            fprintf( fp, "\n" );
283        }
284    }
285    else
286    {
287        if( dns_list
288            && ( strlen( dns_list->dns_server[0] ) > 0
289                 || strlen( dns_list->dns_server[1] ) > 0
290                 || strlen( dns_list->dns_server[2] ) > 0 ) )
291        {
292            fprintf( fp, "option dns" );
293            if( strlen( dns_list->dns_server[0] ) > 0 )
294                fprintf( fp, " %s", dns_list->dns_server[0] );
295            if( strlen( dns_list->dns_server[1] ) > 0 )
296                fprintf( fp, " %s", dns_list->dns_server[1] );
297            if( strlen( dns_list->dns_server[2] ) > 0 )
298                fprintf( fp, " %s", dns_list->dns_server[2] );
299
300            fprintf( fp, "\n" );
301        }
302    }
303
304    if( dns_list )
305        free( dns_list );
306
307    /*
308     * DHCP Domain
309     */
310    if( nvram_match( "dhcp_domain", "wan" ) )
311    {
312        if( nvram_invmatch( "wan_domain", "" ) )
313            fprintf( fp, "option domain %s\n",
314                     nvram_safe_get( "wan_domain" ) );
315        else if( nvram_invmatch( "wan_get_domain", "" ) )
316            fprintf( fp, "option domain %s\n",
317                     nvram_safe_get( "wan_get_domain" ) );
318    }
319    else
320    {
321        if( nvram_invmatch( "lan_domain", "" ) )
322            fprintf( fp, "option domain %s\n",
323                     nvram_safe_get( "lan_domain" ) );
324    }
325
326    if( nvram_invmatch( "dhcpd_options", "" ) )
327    {
328        fwritenvram( "dhcpd_options", fp );
329    }
330    fclose( fp );
331
332    /*
333     * Sveasoft addition - create static leases file
334     */
335    // Static for router
336    if( !( fp = fopen( "/tmp/udhcpd.statics", "w" ) ) )
337    {
338        perror( "/tmp/udhcpd.statics" );
339        return;
340    }
341
342    if( nvram_match( "local_dns", "1" ) )
343    {
344        if( nvram_match( "port_swap", "1" ) )
345            fprintf( fp, "%s %s %s\n", nvram_safe_get( "lan_ipaddr" ),
346                     nvram_safe_get( "et1macaddr" ),
347                     nvram_safe_get( "router_name" ) );
348        else
349            fprintf( fp, "%s %s %s\n", nvram_safe_get( "lan_ipaddr" ),
350                     nvram_safe_get( "et0macaddr" ),
351                     nvram_safe_get( "router_name" ) );
352    }
353    int leasenum = atoi( nvram_safe_get( "static_leasenum" ) );
354
355    if( leasenum > 0 )
356    {
357        char *lease = nvram_safe_get( "static_leases" );
358        char *leasebuf = ( char * )malloc( strlen( lease ) + 1 );
359        char *cp = leasebuf;
360
361        strcpy( leasebuf, lease );
362        for( i = 0; i < leasenum; i++ )
363        {
364            char *mac = strsep( &leasebuf, "=" );
365            char *host = strsep( &leasebuf, "=" );
366            char *ip = strsep( &leasebuf, " " );
367
368            if( mac == NULL || host == NULL || ip == NULL )
369                continue;
370            fprintf( fp, "%s %s %s\n", ip, mac, host );
371            addHost( host, ip );
372        }
373        free( cp );
374    }
375
376    fclose( fp );
377    /*
378     * end Sveasoft addition
379     */
380
381    dns_to_resolv(  );
382
383    eval( "udhcpd", "/tmp/udhcpd.conf" );
384    dd_syslog( LOG_INFO, "udhcpd : udhcp daemon successfully started\n" );
385
386    /*
387     * Dump static leases to udhcpd.leases so they can be read by dnsmasq
388     */
389    /*
390     * DD-WRT (belanger) : the dump database is now handled directly in
391     * udhcpd
392     */
393    // sprintf (sigusr1, "-%d", SIGUSR1);
394    // killps("udhcpd",sigusr1);
395
396    // eval ("killall", sigusr1, "udhcpd");
397
398    cprintf( "done\n" );
399    return;
400}
401
402void stop_udhcpd( void )
403{
404    if( pidof( "udhcpd" ) > 0 )
405    {
406        dd_syslog( LOG_INFO, "udhcpd : udhcp daemon successfully stopped\n" );
407        softkill( "udhcpd" );
408    }
409    cprintf( "done\n" );
410    return;
411}
412
413#endif
Note: See TracBrowser for help on using the repository browser.