root/src/router/services/networking/udhcpc.c

Revision 12386, 10.3 kB (checked in by BrainSlayer, 5 months ago)

fixes pptp snat issue

Line 
1 /*
2  * udhcpc.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
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <net/route.h>
27 #include <sys/socket.h>
28 #include <netinet/in.h>
29 #include <arpa/inet.h>
30 #include <errno.h>
31 #include <time.h>
32 #include <unistd.h>
33 #include <sys/sysinfo.h>
34
35 #include <bcmnvram.h>
36 #include <netconf.h>
37 #include <shutils.h>
38 #include <rc.h>
39 #include <code_pattern.h>
40 #include <cy_conf.h>
41 #include <utils.h>
42 #include <services.h>
43
44 #define IFUP (IFF_UP | IFF_RUNNING | IFF_BROADCAST | IFF_MULTICAST)
45
46 static int expires(unsigned int in)
47 {
48         struct sysinfo info;
49         FILE *fp;
50
51         sysinfo(&info);
52
53         /*
54          * Save uptime ranther than system time, because the system time may
55          * change
56          */
57         if (!(fp = fopen("/tmp/udhcpc.expires", "w"))) {
58                 perror("/tmp/udhcpd.expires");
59                 return errno;
60         }
61         fprintf(fp, "%d", (unsigned int)info.uptime + in);
62         fclose(fp);
63         return 0;
64 }
65
66 /*
67  * deconfig: This argument is used when udhcpc starts, and when a
68  * leases is lost. The script should put the interface in an up, but
69  * deconfigured state.
70  */
71 static int deconfig(void)
72 {
73         char *wan_ifname = safe_getenv("interface");
74
75         eval("ifconfig", wan_ifname, "0.0.0.0", "up");
76         expires(0);
77
78         nvram_set("wan_ipaddr", "0.0.0.0");
79         nvram_set("wan_netmask", "0.0.0.0");
80         nvram_set("wan_gateway", "0.0.0.0");
81         nvram_set("wan_get_dns", "");
82         // nvram_set("wan_wins","0.0.0.0"); // Don't care for linksys spec
83         nvram_set("wan_lease", "0");
84
85         unlink("/tmp/get_lease_time");
86         unlink("/tmp/lease_time");
87
88         cprintf("done\n");
89         return 0;
90 }
91
92 // ==================================================================
93 static int update_value(void)
94 {
95
96         char *value;
97         int changed = 0;
98
99         if ((value = getenv("ip"))) {
100                 chomp(value);
101                 if (nvram_invmatch("wan_ipaddr", value)) {
102                         nvram_set("wan_ipaddr", value);
103                         changed++;
104                 }
105         }
106         if ((value = getenv("subnet"))) {
107                 chomp(value);
108                 if (nvram_invmatch("wan_netmask", value)) {
109                         nvram_set("wan_netmask", value);
110                         changed++;
111                 }
112         }
113         if ((value = getenv("router"))) {
114                 chomp(value);
115                 if (nvram_invmatch("wan_gateway", value)) {
116                         nvram_set("wan_gateway", value);
117                         changed++;
118                 }
119         }
120         if ((value = getenv("dns"))) {
121                 chomp(value);
122                 if (nvram_invmatch("wan_get_dns", value)) {
123                         nvram_set("wan_get_dns", value);
124                         changed++;
125                 }
126         }
127         /*
128          * if ((value = getenv("wins"))) nvram_set("wan_wins", value); if ((value
129          * = getenv("hostname"))) sethostname(value, strlen(value) + 1);
130          */
131         if ((value = getenv("domain"))) {
132                 chomp(value);
133                 if (nvram_invmatch("wan_get_domain", value)) {
134                         nvram_set("wan_get_domain", value);
135                         changed++;
136                 }
137         }
138         if ((value = getenv("lease"))) {
139                 chomp(value);
140                 if (nvram_invmatch("wan_lease", value)) {
141                         nvram_set("wan_lease", value);
142                         changed++;
143                 }
144                 expires(atoi(value));
145         }
146
147         if (changed) {
148                 set_host_domain_name();
149 #ifdef HAVE_UDHCPD
150                 stop_udhcpd();
151                 start_udhcpd();
152 #endif
153         }
154         return 0;
155 }
156
157 // =================================================================
158
159 /*
160  * bound: This argument is used when udhcpc moves from an unbound, to
161  * a bound state. All of the paramaters are set in enviromental
162  * variables, The script should configure the interface, and set any
163  * other relavent parameters (default gateway, dns server, etc).
164  */
165 #ifdef HAVE_HEARTBEAT
166 extern void start_heartbeat_boot(void);
167 #endif
168 static int bound(void)
169 {
170         nvram_unset("dhcpc_done");
171         char *wan_ifname = safe_getenv("interface");
172         char *value;
173         char temp_wan_ipaddr[16], temp_wan_netmask[16], temp_wan_gateway[16];
174         int changed = 0;
175
176         if ((value = getenv("ip"))) {
177                 chomp(value);
178                 if (nvram_match("wan_proto", "pptp")
179                     && nvram_match("pptp_use_dhcp", "1"))
180                         strcpy(temp_wan_ipaddr, value);
181                 else {
182                         if (nvram_invmatch("wan_ipaddr", value))
183                                 changed = 1;
184                 }
185                 nvram_set("wan_ipaddr", value);
186         }
187         if ((value = getenv("subnet"))) {
188                 chomp(value);
189                 if (nvram_match("wan_proto", "pptp")
190                     && nvram_match("pptp_use_dhcp", "1"))
191                         strcpy(temp_wan_netmask, value);
192                 else {
193                         if (nvram_invmatch("wan_netmask", value))
194                                 changed = 1;
195                         nvram_set("wan_netmask", value);
196                 }
197         }
198         if ((value = getenv("router"))) {
199                 chomp(value);
200                 if (nvram_invmatch("wan_gateway", value))
201                         changed = 1;
202                 nvram_set("wan_gateway", value);
203         }
204         if ((value = getenv("dns"))) {
205                 chomp(value);
206                 // if (nvram_invmatch("wan_get_dns",value))
207                 // changed=1;
208                 nvram_set("wan_get_dns", value);
209         }
210         /*
211          * Don't care for linksys spec if ((value = getenv("wins")))
212          * nvram_set("wan_wins", value); if ((value = getenv("hostname")))
213          * sethostname(value, strlen(value) + 1);
214          */
215         if ((value = getenv("domain"))) {
216                 chomp(value);
217                 if (nvram_invmatch("wan_get_domain", value))
218                         changed = 1;
219                 nvram_set("wan_get_domain", value);     // HeartBeat need to use
220         }
221         if ((value = getenv("lease"))) {
222                 chomp(value);
223                 nvram_set("wan_lease", value);
224                 expires(atoi(value));
225         }
226         if (!changed) {
227                 cprintf("interface hasnt changed, do nothing\n");
228                 return 0;
229         }
230         stop_firewall();
231         cprintf("configure to IF[%s] , IP[%s], MASK[%s]\n", wan_ifname,
232                 nvram_safe_get("wan_ipaddr"), nvram_safe_get("wan_netmask"));
233
234         if (nvram_match("wan_proto", "pptp")
235             && nvram_match("pptp_use_dhcp", "1"))
236                 {
237                 eval("ifconfig", wan_ifname, temp_wan_ipaddr, "netmask",temp_wan_netmask, "up");
238                 nvram_set("pptp_wan_ipaddr",temp_wan_ipaddr);
239                 }
240         else
241                 eval("ifconfig", wan_ifname, nvram_safe_get("wan_ipaddr"),
242                      "netmask", nvram_safe_get("wan_netmask"), "up");
243
244         /*
245          * We only want to exec bellow functions after dhcp get ip if the
246          * wan_proto is heartbeat
247          */
248 #ifdef HAVE_HEARTBEAT
249         if (nvram_match("wan_proto", "heartbeat")) {
250                 int i = 0;
251
252                 /*
253                  * Delete all default routes
254                  */
255                 while (route_del(wan_ifname, 0, NULL, NULL, NULL) == 0
256                        || i++ < 10) ;
257
258                 /*
259                  * Set default route to gateway if specified
260                  */
261                 route_add(wan_ifname, 0, "0.0.0.0",
262                           nvram_safe_get("wan_gateway"), "0.0.0.0");
263
264                 /*
265                  * save dns to resolv.conf
266                  */
267                 dns_to_resolv();
268                 stop_udhcpd();
269                 start_udhcpd();
270                 start_firewall();
271                 stop_wland();
272                 start_wshaper();
273                 start_wland();
274                 start_heartbeat_boot();
275         }
276 #else
277         if (0) {
278                 // nothing
279         }
280 #endif
281 #ifdef HAVE_PPTP
282         else if (nvram_match("wan_proto", "pptp")
283                  && nvram_match("pptp_use_dhcp", "1")) {
284                 char pptpip[64];
285                 struct dns_lists *dns_list = NULL;
286
287                 dns_to_resolv();
288
289                 dns_list = get_dns_list();
290                 int i = 0;
291
292                 if (dns_list) {
293                         for (i = 0; i < dns_list->num_servers; i++)
294                                 route_add(wan_ifname, 0,
295                                           dns_list->dns_server[i],
296                                           nvram_safe_get("wan_gateway"),
297                                           "255.255.255.255");
298                         free(dns_list);
299                 }
300                 route_add(wan_ifname, 0, "0.0.0.0",
301                           nvram_safe_get("wan_gateway"), "0.0.0.0");
302
303                 nvram_set("wan_gateway_buf", nvram_get("wan_gateway"));
304
305                 getIPFromName(nvram_safe_get("pptp_server_name"), pptpip);
306                 nvram_set("pptp_server_ip", pptpip);
307
308                 // Add the route to the PPTP server on the wan interface for pptp
309                 // client to reach it
310                 if (nvram_match("wan_gateway", "0.0.0.0")
311                     || nvram_match("wan_netmask", "0.0.0.0"))
312                         route_add(wan_ifname, 0,
313                                   nvram_safe_get("pptp_server_ip"),
314                                   nvram_safe_get("wan_gateway"),
315                                   "255.255.255.255");
316                 else
317                         route_add(wan_ifname, 0,
318                                   nvram_safe_get("pptp_server_ip"),
319                                   nvram_safe_get("wan_gateway"),
320                                   nvram_safe_get("wan_netmask"));
321
322         }
323 #endif
324 #ifdef HAVE_L2TP
325         else if (nvram_match("wan_proto", "l2tp")) {
326                 int i = 0;
327
328                 /*
329                  * Delete all default routes
330                  */
331                 while (route_del(wan_ifname, 0, NULL, NULL, NULL) == 0
332                        || i++ < 10) ;
333
334                 /*
335                  * Set default route to gateway if specified
336                  */
337                 route_add(wan_ifname, 0, "0.0.0.0",
338                           nvram_safe_get("wan_gateway"), "0.0.0.0");
339
340                 /*
341                  * Backup the default gateway. It should be used if L2TP connection
342                  * is broken
343                  */
344                 nvram_set("wan_gateway_buf", nvram_get("wan_gateway"));
345
346                 /*
347                  * clear dns from the resolv.conf
348                  */
349                 nvram_set("wan_get_dns", "");
350                 dns_to_resolv();
351                 start_firewall();
352                 start_l2tp_boot();
353         }
354 #endif
355         else {
356                 cprintf("start wan done\n");
357                 start_wan_done(wan_ifname);
358         }
359         nvram_set("dhcpc_done", "1");
360         cprintf("done\n");
361         return 0;
362 }
363
364 /*
365  * renew: This argument is used when a DHCP lease is renewed. All of
366  * the paramaters are set in enviromental variables. This argument is
367  * used when the interface is already configured, so the IP address,
368  * will not change, however, the other DHCP paramaters, such as the
369  * default gateway, subnet mask, and dns server may change.
370  */
371 static int renew(void)
372 {
373         bound();
374
375         cprintf("done\n");
376         return 0;
377 }
378
379 int udhcpc_main(int argc, char **argv)
380 {
381         if (check_action() != ACT_IDLE)
382                 return -1;
383
384         if (!argv[1])
385                 return EINVAL;
386         else if (strstr(argv[1], "deconfig"))
387                 return deconfig();
388         else if (strstr(argv[1], "bound"))
389                 return bound();
390         else if (strstr(argv[1], "renew"))
391                 return renew();
392         else if (strstr(argv[1], "update"))
393                 return update_value();
394         else
395                 return EINVAL;
396 }
397
398 static int bound_tv(void)
399 {
400         char *ifname = safe_getenv("interface");
401         char *ip = safe_getenv("ip");
402         char *net = safe_getenv("subnet");
403         char *cidr = safe_getenv("cidrroute");
404         if (ip && net && ifname) {
405                 char bcast[32];
406                 strcpy(bcast, ip);
407                 get_broadcast(bcast, net);
408                 eval("ifconfig", ifname, ip, "netmask", net, "broadcast", bcast,"multi");
409                 nvram_set("tvnicaddr",ip);
410         }
411         if (cidr && ifname) {
412                 char *callbuffer = malloc(strlen(cidr) + 128);
413                 sprintf(callbuffer,
414                         "export cidrroute=\"%s\";export interface=\"%s\";/etc/cidrroute.sh",
415                         cidr, ifname);
416                 system(callbuffer);
417                 free(callbuffer);
418         }
419         return 0;
420 }
421
422 int udhcpc_tv_main(int argc, char **argv)
423 {
424         if (check_action() != ACT_IDLE)
425                 return -1;
426
427         if (!argv[1])
428                 return EINVAL;
429         else if (strstr(argv[1], "deconfig"))
430                 return 0;
431         else if (strstr(argv[1], "bound"))
432                 return bound_tv();
433         else if (strstr(argv[1], "renew"))
434                 return bound_tv();
435         else if (strstr(argv[1], "update"))
436                 return bound_tv();
437         else
438                 return EINVAL;
439 }
Note: See TracBrowser for help on using the browser.